Parcourir la source

refactor: update sidebar state management and initialization logic

Yuki Takei il y a 11 mois
Parent
commit
a098f5097e
3 fichiers modifiés avec 33 ajouts et 9 suppressions
  1. 3 5
      apps/app/src/pages/utils/commons.ts
  2. 29 3
      apps/app/src/states/ui.ts
  3. 1 1
      apps/app/src/stores/ui.tsx

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

@@ -14,7 +14,7 @@ import type { IUserUISettings } from '~/interfaces/user-ui-settings';
 import type { PageDocument } from '~/server/models/page';
 import type { PageDocument } from '~/server/models/page';
 import type { UserUISettingsDocument } from '~/server/models/user-ui-settings';
 import type { UserUISettingsDocument } from '~/server/models/user-ui-settings';
 import { detectLocaleFromBrowserAcceptLanguage } from '~/server/util/locale-utils';
 import { detectLocaleFromBrowserAcceptLanguage } from '~/server/util/locale-utils';
-import { usePreferCollapsedMode } from '~/states/ui';
+import { usePreferCollapsedModeInitializer } from '~/states/ui';
 import { useCurrentProductNavWidth, useCurrentSidebarContents } from '~/stores/ui';
 import { useCurrentProductNavWidth, useCurrentSidebarContents } from '~/stores/ui';
 import { getGrowiVersion } from '~/utils/growi-version';
 import { getGrowiVersion } from '~/utils/growi-version';
 
 
@@ -183,10 +183,8 @@ export const generateCustomTitleForPage = (props: CommonProps, pagePath: string)
 };
 };
 
 
 export const useInitSidebarConfig = (sidebarConfig: ISidebarConfig, userUISettings?: IUserUISettings): void => {
 export const useInitSidebarConfig = (sidebarConfig: ISidebarConfig, userUISettings?: IUserUISettings): void => {
-  // UserUISettings
-  const [, setPreferCollapsedMode] = usePreferCollapsedMode();
-  const value = userUISettings?.preferCollapsedModeByUser ?? sidebarConfig.isSidebarCollapsedMode;
-  setPreferCollapsedMode(userUISettings?.preferCollapsedModeByUser ?? sidebarConfig.isSidebarCollapsedMode);
+  // Initialize with user preference from DB if available, otherwise use system default
+  usePreferCollapsedModeInitializer(userUISettings?.preferCollapsedModeByUser ?? sidebarConfig.isSidebarCollapsedMode);
 
 
   useCurrentSidebarContents(userUISettings?.currentSidebarContents);
   useCurrentSidebarContents(userUISettings?.currentSidebarContents);
   useCurrentProductNavWidth(userUISettings?.currentProductNavWidth);
   useCurrentProductNavWidth(userUISettings?.currentProductNavWidth);

+ 29 - 3
apps/app/src/states/ui.ts

@@ -1,4 +1,4 @@
-import { useEffect } from 'react';
+import { useCallback, useEffect } from 'react';
 
 
 
 
 import { isClient } from '@growi/core/dist/utils';
 import { isClient } from '@growi/core/dist/utils';
@@ -6,20 +6,46 @@ import { Breakpoint } from '@growi/ui/dist/interfaces';
 import { addBreakpointListener, cleanupBreakpointListener } from '@growi/ui/dist/utils';
 import { addBreakpointListener, cleanupBreakpointListener } from '@growi/ui/dist/utils';
 import { atom, useAtom } from 'jotai';
 import { atom, useAtom } from 'jotai';
 
 
+import { scheduleToPut } from '~/client/services/user-ui-settings';
 import { SidebarMode } from '~/interfaces/ui';
 import { SidebarMode } from '~/interfaces/ui';
 import { EditorMode } from '~/stores-universal/ui';
 import { EditorMode } from '~/stores-universal/ui';
 
 
+
 const isDrawerOpenedAtom = atom<boolean>(false);
 const isDrawerOpenedAtom = atom<boolean>(false);
 
 
 export const useDrawerOpened = () => {
 export const useDrawerOpened = () => {
   return useAtom(isDrawerOpenedAtom);
   return useAtom(isDrawerOpenedAtom);
 };
 };
 
 
-
+// Avoid local storage to prevent conflicts with DB settings
 const preferCollapsedModeAtom = atom<boolean>(false);
 const preferCollapsedModeAtom = atom<boolean>(false);
 
 
+// Custom hook for managing sidebar state
 export const usePreferCollapsedMode = () => {
 export const usePreferCollapsedMode = () => {
-  return useAtom(preferCollapsedModeAtom);
+  const [value, setValue] = useAtom(preferCollapsedModeAtom);
+
+  const setValueWithPersist = useCallback((newValue: boolean) => {
+    setValue(newValue);
+    // Save to server
+    scheduleToPut({ preferCollapsedModeByUser: newValue });
+  }, [setValue]);
+
+  return [value, setValueWithPersist] as const;
+};
+
+// Initialize state from server-side props only once per session
+const preferCollapsedModeInitializedAtom = atom<boolean>(false);
+
+export const usePreferCollapsedModeInitializer = (initialData: boolean): void => {
+  const [isInitialized, setIsInitialized] = useAtom(preferCollapsedModeInitializedAtom);
+  const [, setPreferCollapsedMode] = usePreferCollapsedMode();
+
+  useEffect(() => {
+    if (!isInitialized) {
+      setPreferCollapsedMode(initialData);
+      setIsInitialized(true);
+    }
+  }, [isInitialized, setPreferCollapsedMode, setIsInitialized, initialData]);
 };
 };
 
 
 
 

+ 1 - 1
apps/app/src/stores/ui.tsx

@@ -18,7 +18,7 @@ import useSWRImmutable from 'swr/immutable';
 
 
 import { scheduleToPut } from '~/client/services/user-ui-settings';
 import { scheduleToPut } from '~/client/services/user-ui-settings';
 import type { IPageSelectedGrant } from '~/interfaces/page';
 import type { IPageSelectedGrant } from '~/interfaces/page';
-import { SidebarContentsType, SidebarMode } from '~/interfaces/ui';
+import { SidebarContentsType } from '~/interfaces/ui';
 import type { UpdateDescCountData } from '~/interfaces/websocket';
 import type { UpdateDescCountData } from '~/interfaces/websocket';
 import {
 import {
   useIsEditable, useIsReadOnlyUser,
   useIsEditable, useIsReadOnlyUser,