diff --git a/frontend/src/components/editor/DocumentView.tsx b/frontend/src/components/editor/DocumentView.tsx index 1209458c..de756adc 100644 --- a/frontend/src/components/editor/DocumentView.tsx +++ b/frontend/src/components/editor/DocumentView.tsx @@ -6,10 +6,12 @@ import { ScrollSync, ScrollSyncPane } from "react-scroll-sync"; import { EditorModeType, selectEditor } from "../../store/editorSlice"; import Editor from "./Editor"; import Preview from "./Preview"; +import { selectConfig } from "../../store/configSlice"; function DocumentView() { const editorStore = useSelector(selectEditor); const windowWidth = useWindowWidth(); + const configStore = useSelector(selectConfig); if (!editorStore.doc || !editorStore.client) return ( @@ -23,7 +25,7 @@ function DocumentView() { {editorStore.mode === EditorModeType.BOTH && ( {({ position: width, separatorProps }) => ( - +
{ diff --git a/frontend/src/components/headers/DocumentHeader.tsx b/frontend/src/components/headers/DocumentHeader.tsx index 1575ffdf..e6a4374f 100644 --- a/frontend/src/components/headers/DocumentHeader.tsx +++ b/frontend/src/components/headers/DocumentHeader.tsx @@ -14,7 +14,7 @@ import { Grid2 as Grid, Typography, } from "@mui/material"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { useUserPresence } from "../../hooks/useUserPresence"; @@ -23,11 +23,12 @@ import { selectWorkspace } from "../../store/workspaceSlice"; import { ShareRole } from "../../utils/share"; import DownloadMenu from "../common/DownloadMenu"; import ShareButton from "../common/ShareButton"; -import ThemeButton from "../common/ThemeButton"; import UserPresenceList from "./UserPresenceList"; import { selectDocument } from "../../store/documentSlice"; import { useUpdateDocumentTitleMutation } from "../../hooks/api/workspaceDocument"; import { useSnackbar } from "notistack"; +import DocumentPopover from "../popovers/DocumentPopover"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; function DocumentHeader() { const dispatch = useDispatch(); @@ -42,6 +43,7 @@ function DocumentHeader() { ); const isEditingDisabled = Boolean(editorState.shareRole); const { enqueueSnackbar } = useSnackbar(); + const [moreButtonanchorEl, setMoreButtonAnchorEl] = useState(null); useEffect(() => { if (editorState.shareRole === ShareRole.READ) { @@ -83,6 +85,14 @@ function DocumentHeader() { enqueueSnackbar("The title is changed successfully", { variant: "success" }); }; + const handleMoreButtonClick: React.MouseEventHandler = (e) => { + setMoreButtonAnchorEl(e.currentTarget); + }; + + const handleDocumentMenuClose = () => { + setMoreButtonAnchorEl(null); + }; + return ( @@ -148,7 +158,14 @@ function DocumentHeader() { {!editorState.shareRole && } - + + + + diff --git a/frontend/src/components/popovers/DocumentPopover.tsx b/frontend/src/components/popovers/DocumentPopover.tsx new file mode 100644 index 00000000..bb1fc562 --- /dev/null +++ b/frontend/src/components/popovers/DocumentPopover.tsx @@ -0,0 +1,64 @@ +import { + ListItemIcon, + ListItemText, + MenuItem, + MenuList, + Popover, + PopoverProps, +} from "@mui/material"; +import { useDispatch, useSelector } from "react-redux"; +import { selectConfig, setDisableScrollSync, setTheme, ThemeType } from "../../store/configSlice"; +import { useCurrentTheme } from "../../hooks/useCurrentTheme"; +import DarkModeIcon from "@mui/icons-material/DarkMode"; +import LightModeIcon from "@mui/icons-material/LightMode"; +import ToggleOnIcon from "@mui/icons-material/ToggleOn"; +import ToggleOffIcon from "@mui/icons-material/ToggleOff"; + +function DocumentPopover(props: PopoverProps) { + const dispatch = useDispatch(); + const themeMode = useCurrentTheme(); + const configStore = useSelector(selectConfig); + + const handleChangeTheme = () => { + dispatch(setTheme(themeMode === ThemeType.LIGHT ? ThemeType.DARK : ThemeType.LIGHT)); + }; + + const handleScrollSyncChange = () => { + dispatch(setDisableScrollSync(!configStore.disableScrollSync)); + }; + + return ( + + + + + {themeMode === "light" ? : } + + Appearance + + + + {configStore.disableScrollSync ? ( + + ) : ( + + )} + + Panel Scroll Sync + + + + ); +} + +export default DocumentPopover; diff --git a/frontend/src/components/popovers/ProfilePopover.tsx b/frontend/src/components/popovers/ProfilePopover.tsx index 566f7981..f8c29583 100644 --- a/frontend/src/components/popovers/ProfilePopover.tsx +++ b/frontend/src/components/popovers/ProfilePopover.tsx @@ -32,7 +32,7 @@ function ProfilePopover(props: PopoverProps) { }; const handleChangeTheme = () => { - dispatch(setTheme(themeMode == ThemeType.LIGHT ? ThemeType.DARK : ThemeType.LIGHT)); + dispatch(setTheme(themeMode === ThemeType.LIGHT ? ThemeType.DARK : ThemeType.LIGHT)); }; return ( diff --git a/frontend/src/store/configSlice.ts b/frontend/src/store/configSlice.ts index f4f40a09..8f8c67a1 100644 --- a/frontend/src/store/configSlice.ts +++ b/frontend/src/store/configSlice.ts @@ -17,12 +17,14 @@ export interface ConfigState { theme: ThemeType; drawerOpen: boolean; codeKey: CodeKeyType; + disableScrollSync: boolean; } const initialState: ConfigState = { theme: ThemeType.DEFAULT, drawerOpen: true, codeKey: CodeKeyType.SUBLIME, + disableScrollSync: false, }; export const configSlice = createSlice({ @@ -38,10 +40,14 @@ export const configSlice = createSlice({ setCodeKeyType: (state, action: PayloadAction) => { state.codeKey = action.payload; }, + setDisableScrollSync: (state, action: PayloadAction) => { + state.disableScrollSync = action.payload; + }, }, }); -export const { setTheme, setDrawerOpen, setCodeKeyType } = configSlice.actions; +export const { setTheme, setDrawerOpen, setCodeKeyType, setDisableScrollSync } = + configSlice.actions; export const selectConfig = (state: RootState) => state.config;