|
|
@@ -5,12 +5,11 @@ import {
|
|
|
|
|
|
import { PageGrant, type Nullable } from '@growi/core';
|
|
|
import { type SWRResponseWithUtils, useSWRStatic, withUtils } from '@growi/core/dist/swr';
|
|
|
-import { pagePathUtils, isClient, isServer } from '@growi/core/dist/utils';
|
|
|
+import { pagePathUtils, isClient } from '@growi/core/dist/utils';
|
|
|
import { Breakpoint } from '@growi/ui/dist/interfaces';
|
|
|
import { addBreakpointListener, cleanupBreakpointListener } from '@growi/ui/dist/utils';
|
|
|
import { useRouter } from 'next/router';
|
|
|
import type { HtmlElementNode } from 'rehype-toc';
|
|
|
-import type SimpleBar from 'simplebar-react';
|
|
|
import type { MutatorOptions } from 'swr';
|
|
|
import {
|
|
|
useSWRConfig, type SWRResponse, type Key,
|
|
|
@@ -21,6 +20,7 @@ import { scheduleToPut } from '~/client/services/user-ui-settings';
|
|
|
import type { IPageSelectedGrant } from '~/interfaces/page';
|
|
|
import { SidebarContentsType, SidebarMode } from '~/interfaces/ui';
|
|
|
import type { UpdateDescCountData } from '~/interfaces/websocket';
|
|
|
+import { EditorMode, useEditorMode } from '~/stores-universal/ui';
|
|
|
import {
|
|
|
useIsNotFound, useCurrentPagePath, useIsTrashPage, useCurrentPageId,
|
|
|
} from '~/stores/page';
|
|
|
@@ -37,17 +37,6 @@ const { isTrashTopPage, isUsersTopPage } = pagePathUtils;
|
|
|
const logger = loggerFactory('growi:stores:ui');
|
|
|
|
|
|
|
|
|
-/** **********************************************************
|
|
|
- * Unions
|
|
|
- *********************************************************** */
|
|
|
-
|
|
|
-export const EditorMode = {
|
|
|
- View: 'view',
|
|
|
- Editor: 'editor',
|
|
|
-} as const;
|
|
|
-export type EditorMode = typeof EditorMode[keyof typeof EditorMode];
|
|
|
-
|
|
|
-
|
|
|
/** **********************************************************
|
|
|
* Storing objects to ref
|
|
|
*********************************************************** */
|
|
|
@@ -81,92 +70,6 @@ export const useIsMobile = (): SWRResponse<boolean, Error> => {
|
|
|
return useStaticSWR<boolean, Error>(key, undefined, configuration);
|
|
|
};
|
|
|
|
|
|
-const getClassNamesByEditorMode = (editorMode: EditorMode | undefined): string[] => {
|
|
|
- const classNames: string[] = [];
|
|
|
- switch (editorMode) {
|
|
|
- case EditorMode.Editor:
|
|
|
- classNames.push('editing', 'builtin-editor');
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return classNames;
|
|
|
-};
|
|
|
-
|
|
|
-export const EditorModeHash = {
|
|
|
- View: '',
|
|
|
- Edit: '#edit',
|
|
|
-} as const;
|
|
|
-export type EditorModeHash = typeof EditorModeHash[keyof typeof EditorModeHash];
|
|
|
-
|
|
|
-const updateHashByEditorMode = (newEditorMode: EditorMode) => {
|
|
|
- const { pathname, search } = window.location;
|
|
|
-
|
|
|
- switch (newEditorMode) {
|
|
|
- case EditorMode.View:
|
|
|
- window.history.replaceState(null, '', `${pathname}${search}${EditorModeHash.View}`);
|
|
|
- break;
|
|
|
- case EditorMode.Editor:
|
|
|
- window.history.replaceState(null, '', `${pathname}${search}${EditorModeHash.Edit}`);
|
|
|
- break;
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-export const determineEditorModeByHash = (): EditorMode => {
|
|
|
- if (isServer()) {
|
|
|
- return EditorMode.View;
|
|
|
- }
|
|
|
-
|
|
|
- const { hash } = window.location;
|
|
|
-
|
|
|
- switch (hash) {
|
|
|
- case EditorModeHash.Edit:
|
|
|
- return EditorMode.Editor;
|
|
|
- default:
|
|
|
- return EditorMode.View;
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-type EditorModeUtils = {
|
|
|
- getClassNamesByEditorMode: () => string[],
|
|
|
-}
|
|
|
-
|
|
|
-export const useEditorMode = (): SWRResponseWithUtils<EditorModeUtils, EditorMode> => {
|
|
|
- const { data: _isEditable } = useIsEditable();
|
|
|
- const { data: isNotFound } = useIsNotFound();
|
|
|
-
|
|
|
- const editorModeByHash = determineEditorModeByHash();
|
|
|
-
|
|
|
- const isLoading = _isEditable === undefined;
|
|
|
- const isEditable = !isLoading && _isEditable;
|
|
|
- const preventModeEditor = !isEditable || isNotFound === undefined || isNotFound === true;
|
|
|
- const initialData = preventModeEditor ? EditorMode.View : editorModeByHash;
|
|
|
-
|
|
|
- const swrResponse = useSWRImmutable(
|
|
|
- isLoading ? null : ['editorMode', isEditable, preventModeEditor],
|
|
|
- null,
|
|
|
- { fallbackData: initialData },
|
|
|
- );
|
|
|
-
|
|
|
- // construct overriding mutate method
|
|
|
- const mutateOriginal = swrResponse.mutate;
|
|
|
- const mutate = useCallback((editorMode: EditorMode, shouldRevalidate?: boolean) => {
|
|
|
- if (preventModeEditor) {
|
|
|
- return Promise.resolve(EditorMode.View); // fixed if not editable
|
|
|
- }
|
|
|
- updateHashByEditorMode(editorMode);
|
|
|
- return mutateOriginal(editorMode, shouldRevalidate);
|
|
|
- }, [preventModeEditor, mutateOriginal]);
|
|
|
-
|
|
|
- const getClassNames = useCallback(() => {
|
|
|
- return getClassNamesByEditorMode(swrResponse.data);
|
|
|
- }, [swrResponse.data]);
|
|
|
-
|
|
|
- return Object.assign(swrResponse, {
|
|
|
- mutate,
|
|
|
- getClassNamesByEditorMode: getClassNames,
|
|
|
- });
|
|
|
-};
|
|
|
-
|
|
|
export const useIsDeviceLargerThanMd = (): SWRResponse<boolean, Error> => {
|
|
|
const key: Key = isClient() ? 'isDeviceLargerThanMd' : null;
|
|
|
|