Просмотр исходного кода

implement useCurrentIndentSize

Yuki Takei 3 лет назад
Родитель
Сommit
d117f78222

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

@@ -17,17 +17,8 @@ export default class EditorContainer extends Container {
     this.appContainer = appContainer;
     this.appContainer.registerContainer(this);
 
-    const mainContent = document.querySelector('#content-main');
-
-    if (mainContent == null) {
-      logger.debug('#content-main element is not exists');
-      return;
-    }
-
     this.state = {
       tags: null,
-
-      indentSize: this.appContainer.config.adminPreferredIndentSize || 4,
     };
 
     this.isSetBeforeunloadEventHandler = false;

+ 32 - 22
packages/app/src/components/PageEditor.jsx

@@ -10,8 +10,8 @@ import EditorContainer from '~/client/services/EditorContainer';
 import PageContainer from '~/client/services/PageContainer';
 import { apiGet, apiPost } from '~/client/util/apiv1-client';
 import { getOptionsToSave } from '~/client/util/editor';
-import { useIsEditable, useSlackChannels } from '~/stores/context';
-import { useIsSlackEnabled } from '~/stores/editor';
+import { useIsEditable, useIsIndentSizeForced, useSlackChannels } from '~/stores/context';
+import { useCurrentIndentSize, useIsSlackEnabled } from '~/stores/editor';
 import {
   useEditorMode, useIsMobile, useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
 } from '~/stores/ui';
@@ -75,10 +75,10 @@ class PageEditor extends React.Component {
 
     // Detect indent size from contents (only when users are allowed to change it)
     // TODO: https://youtrack.weseek.co.jp/issue/GW-5368
-    if (!this.props.appContainer.config.isIndentSizeForced && this.state.markdown) {
+    if (!props.isIndentSizeForced && this.state.markdown) {
       const detectedIndent = detectIndent(this.state.markdown);
       if (detectedIndent.type === 'space' && new Set([2, 4]).has(detectedIndent.amount)) {
-        this.props.editorContainer.setState({ indentSize: detectedIndent.amount });
+        props.mutateCurrentIndentSize(detectedIndent.amount);
       }
     }
   }
@@ -340,6 +340,7 @@ class PageEditor extends React.Component {
             isMobile={this.props.isMobile}
             isUploadable={this.state.isUploadable}
             isUploadableFile={this.state.isUploadableFile}
+            indentSize={this.props.indentSize}
             onScroll={this.onEditorScroll}
             onScrollCursorIntoView={this.onEditorScrollCursorIntoView}
             onChange={this.onMarkdownChanged}
@@ -370,6 +371,27 @@ class PageEditor extends React.Component {
 
 }
 
+PageEditor.propTypes = {
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
+  editorContainer: PropTypes.instanceOf(EditorContainer).isRequired,
+
+  isEditable: PropTypes.bool.isRequired,
+
+  // TODO: remove this when omitting unstated is completed
+  editorMode: PropTypes.string.isRequired,
+  isMobile: PropTypes.bool,
+  isSlackEnabled: PropTypes.bool.isRequired,
+  slackChannels: PropTypes.string.isRequired,
+  grant: PropTypes.number.isRequired,
+  grantGroupId: PropTypes.string,
+  grantGroupName: PropTypes.string,
+  mutateGrant: PropTypes.func,
+  isIndentSizeForced: PropTypes.bool,
+  indentSize: PropTypes.number,
+  mutateCurrentIndentSize: PropTypes.func,
+};
+
 /**
  * Wrapper component for using unstated
  */
@@ -384,6 +406,8 @@ const PageEditorWrapper = (props) => {
   const { data: grant, mutate: mutateGrant } = useSelectedGrant();
   const { data: grantGroupId } = useSelectedGrantGroupId();
   const { data: grantGroupName } = useSelectedGrantGroupName();
+  const { data: isIndentSizeForced } = useIsIndentSizeForced();
+  const { data: indentSize, mutate: mutateCurrentIndentSize } = useCurrentIndentSize();
 
   if (isEditable == null || editorMode == null) {
     return null;
@@ -401,26 +425,12 @@ const PageEditorWrapper = (props) => {
       grantGroupId={grantGroupId}
       grantGroupName={grantGroupName}
       mutateGrant={mutateGrant}
+      isIndentSizeForced={isIndentSizeForced}
+      indentSize={indentSize}
+      mutateCurrentIndentSize={mutateCurrentIndentSize}
+
     />
   );
 };
 
-PageEditor.propTypes = {
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-  pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
-  editorContainer: PropTypes.instanceOf(EditorContainer).isRequired,
-
-  isEditable: PropTypes.bool.isRequired,
-
-  // TODO: remove this when omitting unstated is completed
-  editorMode: PropTypes.string.isRequired,
-  isMobile: PropTypes.bool,
-  isSlackEnabled: PropTypes.bool.isRequired,
-  slackChannels: PropTypes.string.isRequired,
-  grant: PropTypes.number.isRequired,
-  grantGroupId: PropTypes.string,
-  grantGroupName: PropTypes.string,
-  mutateGrant: PropTypes.func,
-};
-
 export default PageEditorWrapper;

+ 24 - 25
packages/app/src/components/PageEditor/Editor.jsx

@@ -5,15 +5,10 @@ import Dropzone from 'react-dropzone';
 import {
   Modal, ModalHeader, ModalBody,
 } from 'reactstrap';
-import { Subscribe } from 'unstated';
 
-
-import AppContainer from '~/client/services/AppContainer';
-import EditorContainer from '~/client/services/EditorContainer';
+import { useDefaultIndentSize } from '~/stores/context';
 import { useEditorSettings, useIsTextlintEnabled } from '~/stores/editor';
 
-import { withUnstatedContainers } from '../UnstatedUtils';
-
 import AbstractEditor from './AbstractEditor';
 import Cheatsheet from './Cheatsheet';
 import CodeMirrorEditor from './CodeMirrorEditor';
@@ -288,6 +283,7 @@ class Editor extends AbstractEditor {
 
     const {
       isMobile,
+      indentSize,
     } = this.props;
 
     return (
@@ -316,20 +312,16 @@ class Editor extends AbstractEditor {
 
                   {/* for PC */}
                   { !isMobile && (
-                    <Subscribe to={[EditorContainer]}>
-                      { editorContainer => (
-                        // eslint-disable-next-line arrow-body-style
-                        <CodeMirrorEditor
-                          ref={(c) => { this.cmEditor = c }}
-                          indentSize={editorContainer.state.indentSize}
-                          onPasteFiles={this.pasteFilesHandler}
-                          onDragEnter={this.dragEnterHandler}
-                          onMarkdownHelpButtonClicked={this.showMarkdownHelp}
-                          onAddAttachmentButtonClicked={this.addAttachmentHandler}
-                          {...this.props}
-                        />
-                      )}
-                    </Subscribe>
+                    // eslint-disable-next-line arrow-body-style
+                    <CodeMirrorEditor
+                      ref={(c) => { this.cmEditor = c }}
+                      indentSize={indentSize}
+                      onPasteFiles={this.pasteFilesHandler}
+                      onDragEnter={this.dragEnterHandler}
+                      onMarkdownHelpButtonClicked={this.showMarkdownHelp}
+                      onAddAttachmentButtonClicked={this.addAttachmentHandler}
+                      {...this.props}
+                    />
                   )}
 
                   {/* for mobile */}
@@ -386,23 +378,30 @@ Editor.propTypes = Object.assign({
   isTextlintEnabled: PropTypes.bool,
   onChange: PropTypes.func,
   onUpload: PropTypes.func,
-  editorContainer: PropTypes.instanceOf(EditorContainer).isRequired,
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   editorSettings: PropTypes.object.isRequired,
+  indentSize: PropTypes.number,
 }, AbstractEditor.propTypes);
 
 
-const EditorWithContainer = withUnstatedContainers(Editor, [EditorContainer, AppContainer]);
-
 const EditorWrapper = React.forwardRef((props, ref) => {
   const { data: editorSettings } = useEditorSettings();
   const { data: isTextlintEnabled } = useIsTextlintEnabled();
+  const { data: defaultIndentSize } = useDefaultIndentSize();
 
   if (editorSettings == null) {
     return <></>;
   }
 
-  return <EditorWithContainer ref={ref} {...props} isTextlintEnabled={isTextlintEnabled} editorSettings={editorSettings} />;
+  return (
+    <Editor
+      ref={ref}
+      {...props}
+      isTextlintEnabled={isTextlintEnabled}
+      editorSettings={editorSettings}
+      // eslint-disable-next-line react/prop-types
+      indentSize={props.indentSize ?? defaultIndentSize}
+    />
+  );
 });
 
 export default EditorWrapper;

+ 11 - 10
packages/app/src/components/PageEditor/OptionsSelector.tsx

@@ -8,8 +8,8 @@ import {
 } from 'reactstrap';
 
 import AppContainer from '~/client/services/AppContainer';
-import EditorContainer from '~/client/services/EditorContainer';
-import { useEditorSettings, useIsTextlintEnabled } from '~/stores/editor';
+import { useIsIndentSizeForced } from '~/stores/context';
+import { useEditorSettings, useIsTextlintEnabled, useCurrentIndentSize } from '~/stores/editor';
 
 import { DEFAULT_THEME, KeyMapMode } from '../../interfaces/editor-settings';
 import { withUnstatedContainers } from '../UnstatedUtils';
@@ -344,19 +344,20 @@ const ConfigurationDropdown = memo(({ isMathJaxEnabled, onConfirmEnableTextlint
 
 type Props = {
   appContainer: AppContainer
-  editorContainer: EditorContainer,
 };
 
 const OptionsSelector = (props: Props): JSX.Element => {
-  const { appContainer, editorContainer } = props;
-  const config = appContainer.getConfig();
+  const { appContainer } = props;
+  const config = appContainer.config;
 
   const [isDownloadDictModalShown, setDownloadDictModalShown] = useState(false);
 
   const { data: editorSettings, turnOffAskingBeforeDownloadLargeFiles } = useEditorSettings();
   const { mutate: mutateTextlintEnabled } = useIsTextlintEnabled();
+  const { data: isIndentSizeForced } = useIsIndentSizeForced();
+  const { data: currentIndentSize, mutate: mutateCurrentIndentSize } = useCurrentIndentSize();
 
-  if (editorSettings == null) {
+  if (editorSettings == null || isIndentSizeForced == null || currentIndentSize == null) {
     return <></>;
   }
 
@@ -371,9 +372,9 @@ const OptionsSelector = (props: Props): JSX.Element => {
         </span>
         <span className="ml-2 ml-sm-4">
           <IndentSizeSelector
-            isIndentSizeForced={config.isIndentSizeForced}
-            selectedIndentSize={editorContainer.state.indentSize}
-            onChange={newIndentSize => editorContainer.setState({ indentSize: newIndentSize })}
+            isIndentSizeForced={isIndentSizeForced}
+            selectedIndentSize={currentIndentSize}
+            onChange={newValue => mutateCurrentIndentSize(newValue)}
           />
         </span>
         <span className="ml-2 ml-sm-4">
@@ -405,5 +406,5 @@ const OptionsSelector = (props: Props): JSX.Element => {
 };
 
 
-const OptionsSelectorWrapper = withUnstatedContainers(OptionsSelector, [AppContainer, EditorContainer]);
+const OptionsSelectorWrapper = withUnstatedContainers(OptionsSelector, [AppContainer]);
 export default OptionsSelectorWrapper;

+ 10 - 1
packages/app/src/stores/editor.tsx

@@ -4,7 +4,7 @@ import useSWRImmutable from 'swr/immutable';
 import { apiv3Get, apiv3Put } from '~/client/util/apiv3-client';
 import { IEditorSettings } from '~/interfaces/editor-settings';
 
-import { useCurrentUser, useIsGuestUser } from './context';
+import { useCurrentUser, useDefaultIndentSize, useIsGuestUser } from './context';
 import { localStorageMiddleware } from './middlewares/sync-to-storage';
 import { useStaticSWR } from './use-static-swr';
 
@@ -60,3 +60,12 @@ export const useEditorSettings = (): SWRResponse<IEditorSettings, Error> & Edito
 export const useIsTextlintEnabled = (): SWRResponse<boolean, Error> => {
   return useStaticSWR<boolean, Error>('isTextlintEnabled', undefined, { fallbackData: false });
 };
+
+export const useCurrentIndentSize = (): SWRResponse<number, Error> => {
+  const { data: defaultIndentSize } = useDefaultIndentSize();
+  return useStaticSWR<number, Error>(
+    defaultIndentSize == null ? null : 'currentIndentSize',
+    undefined,
+    { fallbackData: defaultIndentSize },
+  );
+};