Browse Source

refactor setCaretLine and focusToEditor

Yuki Takei 3 years ago
parent
commit
46d7013000

+ 2 - 32
packages/app/src/client/legacy/crowi.js

@@ -12,38 +12,8 @@ if (!window) {
 }
 }
 window.Crowi = Crowi;
 window.Crowi = Crowi;
 
 
-/**
- * set 'data-caret-line' attribute that will be processed when 'shown.bs.tab' event fired
- * @param {number} line
- */
-Crowi.setCaretLineData = function(line) {
-  const { appContainer } = window;
-  const pageEditorDom = document.querySelector('#page-editor');
-  pageEditorDom.setAttribute('data-caret-line', line);
-};
-
-/**
- * invoked when;
- *
- * 1. 'shown.bs.tab' event fired
- */
-Crowi.setCaretLineAndFocusToEditor = function() {
-  // get 'data-caret-line' attributes
-  const pageEditorDom = document.querySelector('#page-editor');
-
-  if (pageEditorDom == null) {
-    return;
-  }
-
-  const { appContainer } = window;
-  const editorContainer = appContainer.getContainer('EditorContainer');
-  const line = pageEditorDom.getAttribute('data-caret-line') || 0;
-  editorContainer.setCaretLine(+line);
-  // reset data-caret-line attribute
-  pageEditorDom.removeAttribute('data-caret-line');
-
-  // focus
-  editorContainer.focusToEditor();
+Crowi.setCaretLine = function(line) {
+  window.globalEmitter.emit('setCaretLine', line);
 };
 };
 
 
 // original: middleware.swigFilter
 // original: middleware.swigFilter

+ 0 - 14
packages/app/src/client/services/EditorContainer.js

@@ -59,20 +59,6 @@ export default class EditorContainer extends Container {
     }
     }
   }
   }
 
 
-  setCaretLine(line) {
-    const pageEditor = this.appContainer.getComponentInstance('PageEditor');
-    if (pageEditor != null) {
-      pageEditor.setCaretLine(line);
-    }
-  }
-
-  focusToEditor() {
-    const pageEditor = this.appContainer.getComponentInstance('PageEditor');
-    if (pageEditor != null) {
-      pageEditor.focusToEditor();
-    }
-  }
-
   getCurrentOptionsToSave() {
   getCurrentOptionsToSave() {
     const opt = {
     const opt = {
       pageTags: this.state.tags,
       pageTags: this.state.tags,

+ 1 - 1
packages/app/src/client/util/markdown-it/header-with-edit-link.js

@@ -7,7 +7,7 @@ export default class HeaderWithEditLinkConfigurer {
   configure(md) {
   configure(md) {
     md.renderer.rules.heading_close = (tokens, idx) => {
     md.renderer.rules.heading_close = (tokens, idx) => {
       return `<span class="revision-head-edit-button">
       return `<span class="revision-head-edit-button">
-                <a href="#edit" onClick="Crowi.setCaretLineData(parseInt(this.parentNode.parentNode.dataset.line, 10))">
+                <a href="#edit" onClick="Crowi.setCaretLine(parseInt(this.parentNode.parentNode.dataset.line, 10))">
                   <i class="icon-note"></i>
                   <i class="icon-note"></i>
                 </a>
                 </a>
               </span></${tokens[idx].tag}>`;
               </span></${tokens[idx].tag}>`;

+ 30 - 3
packages/app/src/components/PageEditor.jsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect, useRef } from 'react';
 
 
 import { envUtils } from '@growi/core';
 import { envUtils } from '@growi/core';
 import detectIndent from 'detect-indent';
 import detectIndent from 'detect-indent';
@@ -13,6 +13,7 @@ import { getOptionsToSave } from '~/client/util/editor';
 import { useIsEditable, useIsIndentSizeForced, useSlackChannels } from '~/stores/context';
 import { useIsEditable, useIsIndentSizeForced, useSlackChannels } from '~/stores/context';
 import { useCurrentIndentSize, useIsSlackEnabled, useIsTextlintEnabled } from '~/stores/editor';
 import { useCurrentIndentSize, useIsSlackEnabled, useIsTextlintEnabled } from '~/stores/editor';
 import {
 import {
+  EditorMode,
   useEditorMode, useIsMobile, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
   useEditorMode, useIsMobile, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
 } from '~/stores/ui';
 } from '~/stores/ui';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
@@ -96,7 +97,9 @@ class PageEditor extends React.Component {
   }
   }
 
 
   focusToEditor() {
   focusToEditor() {
-    this.editor.forceToFocus();
+    if (this.editor != null) {
+      this.editor.forceToFocus();
+    }
   }
   }
 
 
   /**
   /**
@@ -298,7 +301,7 @@ class PageEditor extends React.Component {
    * @param {number} offset
    * @param {number} offset
    */
    */
   scrollEditorByPreviewScroll(offset) {
   scrollEditorByPreviewScroll(offset) {
-    if (this.previewElement == null) {
+    if (this.editor == null || this.previewElement == null) {
       return;
       return;
     }
     }
 
 
@@ -412,6 +415,29 @@ const PageEditorWrapper = (props) => {
   const { data: isIndentSizeForced } = useIsIndentSizeForced();
   const { data: isIndentSizeForced } = useIsIndentSizeForced();
   const { data: indentSize, mutate: mutateCurrentIndentSize } = useCurrentIndentSize();
   const { data: indentSize, mutate: mutateCurrentIndentSize } = useCurrentIndentSize();
 
 
+  const pageEditorRef = useRef(null);
+
+  // set handler to set caret line
+  useEffect(() => {
+    const handler = (line) => {
+      if (pageEditorRef.current != null) {
+        pageEditorRef.current.setCaretLine(line);
+      }
+    };
+    window.globalEmitter.on('setCaretLine', handler);
+
+    return function cleanup() {
+      window.globalEmitter.removeListener('setCaretLine', handler);
+    };
+  }, []);
+
+  // set handler to focus
+  useEffect(() => {
+    if (pageEditorRef.current != null && editorMode === EditorMode.Editor) {
+      pageEditorRef.current.focusToEditor();
+    }
+  }, [editorMode]);
+
   if (isEditable == null || editorMode == null) {
   if (isEditable == null || editorMode == null) {
     return null;
     return null;
   }
   }
@@ -419,6 +445,7 @@ const PageEditorWrapper = (props) => {
   return (
   return (
     <PageEditorHOCWrapper
     <PageEditorHOCWrapper
       {...props}
       {...props}
+      ref={pageEditorRef}
       isEditable={isEditable}
       isEditable={isEditable}
       editorMode={editorMode}
       editorMode={editorMode}
       isMobile={isMobile}
       isMobile={isMobile}