diff --git a/frontend/src/components/editor/Editor.tsx b/frontend/src/components/editor/Editor.tsx index 2682c81e..c291a26d 100644 --- a/frontend/src/components/editor/Editor.tsx +++ b/frontend/src/components/editor/Editor.tsx @@ -1,6 +1,6 @@ import { markdown } from "@codemirror/lang-markdown"; import { EditorState } from "@codemirror/state"; -import { keymap, ViewUpdate } from "@codemirror/view"; +import { keymap } from "@codemirror/view"; import { xcodeDark, xcodeLight } from "@uiw/codemirror-theme-xcode"; import { basicSetup, EditorView } from "codemirror"; import { useCallback, useEffect, useState } from "react"; @@ -8,7 +8,8 @@ import { useDispatch, useSelector } from "react-redux"; import { ScrollSyncPane } from "react-scroll-sync"; import { useCreateUploadUrlMutation, useUploadFileMutation } from "../../hooks/api/file"; import { useCurrentTheme } from "../../hooks/useCurrentTheme"; -import { FormatType, ToolBarState, useFormatUtils } from "../../hooks/useFormatUtils"; +import { useFormatUtils } from "../../hooks/useFormatUtils"; +import { useToolBar } from "../../hooks/useToolBar"; import { selectEditor, setCmView } from "../../store/editorSlice"; import { selectSetting } from "../../store/settingSlice"; import { selectWorkspace } from "../../store/workspaceSlice"; @@ -26,77 +27,15 @@ function Editor() { const workspaceStore = useSelector(selectWorkspace); const { mutateAsync: createUploadUrl } = useCreateUploadUrlMutation(); const { mutateAsync: uploadFile } = useUploadFileMutation(); - - const [toolBarState, setToolBarState] = useState({ - show: false, - position: { top: 0, left: 0 }, - selectedFormats: new Set(), - }); - - const { getFormatMarkerLength, applyFormat, setKeymapConfig } = useFormatUtils(); + const { applyFormat, setKeymapConfig } = useFormatUtils(); + const { toolBarState, setToolBarState, updateFormatBar } = useToolBar(); const ref = useCallback((node: HTMLElement | null) => { if (!node) return; setElement(node); }, []); - const updateFormatBar = useCallback( - (update: ViewUpdate) => { - const selection = update.state.selection.main; - if (!selection.empty) { - const coords = update.view.coordsAtPos(selection.from); - if (coords) { - const maxLength = getFormatMarkerLength(update.view.state, selection.from); - - const selectedTextStart = update.state.sliceDoc( - selection.from - maxLength, - selection.from - ); - const selectedTextEnd = update.state.sliceDoc( - selection.to, - selection.to + maxLength - ); - const formats = new Set(); - - const checkAndAddFormat = (marker: string, format: FormatType) => { - if ( - selectedTextStart.includes(marker) && - selectedTextEnd.includes(marker) - ) { - formats.add(format); - } - }; - - checkAndAddFormat("**", FormatType.BOLD); - checkAndAddFormat("_", FormatType.ITALIC); - checkAndAddFormat("`", FormatType.CODE); - checkAndAddFormat("~~", FormatType.STRIKETHROUGH); - - // TODO: Modify the rendering method so that it is not affected by the size of the Toolbar - setToolBarState((prev) => ({ - ...prev, - show: true, - position: { - top: coords.top - 5, - left: coords.left, - }, - selectedFormats: formats, - })); - } - } else { - setToolBarState((prev) => ({ - ...prev, - show: false, - selectedFormats: new Set(), - })); - } - }, - [getFormatMarkerLength] - ); - useEffect(() => { - let view: EditorView | undefined = undefined; - if ( !element || !editorStore.doc || @@ -126,28 +65,23 @@ function Editor() { keymap.of(setKeymapConfig()), basicSetup, markdown(), - yorkieCodeMirror(editorStore.doc, editorStore.client), themeMode == "light" ? xcodeLight : xcodeDark, - EditorView.theme({ - "&": { width: "100%" }, - }), + EditorView.theme({ "&": { width: "100%" } }), EditorView.lineWrapping, - intelligencePivot, - ...(settingStore.fileUpload.enable - ? [imageUploader(handleUploadImage, editorStore.doc)] - : []), EditorView.updateListener.of((update) => { if (update.selectionSet) { updateFormatBar(update); } }), + yorkieCodeMirror(editorStore.doc, editorStore.client), + intelligencePivot, + ...(settingStore.fileUpload.enable + ? [imageUploader(handleUploadImage, editorStore.doc)] + : []), ], }); - view = new EditorView({ - state, - parent: element, - }); + const view = new EditorView({ state, parent: element }); dispatch(setCmView(view)); @@ -155,15 +89,15 @@ function Editor() { view?.destroy(); }; }, [ - dispatch, + element, editorStore.client, editorStore.doc, - element, themeMode, workspaceStore.data, + settingStore.fileUpload?.enable, + dispatch, createUploadUrl, uploadFile, - settingStore.fileUpload?.enable, applyFormat, updateFormatBar, setKeymapConfig, diff --git a/frontend/src/hooks/useToolBar.ts b/frontend/src/hooks/useToolBar.ts new file mode 100644 index 00000000..f1023e74 --- /dev/null +++ b/frontend/src/hooks/useToolBar.ts @@ -0,0 +1,68 @@ +import { useCallback, useState } from "react"; +import { FormatType, ToolBarState, useFormatUtils } from "./useFormatUtils"; +import { ViewUpdate } from "@codemirror/view"; + +export const useToolBar = () => { + const [toolBarState, setToolBarState] = useState({ + show: false, + position: { top: 0, left: 0 }, + selectedFormats: new Set(), + }); + const { getFormatMarkerLength } = useFormatUtils(); + + const updateFormatBar = useCallback( + (update: ViewUpdate) => { + const selection = update.state.selection.main; + if (!selection.empty) { + const coords = update.view.coordsAtPos(selection.from); + if (coords) { + const maxLength = getFormatMarkerLength(update.view.state, selection.from); + + const selectedTextStart = update.state.sliceDoc( + selection.from - maxLength, + selection.from + ); + const selectedTextEnd = update.state.sliceDoc( + selection.to, + selection.to + maxLength + ); + const formats = new Set(); + + const checkAndAddFormat = (marker: string, format: FormatType) => { + if ( + selectedTextStart.includes(marker) && + selectedTextEnd.includes(marker) + ) { + formats.add(format); + } + }; + + checkAndAddFormat("**", FormatType.BOLD); + checkAndAddFormat("_", FormatType.ITALIC); + checkAndAddFormat("`", FormatType.CODE); + checkAndAddFormat("~~", FormatType.STRIKETHROUGH); + + // TODO: Modify the rendering method so that it is not affected by the size of the Toolbar + setToolBarState((prev) => ({ + ...prev, + show: true, + position: { + top: coords.top - 5, + left: coords.left, + }, + selectedFormats: formats, + })); + } + } else { + setToolBarState((prev) => ({ + ...prev, + show: false, + selectedFormats: new Set(), + })); + } + }, + [getFormatMarkerLength] + ); + + return { toolBarState, setToolBarState, updateFormatBar }; +};