Explorar o código

set handler to save with shortcut key

Yuki Takei %!s(int64=2) %!d(string=hai) anos
pai
achega
f5cac5b1a6

+ 23 - 16
apps/app/src/components/PageEditor/PageEditor.tsx

@@ -5,7 +5,8 @@ import React, {
 import EventEmitter from 'events';
 import nodePath from 'path';
 
-
+import { Compartment } from '@codemirror/state';
+import { keymap } from '@codemirror/view';
 import type { IPageHasId } from '@growi/core';
 import { pathUtils } from '@growi/core/dist/utils';
 import { CodeMirrorEditorContainer, useCodeMirrorEditorMain } from '@growi/editor';
@@ -117,7 +118,9 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
 
   const { data: codemirrorEditor } = useCodeMirrorEditorMain(codeMirrorEditorContainerRef.current);
   const {
-    initDoc, getDoc, focus: focusToEditor, setCaretLine,
+    appendExtension,
+    initDoc, getDoc,
+    focus: focusToEditor, setCaretLine,
   } = codemirrorEditor ?? {};
 
   const { data: rendererOptions } = usePreviewOptions();
@@ -256,10 +259,6 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
   ]);
 
   const saveAndReturnToViewHandler = useCallback(async(opts: {slackChannels: string, overwriteScopesOfDescendants?: boolean}) => {
-    if (editorMode !== EditorMode.Editor) {
-      return;
-    }
-
     const page = await save(opts);
     if (page == null) {
       return;
@@ -272,13 +271,9 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
       updateStateAfterSave?.();
     }
     mutateEditorMode(EditorMode.View);
-  }, [editorMode, save, isNotFound, mutateEditorMode, router, updateStateAfterSave]);
+  }, [save, isNotFound, mutateEditorMode, router, updateStateAfterSave]);
 
   const saveWithShortcut = useCallback(async() => {
-    if (editorMode !== EditorMode.Editor) {
-      return;
-    }
-
     const page = await save();
     if (page == null) {
       return;
@@ -293,7 +288,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
     toastSuccess(t('toaster.save_succeeded'));
     mutateEditorMode(EditorMode.Editor);
 
-  }, [editorMode, isNotFound, mutateEditorMode, router, save, t, updateStateAfterSave]);
+  }, [isNotFound, mutateEditorMode, router, save, t, updateStateAfterSave]);
 
 
   /**
@@ -514,10 +509,22 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
 
   // set handler to save with shortcut key
   useEffect(() => {
-    // TODO impl
-    return function cleanup() {
-    };
-  }, []);
+    const compartment = new Compartment();
+    const extension = keymap.of([
+      {
+        key: 'Mod-s',
+        preventDefault: true,
+        run: () => {
+          saveWithShortcut();
+          return false;
+        },
+      },
+    ]);
+
+    const cleanupFunction = appendExtension?.(extension, compartment);
+
+    return cleanupFunction;
+  }, [appendExtension, saveWithShortcut]);
 
   // set handler to focus
   useLayoutEffect(() => {

+ 19 - 4
packages/editor/src/services/codemirror-editor/use-codemirror-editor.ts

@@ -3,7 +3,7 @@ import { useCallback, useEffect } from 'react';
 import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
 import { languages } from '@codemirror/language-data';
 import {
-  EditorState, StateEffect, type EditorStateConfig, type Extension,
+  EditorState, StateEffect, type EditorStateConfig, type Extension, Compartment,
 } from '@codemirror/state';
 import { basicSetup, useCodeMirror, type UseCodeMirror } from '@uiw/react-codemirror';
 
@@ -14,7 +14,7 @@ export type UseCodeMirrorEditor = UseCodeMirror;
 type UseCodeMirrorEditorUtils = {
   initState: (config?: EditorStateConfig) => void,
   initDoc: (doc?: string) => void,
-  appendExtension: (extension: Extension) => void,
+  appendExtension: (extension: Extension, compartment?: Compartment) => CleanupFunction | undefined,
   getDoc: () => string | undefined,
   focus: () => void,
   setCaretLine: (lineNumber?: number) => void,
@@ -22,6 +22,8 @@ type UseCodeMirrorEditorUtils = {
 
 export type UseCodeMirrorEditorResponse = UseCodeMirrorEditorStates & UseCodeMirrorEditorUtils;
 
+type CleanupFunction = () => void;
+
 const defaultExtensions: Extension[] = [
   markdown({ base: markdownLanguage, codeLanguages: languages }),
 ];
@@ -66,10 +68,23 @@ export const useCodeMirrorEditor = (props?: UseCodeMirrorEditor): UseCodeMirrorE
   }, [initState]);
 
   // implement appendExtension method
-  const appendExtension = useCallback((extension: Extension): void => {
+  const appendExtension = useCallback((extension: Extension, compartment?: Compartment): CleanupFunction | undefined => {
     view?.dispatch({
-      effects: StateEffect.appendConfig.of(extension),
+      effects: StateEffect.appendConfig.of(
+        compartment != null
+          ? compartment.of(extension)
+          : extension,
+      ),
     });
+
+    return compartment != null
+      // return cleanup function
+      ? () => {
+        view?.dispatch({
+          effects: compartment?.reconfigure([]),
+        });
+      }
+      : undefined;
   }, [view]);
 
   // implement getDoc method