Browse Source

useEditorSetings

reiji-h 2 years ago
parent
commit
4baaec1ec2

+ 2 - 2
apps/app/src/components/PageEditor/Editor.tsx

@@ -5,7 +5,7 @@ import React, {
   useEffect,
 } from 'react';
 
-import type { IEditorSettings } from '@growi/editor';
+import type { EditorSettings } from '@growi/editor';
 import Dropzone from 'react-dropzone';
 import { useTranslation } from 'react-i18next';
 import {
@@ -36,7 +36,7 @@ export type EditorPropsType = {
   isUploadAllFileAllowed?: boolean,
   onChange?: (newValue: string, isClean?: boolean) => void,
   onUpload?: (file) => void,
-  editorSettings?: IEditorSettings,
+  editorSettings?: EditorSettings,
   indentSize?: number,
   onDragEnter?: (event: any) => void,
   onMarkdownHelpButtonClicked?: () => void,

+ 1 - 4
apps/app/src/components/PageEditor/PageEditor.tsx

@@ -457,10 +457,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
             pageId={pageId ?? undefined}
             initialValue={initialValue}
             onOpenEditor={markdown => setMarkdownToPreview(markdown)}
-            editorTheme={editorSettings?.theme}
-            editorKeymap={editorSettings?.keymapMode}
-            styleActiveLine={editorSettings?.styleActiveLine}
-            autoFormatMarkdownTable={editorSettings?.autoFormatMarkdownTable}
+            editorSettings={editorSettings}
           />
         </div>
         <div ref={previewRef} onScroll={scrollPreviewHandlerThrottle} className="page-editor-preview-container flex-expand-vert d-none d-lg-flex">

+ 2 - 2
apps/app/src/server/models/editor-settings.ts

@@ -1,4 +1,4 @@
-import type { IEditorSettings } from '@growi/editor';
+import type { EditorSettings } from '@growi/editor';
 import type { Model, Document } from 'mongoose';
 import {
   Schema,
@@ -7,7 +7,7 @@ import {
 import { getOrCreateModel } from '../util/mongoose-utils';
 
 
-export interface EditorSettingsDocument extends IEditorSettings, Document {
+export interface EditorSettingsDocument extends EditorSettings, Document {
   userId: Schema.Types.ObjectId,
 }
 export type EditorSettingsModel = Model<EditorSettingsDocument>

+ 4 - 4
apps/app/src/stores/editor.tsx

@@ -2,7 +2,7 @@ import { useCallback } from 'react';
 
 import { type Nullable } from '@growi/core';
 import { withUtils, type SWRResponseWithUtils } from '@growi/core/dist/swr';
-import type { IEditorSettings } from '@growi/editor';
+import type { EditorSettings } from '@growi/editor';
 import useSWR, { type SWRResponse } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 
@@ -29,13 +29,13 @@ export const useEditingMarkdown = (initialData?: string): SWRResponse<string, Er
 
 
 type EditorSettingsOperation = {
-  update: (updateData: Partial<IEditorSettings>) => Promise<void>,
+  update: (updateData: Partial<EditorSettings>) => Promise<void>,
 }
 
 // TODO: Enable localStorageMiddleware
 //   - Unabling localStorageMiddleware occurrs a flickering problem when loading theme.
 //   - see: https://github.com/weseek/growi/pull/6781#discussion_r1000285786
-export const useEditorSettings = (): SWRResponseWithUtils<EditorSettingsOperation, IEditorSettings, Error> => {
+export const useEditorSettings = (): SWRResponseWithUtils<EditorSettingsOperation, EditorSettings, Error> => {
   const { data: currentUser } = useCurrentUser();
   const { data: isGuestUser } = useIsGuestUser();
   const { data: isReadOnlyUser } = useIsReadOnlyUser();
@@ -51,7 +51,7 @@ export const useEditorSettings = (): SWRResponseWithUtils<EditorSettingsOperatio
     },
   );
 
-  return withUtils<EditorSettingsOperation, IEditorSettings, Error>(swrResult, {
+  return withUtils<EditorSettingsOperation, EditorSettings, Error>(swrResult, {
     update: async(updateData) => {
       const { data, mutate } = swrResult;
 

+ 11 - 86
packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.tsx

@@ -1,29 +1,28 @@
 import {
-  forwardRef, useMemo, useRef, useEffect, useState, useCallback,
+  forwardRef, useMemo, useRef, useEffect,
 } from 'react';
 
 import { indentUnit } from '@codemirror/language';
-import { Prec, Extension } from '@codemirror/state';
 import {
-  keymap, type Command, EditorView, highlightActiveLine, highlightActiveLineGutter,
+  EditorView,
 } from '@codemirror/view';
 import { AcceptedUploadFileType } from '@growi/core';
 import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
 
-import { GlobalCodeMirrorEditorKey } from '../../consts';
+import { EditorSettings, GlobalCodeMirrorEditorKey } from '../../consts';
 import {
-  useFileDropzone, FileDropzoneOverlay, getEditorTheme, type EditorTheme, getKeymap, type KeyMapMode,
+  useFileDropzone, FileDropzoneOverlay,
 } from '../../services';
-import { insertNewlineContinueMarkup } from '../../services/list-util/insert-newline-continue-markup';
 import {
   adjustPasteData, getStrFromBol,
 } from '../../services/paste-util/paste-markdown-util';
-import { insertNewRowToMarkdownTable, isInTable } from '../../services/table-util/insert-new-row-to-table-markdown';
 import { useCodeMirrorEditorIsolated } from '../../stores';
 
 import { Toolbar } from './Toolbar';
 
 
+import { useEditorSettings } from 'src/stores/use-editor-settings';
+
 import style from './CodeMirrorEditor.module.scss';
 
 const CodeMirrorEditorContainer = forwardRef<HTMLDivElement>((props, ref) => {
@@ -34,11 +33,8 @@ const CodeMirrorEditorContainer = forwardRef<HTMLDivElement>((props, ref) => {
 
 export type CodeMirrorEditorProps = {
   acceptedUploadFileType?: AcceptedUploadFileType,
-  indentSize?: number,
-  editorTheme?: EditorTheme,
-  editorKeymap?: KeyMapMode,
-  styleActiveLine?: boolean,
-  autoFormatMarkdownTable?: boolean,
+  indentSize: number,
+  editorSettings?: EditorSettings,
   onChange?: (value: string) => void,
   onSave?: () => void,
   onUpload?: (files: File[]) => void,
@@ -54,10 +50,7 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
     editorKey,
     acceptedUploadFileType = AcceptedUploadFileType.NONE,
     indentSize,
-    editorTheme,
-    editorKeymap,
-    styleActiveLine,
-    autoFormatMarkdownTable,
+    editorSettings,
     onChange,
     onSave,
     onUpload,
@@ -73,6 +66,8 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
   }, [onChange]);
   const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(editorKey, containerRef.current, cmProps);
 
+  useEditorSettings(codeMirrorEditor, editorSettings, onSave);
+
   useEffect(() => {
     if (indentSize == null) {
       return;
@@ -84,37 +79,6 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
 
   }, [codeMirrorEditor, indentSize]);
 
-  useEffect(() => {
-    if (styleActiveLine == null) {
-      return;
-    }
-    const extensions = (styleActiveLine) ? [[highlightActiveLine(), highlightActiveLineGutter()]] : [[]];
-
-    const cleanupFunction = codeMirrorEditor?.appendExtensions?.(extensions);
-    return cleanupFunction;
-
-  }, [codeMirrorEditor, styleActiveLine]);
-
-  const onPressEnter: Command = useCallback((editor) => {
-    if (isInTable(editor) && autoFormatMarkdownTable) {
-      insertNewRowToMarkdownTable(editor);
-      return true;
-    }
-    insertNewlineContinueMarkup(editor);
-    return true;
-  }, [autoFormatMarkdownTable]);
-
-
-  useEffect(() => {
-
-    const extension = keymap.of([
-      { key: 'Enter', run: onPressEnter },
-    ]);
-
-    const cleanupFunction = codeMirrorEditor?.appendExtensions?.(extension);
-    return cleanupFunction;
-
-  }, [codeMirrorEditor, onPressEnter]);
 
   useEffect(() => {
     const handlePaste = (event: ClipboardEvent) => {
@@ -190,45 +154,6 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
   }, [onScroll, codeMirrorEditor]);
 
 
-  const [themeExtension, setThemeExtension] = useState<Extension | undefined>(undefined);
-  useEffect(() => {
-    const settingTheme = async(name?: EditorTheme) => {
-      setThemeExtension(await getEditorTheme(name ?? 'defaultlight'));
-    };
-    settingTheme(editorTheme);
-  }, [codeMirrorEditor, editorTheme, setThemeExtension]);
-
-  useEffect(() => {
-    if (themeExtension == null) {
-      return;
-    }
-    // React CodeMirror has default theme which is default prec
-    // and extension have to be higher prec here than default theme.
-    const cleanupFunction = codeMirrorEditor?.appendExtensions(Prec.high(themeExtension));
-    return cleanupFunction;
-  }, [codeMirrorEditor, themeExtension]);
-
-
-  const [keymapExtension, setKeymapExtension] = useState<Extension | undefined>(undefined);
-  useEffect(() => {
-    const settingKeyMap = async(name?: KeyMapMode) => {
-      setKeymapExtension(await getKeymap(name ?? 'default'));
-    };
-    settingKeyMap(editorKeymap);
-
-  }, [codeMirrorEditor, editorKeymap, setKeymapExtension]);
-
-  useEffect(() => {
-    if (keymapExtension == null) {
-      return;
-    }
-
-    // Prevent these Keybind from overwriting the originally defined keymap.
-    const cleanupFunction = codeMirrorEditor?.appendExtensions(Prec.low(keymapExtension));
-    return cleanupFunction;
-
-  }, [codeMirrorEditor, keymapExtension, onSave]);
-
   const {
     getRootProps,
     getInputProps,

+ 1 - 1
packages/editor/src/consts/editor-settings.ts

@@ -1,6 +1,6 @@
 import { EditorTheme, KeyMapMode } from '../services';
 
-export interface IEditorSettings {
+export interface EditorSettings {
   theme: undefined | EditorTheme,
   keymapMode: undefined | KeyMapMode,
   styleActiveLine: boolean,

+ 91 - 0
packages/editor/src/stores/use-editor-settings.ts

@@ -0,0 +1,91 @@
+import { useEffect, useCallback, useState } from 'react';
+
+import { Prec, Extension } from '@codemirror/state';
+import {
+  keymap, type Command, highlightActiveLine, highlightActiveLineGutter,
+} from '@codemirror/view';
+
+import type { EditorSettings } from '../consts';
+import type { UseCodeMirrorEditor, EditorTheme, KeyMapMode } from '../services';
+import { getEditorTheme, getKeymap } from '../services';
+import { insertNewlineContinueMarkup } from '../services/list-util/insert-newline-continue-markup';
+import { insertNewRowToMarkdownTable, isInTable } from '../services/table-util/insert-new-row-to-table-markdown';
+
+export const useEditorSettings = (
+    codeMirrorEditor?: UseCodeMirrorEditor,
+    editorSetings?: EditorSettings,
+    onSave?: () => void,
+): void => {
+
+  useEffect(() => {
+    if (editorSetings?.styleActiveLine == null) {
+      return;
+    }
+    const extensions = (editorSetings?.styleActiveLine) ? [[highlightActiveLine(), highlightActiveLineGutter()]] : [[]];
+
+    const cleanupFunction = codeMirrorEditor?.appendExtensions?.(extensions);
+    return cleanupFunction;
+
+  }, [codeMirrorEditor, editorSetings?.styleActiveLine]);
+
+  const onPressEnter: Command = useCallback((editor) => {
+    if (isInTable(editor) && editorSetings?.autoFormatMarkdownTable) {
+      insertNewRowToMarkdownTable(editor);
+      return true;
+    }
+    insertNewlineContinueMarkup(editor);
+    return true;
+  }, [editorSetings?.autoFormatMarkdownTable]);
+
+
+  useEffect(() => {
+
+    const extension = keymap.of([
+      { key: 'Enter', run: onPressEnter },
+    ]);
+
+    const cleanupFunction = codeMirrorEditor?.appendExtensions?.(extension);
+    return cleanupFunction;
+
+  }, [codeMirrorEditor, onPressEnter]);
+
+  const [themeExtension, setThemeExtension] = useState<Extension | undefined>(undefined);
+  useEffect(() => {
+    const settingTheme = async(name?: EditorTheme) => {
+      setThemeExtension(await getEditorTheme(name));
+    };
+    settingTheme(editorSetings?.theme);
+  }, [codeMirrorEditor, editorSetings?.theme, setThemeExtension]);
+
+  useEffect(() => {
+    if (themeExtension == null) {
+      return;
+    }
+    // React CodeMirror has default theme which is default prec
+    // and extension have to be higher prec here than default theme.
+    const cleanupFunction = codeMirrorEditor?.appendExtensions(Prec.high(themeExtension));
+    return cleanupFunction;
+  }, [codeMirrorEditor, themeExtension]);
+
+
+  const [keymapExtension, setKeymapExtension] = useState<Extension | undefined>(undefined);
+  useEffect(() => {
+    const settingKeyMap = async(name?: KeyMapMode) => {
+      setKeymapExtension(await getKeymap(name, onSave));
+    };
+    settingKeyMap(editorSetings?.keymapMode);
+
+  }, [codeMirrorEditor, editorSetings?.keymapMode, setKeymapExtension, onSave]);
+
+  useEffect(() => {
+    if (keymapExtension == null) {
+      return;
+    }
+
+    // Prevent these Keybind from overwriting the originally defined keymap.
+    const cleanupFunction = codeMirrorEditor?.appendExtensions(Prec.low(keymapExtension));
+    return cleanupFunction;
+
+  }, [codeMirrorEditor, keymapExtension]);
+
+};