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

migrate useDrawerOpened and usePreferCollapsedMode

Yuki Takei 11 месяцев назад
Родитель
Сommit
c882e7a030

+ 3 - 4
apps/app/src/client/components/Common/DrawerToggler/DrawerToggler.tsx

@@ -1,7 +1,6 @@
 import { type ReactNode, type JSX } from 'react';
 
-import { useDrawerOpened } from '~/stores/ui';
-
+import { useDrawerOpened } from '~/states/ui';
 
 import styles from './DrawerToggler.module.scss';
 
@@ -17,7 +16,7 @@ export const DrawerToggler = (props: Props): JSX.Element => {
 
   const { className, children } = props;
 
-  const { data: isOpened, mutate } = useDrawerOpened();
+  const [isOpened, setIsOpened] = useDrawerOpened();
 
   return (
     <div className={`${moduleClass} ${className ?? ''}`}>
@@ -26,7 +25,7 @@ export const DrawerToggler = (props: Props): JSX.Element => {
         type="button"
         aria-expanded="false"
         aria-label="Toggle navigation"
-        onClick={() => mutate(!isOpened)}
+        onClick={() => setIsOpened(!isOpened)}
       >
         {children}
       </button>

+ 5 - 4
apps/app/src/client/components/Me/UISettings.tsx

@@ -5,7 +5,8 @@ import { UncontrolledTooltip } from 'reactstrap';
 
 import { updateUserUISettings } from '~/client/services/user-ui-settings';
 import { toastError, toastSuccess } from '~/client/util/toastr';
-import { useCollapsedContentsOpened, usePreferCollapsedMode, useSidebarMode } from '~/stores/ui';
+import { usePreferCollapsedMode } from '~/states/ui';
+import { useCollapsedContentsOpened, useSidebarMode } from '~/stores/ui';
 
 import styles from './UISettings.module.scss';
 
@@ -28,13 +29,13 @@ export const UISettings = (): JSX.Element => {
   const {
     isDockMode, isCollapsedMode,
   } = useSidebarMode();
-  const { mutate: mutatePreferCollapsedMode } = usePreferCollapsedMode();
+  const [, setPreferCollapsedMode] = usePreferCollapsedMode();
   const { mutate: mutateCollapsedContentsOpened } = useCollapsedContentsOpened();
 
   const toggleCollapsed = useCallback(() => {
-    mutatePreferCollapsedMode(!isCollapsedMode());
+    setPreferCollapsedMode(!isCollapsedMode());
     mutateCollapsedContentsOpened(false);
-  }, [mutatePreferCollapsedMode, isCollapsedMode, mutateCollapsedContentsOpened]);
+  }, [setPreferCollapsedMode, isCollapsedMode, mutateCollapsedContentsOpened]);
 
   const updateButtonHandler = useCallback(async() => {
     try {

+ 3 - 3
apps/app/src/client/components/Navbar/GrowiNavbarBottom.tsx

@@ -2,17 +2,17 @@ import React, { useCallback, type JSX } from 'react';
 
 import { GroundGlassBar } from '~/components/Navbar/GroundGlassBar';
 import { useSearchModal } from '~/features/search/client/stores/search';
+import { useDrawerOpened } from '~/states/ui';
 import { useIsSearchPage } from '~/stores-universal/context';
 import { usePageCreateModal } from '~/stores/modal';
 import { useCurrentPagePath } from '~/stores/page';
-import { useDrawerOpened } from '~/stores/ui';
 
 import styles from './GrowiNavbarBottom.module.scss';
 
 
 export const GrowiNavbarBottom = (): JSX.Element => {
 
-  const { data: isDrawerOpened, mutate: mutateDrawerOpened } = useDrawerOpened();
+  const [isDrawerOpened, setIsDrawerOpened] = useDrawerOpened();
   const { open: openCreateModal } = usePageCreateModal();
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: isSearchPage } = useIsSearchPage();
@@ -35,7 +35,7 @@ export const GrowiNavbarBottom = (): JSX.Element => {
             <a
               role="button"
               className="nav-link btn-lg"
-              onClick={() => mutateDrawerOpened(true)}
+              onClick={() => setIsDrawerOpened(true)}
             >
               <span className="material-symbols-outlined fs-2">reorder</span>
             </a>

+ 3 - 3
apps/app/src/client/components/PageEditor/EditorNavbarBottom.tsx

@@ -2,7 +2,7 @@ import type { JSX } from 'react';
 
 import dynamic from 'next/dynamic';
 
-import { useDrawerOpened } from '~/stores/ui';
+import { useDrawerOpened } from '~/states/ui';
 
 import styles from './EditorNavbarBottom.module.scss';
 
@@ -14,7 +14,7 @@ const OptionsSelector = dynamic(() => import('~/client/components/PageEditor/Opt
 
 const EditorNavbarBottom = (): JSX.Element => {
 
-  const { mutate: mutateDrawerOpened } = useDrawerOpened();
+  const [, setIsDrawerOpened] = useDrawerOpened();
 
   return (
     <div className="border-top" data-testid="grw-editor-navbar-bottom">
@@ -22,7 +22,7 @@ const EditorNavbarBottom = (): JSX.Element => {
         <a
           role="button"
           className="nav-link btn-lg p-2 d-md-none me-3 opacity-50"
-          onClick={() => mutateDrawerOpened(true)}
+          onClick={() => setIsDrawerOpened(true)}
         >
           <span className="material-symbols-outlined fs-2">reorder</span>
         </a>

+ 9 - 10
apps/app/src/client/components/Sidebar/Sidebar.tsx

@@ -11,15 +11,14 @@ import { SidebarMode } from '~/interfaces/ui';
 import { useIsSearchPage } from '~/stores-universal/context';
 import { EditorMode, useEditorMode } from '~/stores-universal/ui';
 import {
-  useDrawerOpened,
   useCollapsedContentsOpened,
   useCurrentProductNavWidth,
-  usePreferCollapsedMode,
   useSidebarMode,
   useSidebarScrollerRef,
   useIsDeviceLargerThanMd,
   useIsDeviceLargerThanXl,
 } from '~/stores/ui';
+import { useDrawerOpened, usePreferCollapsedMode } from '~/states/ui';
 
 import { DrawerToggler } from '../Common/DrawerToggler';
 
@@ -70,9 +69,9 @@ const ResizableContainer = memo((props: ResizableContainerProps): JSX.Element =>
   const { children } = props;
 
   const { isDrawerMode, isCollapsedMode, isDockMode } = useSidebarMode();
-  const { mutate: mutateDrawerOpened } = useDrawerOpened();
+  const [, setIsDrawerOpened] = useDrawerOpened();
   const { data: currentProductNavWidth, mutateAndSave: mutateProductNavWidth } = useCurrentProductNavWidth();
-  const { mutateAndSave: mutatePreferCollapsedMode } = usePreferCollapsedMode();
+  const [, setPreferCollapsedMode] = usePreferCollapsedMode();
   const { mutate: mutateCollapsedContentsOpened } = useCollapsedContentsOpened();
 
   const [isClient, setClient] = useState(false);
@@ -89,9 +88,9 @@ const ResizableContainer = memo((props: ResizableContainerProps): JSX.Element =>
   }, [mutateProductNavWidth]);
 
   const collapsedByResizableAreaHandler = useCallback(() => {
-    mutatePreferCollapsedMode(true);
+    setPreferCollapsedMode(true);
     mutateCollapsedContentsOpened(false);
-  }, [mutateCollapsedContentsOpened, mutatePreferCollapsedMode]);
+  }, [mutateCollapsedContentsOpened, setPreferCollapsedMode]);
 
   useIsomorphicLayoutEffect(() => {
     setClient(true);
@@ -100,8 +99,8 @@ const ResizableContainer = memo((props: ResizableContainerProps): JSX.Element =>
   // open/close resizable container when drawer mode
   useEffect(() => {
     setResizableAreaWidth(getWidthByMode(isDrawerMode(), isCollapsedMode(), currentProductNavWidth));
-    mutateDrawerOpened(false);
-  }, [currentProductNavWidth, isCollapsedMode, isDrawerMode, mutateDrawerOpened]);
+    setIsDrawerOpened(false);
+  }, [currentProductNavWidth, isCollapsedMode, isDrawerMode, setIsDrawerOpened]);
 
   return !isClient
     ? (
@@ -206,7 +205,7 @@ const DrawableContainer = memo((props: DrawableContainerProps): JSX.Element => {
 
   const { divProps, className, children } = props;
 
-  const { data: isDrawerOpened, mutate } = useDrawerOpened();
+  const [isDrawerOpened, setIsDrawerOpened] = useDrawerOpened();
 
   const openClass = `${isDrawerOpened ? 'open' : ''}`;
 
@@ -216,7 +215,7 @@ const DrawableContainer = memo((props: DrawableContainerProps): JSX.Element => {
         {children}
       </div>
       { isDrawerOpened && (
-        <div className="modal-backdrop fade show" onClick={() => mutate(false)} />
+        <div className="modal-backdrop fade show" onClick={() => setIsDrawerOpened(false)} />
       ) }
     </>
   );

+ 8 - 7
apps/app/src/client/components/Sidebar/SidebarHead/ToggleCollapseButton.tsx

@@ -2,8 +2,9 @@ import {
   memo, useCallback, useMemo, type JSX,
 } from 'react';
 
+import { useDrawerOpened, usePreferCollapsedMode } from '~/states/ui';
 import {
-  useCollapsedContentsOpened, usePreferCollapsedMode, useDrawerOpened, useSidebarMode,
+  useCollapsedContentsOpened, useSidebarMode,
 } from '~/stores/ui';
 
 
@@ -13,18 +14,18 @@ import styles from './ToggleCollapseButton.module.scss';
 export const ToggleCollapseButton = memo((): JSX.Element => {
 
   const { isDrawerMode, isCollapsedMode } = useSidebarMode();
-  const { data: isDrawerOpened, mutate: mutateDrawerOpened } = useDrawerOpened();
-  const { mutateAndSave: mutatePreferCollapsedMode } = usePreferCollapsedMode();
+  const [isDrawerOpened, setIsDrawerOpened] = useDrawerOpened();
+  const [, setPreferCollapsedMode] = usePreferCollapsedMode();
   const { mutate: mutateCollapsedContentsOpened } = useCollapsedContentsOpened();
 
   const toggleDrawer = useCallback(() => {
-    mutateDrawerOpened(!isDrawerOpened);
-  }, [isDrawerOpened, mutateDrawerOpened]);
+    setIsDrawerOpened(!isDrawerOpened);
+  }, [isDrawerOpened, setIsDrawerOpened]);
 
   const toggleCollapsed = useCallback(() => {
-    mutatePreferCollapsedMode(!isCollapsedMode());
+    setPreferCollapsedMode(!isCollapsedMode());
     mutateCollapsedContentsOpened(false);
-  }, [isCollapsedMode, mutateCollapsedContentsOpened, mutatePreferCollapsedMode]);
+  }, [isCollapsedMode, mutateCollapsedContentsOpened, setPreferCollapsedMode]);
 
   const rotationClass = isCollapsedMode() ? 'rotate180' : '';
   const icon = useMemo(() => {

+ 5 - 4
apps/app/src/pages/utils/commons.ts

@@ -14,9 +14,8 @@ import type { IUserUISettings } from '~/interfaces/user-ui-settings';
 import type { PageDocument } from '~/server/models/page';
 import type { UserUISettingsDocument } from '~/server/models/user-ui-settings';
 import { detectLocaleFromBrowserAcceptLanguage } from '~/server/util/locale-utils';
-import {
-  useCurrentProductNavWidth, useCurrentSidebarContents, usePreferCollapsedMode,
-} from '~/stores/ui';
+import { usePreferCollapsedMode } from '~/states/ui';
+import { useCurrentProductNavWidth, useCurrentSidebarContents } from '~/stores/ui';
 import { getGrowiVersion } from '~/utils/growi-version';
 
 export type CommonProps = {
@@ -185,7 +184,9 @@ export const generateCustomTitleForPage = (props: CommonProps, pagePath: string)
 
 export const useInitSidebarConfig = (sidebarConfig: ISidebarConfig, userUISettings?: IUserUISettings): void => {
   // UserUISettings
-  usePreferCollapsedMode(userUISettings?.preferCollapsedModeByUser ?? sidebarConfig.isSidebarCollapsedMode);
+  const [, setPreferCollapsedMode] = usePreferCollapsedMode();
+  setPreferCollapsedMode(userUISettings?.preferCollapsedModeByUser ?? sidebarConfig.isSidebarCollapsedMode);
+
   useCurrentSidebarContents(userUISettings?.currentSidebarContents);
   useCurrentProductNavWidth(userUISettings?.currentProductNavWidth);
 };

+ 14 - 0
apps/app/src/states/ui.ts

@@ -0,0 +1,14 @@
+import { atom, useAtom } from 'jotai';
+
+// Private atoms
+const isDrawerOpenedAtom = atom<boolean>(false);
+const preferCollapsedModeAtom = atom<boolean>(false);
+
+// Public hooks
+export const useDrawerOpened = () => {
+  return useAtom(isDrawerOpenedAtom);
+};
+
+export const usePreferCollapsedMode = () => {
+  return useAtom(preferCollapsedModeAtom);
+};

+ 6 - 22
apps/app/src/stores/ui.tsx

@@ -20,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 { usePreferCollapsedMode } from '~/states/ui';
 import {
   useIsEditable, useIsReadOnlyUser,
   useIsSharedUser, useIsIdenticalPath, useCurrentUser, useShareLinkId,
@@ -213,27 +214,10 @@ export const useCurrentProductNavWidth = (initialData?: number): SWRResponseWith
   return withUtils(swrResponse, { mutateAndSave });
 };
 
-export const usePreferCollapsedMode = (initialData?: boolean): SWRResponseWithUtils<MutateAndSaveUserUISettingsUtils<boolean>, boolean> => {
-  const swrResponse = useSWRStatic('isPreferCollapsedMode', initialData, { fallbackData: false });
-
-  const { mutate } = swrResponse;
-
-  const mutateAndSave: MutateAndSaveUserUISettings<boolean> = useCallback((data, opts?) => {
-    scheduleToPut({ preferCollapsedModeByUser: data });
-    return mutate(data, opts);
-  }, [mutate]);
-
-  return withUtils(swrResponse, { mutateAndSave });
-};
-
 export const useCollapsedContentsOpened = (initialData?: boolean): SWRResponse<boolean> => {
   return useSWRStatic('isCollapsedContentsOpened', initialData, { fallbackData: false });
 };
 
-export const useDrawerOpened = (isOpened?: boolean): SWRResponse<boolean, Error> => {
-  return useSWRStatic('isDrawerOpened', isOpened, { fallbackData: false });
-};
-
 type DetectSidebarModeUtils = {
   isDrawerMode(): boolean
   isCollapsedMode(): boolean
@@ -243,20 +227,20 @@ type DetectSidebarModeUtils = {
 export const useSidebarMode = (): SWRResponseWithUtils<DetectSidebarModeUtils, SidebarMode> => {
   const { data: isDeviceLargerThanXl } = useIsDeviceLargerThanXl();
   const { data: editorMode } = useEditorMode();
-  const { data: isCollapsedModeUnderDockMode } = usePreferCollapsedMode();
+  const [isCollapsedModeUnderDockMode] = usePreferCollapsedMode();
 
   const condition = isDeviceLargerThanXl != null && editorMode != null && isCollapsedModeUnderDockMode != null;
 
   const isEditorMode = editorMode === EditorMode.Editor;
 
   const fetcher = useCallback((
-      [, isDeviceLargerThanXl, isEditorMode, isCollapsedModeUnderDockMode]: [Key, boolean|undefined, boolean|undefined, boolean|undefined],
-  ) => {
+      [, isDeviceLargerThanXl, isEditorMode]: [Key, boolean | undefined, boolean | undefined, boolean|undefined],
+  ): SidebarMode => {
     if (!isDeviceLargerThanXl) {
       return SidebarMode.DRAWER;
     }
-    return isEditorMode || isCollapsedModeUnderDockMode ? SidebarMode.COLLAPSED : SidebarMode.DOCK;
-  }, []);
+    return (isEditorMode || isCollapsedModeUnderDockMode) ? SidebarMode.COLLAPSED : SidebarMode.DOCK;
+  }, [isCollapsedModeUnderDockMode]);
 
   const swrResponse = useSWRImmutable(
     condition ? ['sidebarMode', isDeviceLargerThanXl, isEditorMode, isCollapsedModeUnderDockMode] : null,