Explorar el Código

Create and apply useCurrentPageYjsData

Shun Miyazawa hace 1 año
padre
commit
d32bddf06b

+ 11 - 12
apps/app/src/client/services/side-effects/yjs.ts

@@ -2,38 +2,37 @@ import { useCallback, useEffect } from 'react';
 
 
 import { useGlobalSocket } from '@growi/core/dist/swr';
 import { useGlobalSocket } from '@growi/core/dist/swr';
 
 
-import type { CurrentPageYjsDraft } from '~/interfaces/page';
 import { SocketEventName } from '~/interfaces/websocket';
 import { SocketEventName } from '~/interfaces/websocket';
-import { useCurrentPageYjsDraft, useCurrentPageYjsAwarenessStateSize } from '~/stores/page';
+import { useCurrentPageYjsData } from '~/stores/yjs';
 
 
 export const useYjsDraftEffect = (): void => {
 export const useYjsDraftEffect = (): void => {
   const { data: socket } = useGlobalSocket();
   const { data: socket } = useGlobalSocket();
-  const { mutate: mutateCurrentPageYjsDraft } = useCurrentPageYjsDraft();
+  const { updateHasDraft } = useCurrentPageYjsData();
 
 
-  const yjsDraftUpdateHandler = useCallback(((currentPageYjsDraft: CurrentPageYjsDraft) => {
-    mutateCurrentPageYjsDraft(currentPageYjsDraft);
-  }), [mutateCurrentPageYjsDraft]);
+  const yjsDraftUpdateHandler = useCallback(((hasDraft: boolean) => {
+    updateHasDraft(hasDraft);
+  }), [updateHasDraft]);
 
 
   useEffect(() => {
   useEffect(() => {
 
 
     if (socket == null) { return }
     if (socket == null) { return }
 
 
-    socket.on(SocketEventName.YjsUpdated, yjsDraftUpdateHandler);
+    socket.on(SocketEventName.YjsDraftUpdated, yjsDraftUpdateHandler);
 
 
     return () => {
     return () => {
-      socket.off(SocketEventName.YjsUpdated, yjsDraftUpdateHandler);
+      socket.off(SocketEventName.YjsDraftUpdated, yjsDraftUpdateHandler);
     };
     };
 
 
-  }, [mutateCurrentPageYjsDraft, socket, yjsDraftUpdateHandler]);
+  }, [socket, yjsDraftUpdateHandler]);
 };
 };
 
 
 export const useYjsAwarenessStateEffect = (): void => {
 export const useYjsAwarenessStateEffect = (): void => {
   const { data: socket } = useGlobalSocket();
   const { data: socket } = useGlobalSocket();
-  const { mutate: mutateCurrentPageYjsAwarenessStateSize } = useCurrentPageYjsAwarenessStateSize();
+  const { updateAwarenessStateSize } = useCurrentPageYjsData();
 
 
   const yjsAwarenessStateUpdateHandler = useCallback(((awarenessStateSize: number) => {
   const yjsAwarenessStateUpdateHandler = useCallback(((awarenessStateSize: number) => {
-    mutateCurrentPageYjsAwarenessStateSize(awarenessStateSize);
-  }), [mutateCurrentPageYjsAwarenessStateSize]);
+    updateAwarenessStateSize(awarenessStateSize);
+  }), [updateAwarenessStateSize]);
 
 
   useEffect(() => {
   useEffect(() => {
 
 

+ 5 - 5
apps/app/src/components/Navbar/PageEditorModeManager.tsx

@@ -5,8 +5,9 @@ import { useTranslation } from 'next-i18next';
 
 
 import { useCreatePageAndTransit } from '~/client/services/create-page';
 import { useCreatePageAndTransit } from '~/client/services/create-page';
 import { toastError } from '~/client/util/toastr';
 import { toastError } from '~/client/util/toastr';
-import { useIsNotFound, useCurrentPageYjsDraft, useCurrentPageYjsAwarenessStateSize } from '~/stores/page';
+import { useIsNotFound } from '~/stores/page';
 import { EditorMode, useEditorMode, useIsDeviceLargerThanMd } from '~/stores/ui';
 import { EditorMode, useEditorMode, useIsDeviceLargerThanMd } from '~/stores/ui';
+import { useCurrentPageYjsData } from '~/stores/yjs';
 
 
 import { shouldCreateWipPage } from '../../utils/should-create-wip-page';
 import { shouldCreateWipPage } from '../../utils/should-create-wip-page';
 
 
@@ -64,8 +65,7 @@ export const PageEditorModeManager = (props: Props): JSX.Element => {
   const { data: isNotFound } = useIsNotFound();
   const { data: isNotFound } = useIsNotFound();
   const { mutate: mutateEditorMode } = useEditorMode();
   const { mutate: mutateEditorMode } = useEditorMode();
   const { data: isDeviceLargerThanMd } = useIsDeviceLargerThanMd();
   const { data: isDeviceLargerThanMd } = useIsDeviceLargerThanMd();
-  const { data: currentPageYjsDraft } = useCurrentPageYjsDraft();
-  const { data: currentPageYjsAwarenessStateSize } = useCurrentPageYjsAwarenessStateSize();
+  const { data: currentPageYjsData } = useCurrentPageYjsData();
 
 
   const { isCreating, createAndTransit } = useCreatePageAndTransit();
   const { isCreating, createAndTransit } = useCreatePageAndTransit();
 
 
@@ -89,12 +89,12 @@ export const PageEditorModeManager = (props: Props): JSX.Element => {
   const _isBtnDisabled = isCreating || isBtnDisabled;
   const _isBtnDisabled = isCreating || isBtnDisabled;
 
 
   const circleColor = useMemo(() => {
   const circleColor = useMemo(() => {
-    if (currentPageYjsAwarenessStateSize != null && currentPageYjsAwarenessStateSize > 0) {
+    if (currentPageYjsData?.awarenessStateSize != null && currentPageYjsData.awarenessStateSize > 0) {
       return 'bg-primary';
       return 'bg-primary';
     }
     }
 
 
     // TODO: https://redmine.weseek.co.jp/issues/145652
     // TODO: https://redmine.weseek.co.jp/issues/145652
-  }, [currentPageYjsAwarenessStateSize]);
+  }, [currentPageYjsData]);
 
 
   return (
   return (
     <>
     <>

+ 8 - 7
apps/app/src/pages/[[...path]].page.tsx

@@ -43,12 +43,13 @@ import {
 } from '~/stores/context';
 } from '~/stores/context';
 import { useEditingMarkdown } from '~/stores/editor';
 import { useEditingMarkdown } from '~/stores/editor';
 import {
 import {
-  useSWRxCurrentPage, useSWRMUTxCurrentPage, useCurrentPageId, useCurrentPageYjsDraft, useCurrentPageYjsAwarenessStateSize,
+  useSWRxCurrentPage, useSWRMUTxCurrentPage, useCurrentPageId,
   useIsNotFound, useIsLatestRevision, useTemplateTagData, useTemplateBodyData,
   useIsNotFound, useIsLatestRevision, useTemplateTagData, useTemplateBodyData,
 } from '~/stores/page';
 } from '~/stores/page';
 import { useRedirectFrom } from '~/stores/page-redirect';
 import { useRedirectFrom } from '~/stores/page-redirect';
 import { useRemoteRevisionId } from '~/stores/remote-latest-page';
 import { useRemoteRevisionId } from '~/stores/remote-latest-page';
 import { useSetupGlobalSocket, useSetupGlobalSocketForPage } from '~/stores/websocket';
 import { useSetupGlobalSocket, useSetupGlobalSocketForPage } from '~/stores/websocket';
+import { useCurrentPageYjsData, type CurrentPageYjsDataStates } from '~/stores/yjs';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 import { BasicLayout } from '../components/Layout/BasicLayout';
 import { BasicLayout } from '../components/Layout/BasicLayout';
@@ -172,8 +173,7 @@ type Props = CommonProps & {
   skipSSR: boolean,
   skipSSR: boolean,
   ssrMaxRevisionBodyLength: number,
   ssrMaxRevisionBodyLength: number,
 
 
-  hasYjsDraft: boolean,
-  yjsAwarenessStateSize: number,
+  yjsData: CurrentPageYjsDataStates,
 
 
   rendererConfig: RendererConfig,
   rendererConfig: RendererConfig,
 };
 };
@@ -225,8 +225,7 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
   useIsUploadAllFileAllowed(props.isUploadAllFileAllowed);
   useIsUploadAllFileAllowed(props.isUploadAllFileAllowed);
   useIsUploadEnabled(props.isUploadEnabled);
   useIsUploadEnabled(props.isUploadEnabled);
 
 
-  useCurrentPageYjsDraft({ hasYjsDraft: props.hasYjsDraft });
-  useCurrentPageYjsAwarenessStateSize(props.yjsAwarenessStateSize);
+  useCurrentPageYjsData(props.yjsData);
 
 
   const { pageWithMeta } = props;
   const { pageWithMeta } = props;
 
 
@@ -492,8 +491,10 @@ async function injectRoutingInformation(context: GetServerSidePropsContext, prop
       }
       }
     }
     }
 
 
-    props.hasYjsDraft = crowi.pageService.hasYjsDraft(page._id);
-    props.yjsAwarenessStateSize = crowi.pageService.getYjsAwarenessStateSize(page._id);
+    props.yjsData = {
+      hasDraft: crowi.pageService.hasYjsDraft(page._id),
+      awarenessStateSize: crowi.pageService.getYjsAwarenessStateSize(page._id),
+    };
   }
   }
 }
 }
 
 

+ 28 - 0
apps/app/src/stores/yjs.ts

@@ -0,0 +1,28 @@
+import { useCallback } from 'react';
+
+import { useSWRStatic } from '@growi/core/dist/swr';
+import { type SWRResponse } from 'swr';
+
+export type CurrentPageYjsDataStates = {
+  hasDraft?: boolean,
+  awarenessStateSize?: number,
+}
+
+type CurrentPageYjsDataUtils = {
+  updateHasDraft(hasYjsDraft: boolean): void
+  updateAwarenessStateSize(awarenessStateSize: number): void
+}
+
+export const useCurrentPageYjsData = (initialValue?: CurrentPageYjsDataStates): SWRResponse<CurrentPageYjsDataStates, Error> & CurrentPageYjsDataUtils => {
+  const swrResponse = useSWRStatic<CurrentPageYjsDataStates, Error>('currentPageYjsData', undefined, { fallbackData: initialValue });
+
+  const updateHasDraft = useCallback((hasDraft: boolean) => {
+    swrResponse.mutate({ ...swrResponse.data, hasDraft });
+  }, [swrResponse]);
+
+  const updateAwarenessStateSize = useCallback((awarenessStateSize: number) => {
+    swrResponse.mutate({ ...swrResponse.data, awarenessStateSize });
+  }, [swrResponse]);
+
+  return { ...swrResponse, updateHasDraft, updateAwarenessStateSize };
+};