Yuki Takei 11 месяцев назад
Родитель
Сommit
efcde05f80
3 измененных файлов с 37 добавлено и 12 удалено
  1. 5 1
      apps/app/src/states/ui/editor.ts
  2. 20 0
      apps/app/src/states/ui/helper.ts
  3. 12 11
      apps/app/src/states/ui/sidebar.ts

+ 5 - 1
apps/app/src/states/ui/editor.ts

@@ -2,8 +2,12 @@ import { atom, useAtom } from 'jotai';
 
 import { EditorMode } from '~/stores-universal/ui';
 
+import type { UseAtom } from './helper';
+
 export const editorModeAtom = atom<EditorMode>(EditorMode.View);
 
-export const useEditorModeState = () => {
+// TODO: migrate from SWR version
+// see: ~/stores-universal/ui
+export const useEditorMode = (): UseAtom<typeof editorModeAtom> => {
   return useAtom(editorModeAtom);
 };

+ 20 - 0
apps/app/src/states/ui/helper.ts

@@ -0,0 +1,20 @@
+import {
+  type Atom,
+  type PrimitiveAtom,
+  type SetStateAction,
+} from 'jotai';
+
+export type UseAtom<AtomType> = AtomType extends PrimitiveAtom<infer Value>
+  ? readonly [Value, (update: SetStateAction<Value>) => void]
+  : AtomType extends Atom<infer Value>
+  ? readonly [Value, never]
+  : never;
+
+/**
+ * 更新関数を実際の値に解決するヘルパー関数
+ */
+export const resolveSetStateAction = <T>(newValue: SetStateAction<T>, currentValue: T): T => {
+  return typeof newValue === 'function'
+    ? (newValue as (prev: T) => T)(currentValue)
+    : newValue;
+};

+ 12 - 11
apps/app/src/states/ui/sidebar.ts

@@ -8,28 +8,29 @@ import { EditorMode } from '~/stores-universal/ui';
 
 import { isDeviceLargerThanXlAtom } from './device';
 import { editorModeAtom } from './editor';
+import type { UseAtom } from './helper';
+import { resolveSetStateAction } from './helper';
 
 
 const isDrawerOpenedAtom = atom(false);
 
-export const useDrawerOpened = () => {
+export const useDrawerOpened = (): UseAtom<typeof isDrawerOpenedAtom> => {
   return useAtom(isDrawerOpenedAtom);
 };
 
 // Avoid local storage to prevent conflicts with DB settings
 const preferCollapsedModeAtom = atom(false);
 
-// Custom hook for managing sidebar state
-export const usePreferCollapsedMode = () => {
+export const usePreferCollapsedMode = (): UseAtom<typeof 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;
+  return [
+    value,
+    (update) => {
+      const nextValue = resolveSetStateAction(update, value);
+      setValue(nextValue);
+      scheduleToPut({ preferCollapsedModeByUser: nextValue });
+    },
+  ] as const;
 };
 
 // Initialize state from server-side props only once per session