Shun Miyazawa 1 год назад
Родитель
Сommit
2af21c3e40

+ 6 - 0
apps/app/src/interfaces/yjs.ts

@@ -3,3 +3,9 @@ export type CurrentPageYjsDraft = {
 }
 
 export const CurrentPageYjsDraftData = { hasYjsDraft: true };
+
+export type CurrentPageYjsData = {
+  hasDraft?: boolean,
+  hasRevisionBodyDiff?: boolean,
+  awarenessStateSize?: number,
+}

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

@@ -27,6 +27,7 @@ import { SupportedAction, type SupportedActionType } from '~/interfaces/activity
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { RendererConfig } from '~/interfaces/services/renderer';
 import type { ISidebarConfig } from '~/interfaces/sidebar-config';
+import type { CurrentPageYjsData } from '~/interfaces/yjs';
 import type { PageModel, PageDocument } from '~/server/models/page';
 import type { PageRedirectModel } from '~/server/models/page-redirect';
 import {
@@ -49,7 +50,7 @@ import {
 import { useRedirectFrom } from '~/stores/page-redirect';
 import { useRemoteRevisionId } from '~/stores/remote-latest-page';
 import { useSetupGlobalSocket, useSetupGlobalSocketForPage } from '~/stores/websocket';
-import { useCurrentPageYjsData, type CurrentPageYjsDataStates } from '~/stores/yjs';
+import { useCurrentPageYjsData } from '~/stores/yjs';
 import loggerFactory from '~/utils/logger';
 
 import { BasicLayout } from '../components/Layout/BasicLayout';
@@ -173,7 +174,7 @@ type Props = CommonProps & {
   skipSSR: boolean,
   ssrMaxRevisionBodyLength: number,
 
-  yjsData: CurrentPageYjsDataStates,
+  yjsData: CurrentPageYjsData,
 
   rendererConfig: RendererConfig,
 };
@@ -495,10 +496,9 @@ async function injectRoutingInformation(context: GetServerSidePropsContext, prop
       }
     }
 
-    props.yjsData = {
-      hasDraft: crowi.pageService.hasYjsDraft(page._id),
-      awarenessStateSize: crowi.pageService.getYjsAwarenessStateSize(page._id),
-    };
+    if (!props.skipSSR) {
+      props.yjsData = crowi.pageService.getYjsData(page._id, props.pageWithMeta?.data.revision?.body);
+    }
   }
 }
 

+ 8 - 7
apps/app/src/server/service/page/index.ts

@@ -33,6 +33,7 @@ import {
 } from '~/interfaces/page-operation';
 import { PageActionOnGroupDelete } from '~/interfaces/user-group';
 import { SocketEventName, type PageMigrationErrorData, type UpdateDescCountRawData } from '~/interfaces/websocket';
+import type { CurrentPageYjsData } from '~/interfaces/yjs';
 import type { CreateMethod } from '~/server/models/page';
 import {
   type PageModel, type PageDocument, pushRevision, PageQueryBuilder,
@@ -4448,16 +4449,16 @@ class PageService implements IPageService {
     });
   }
 
-  hasYjsDraft(pageId: string): boolean {
+  getYjsData(pageId: string, revisionBody?: string): CurrentPageYjsData {
     const yjsConnectionManager = getYjsConnectionManager();
     const currentYdoc = yjsConnectionManager.getCurrentYdoc(pageId);
-    return currentYdoc != null;
-  }
+    const yjsDraft = currentYdoc?.getText('codemirror').toString();
 
-  getYjsAwarenessStateSize(pageId: string): number {
-    const yjsConnectionManager = getYjsConnectionManager();
-    const currentYdoc = yjsConnectionManager.getCurrentYdoc(pageId);
-    return currentYdoc?.awareness.states.size ?? 0;
+    return {
+      hasDraft: currentYdoc != null,
+      hasRevisionBodyDiff: yjsDraft != null && revisionBody != null && yjsDraft !== revisionBody,
+      awarenessStateSize: currentYdoc?.awareness.states.size,
+    };
   }
 
   async createTtlIndex(): Promise<void> {

+ 4 - 7
apps/app/src/stores/yjs.ts

@@ -1,20 +1,17 @@
 import { useCallback } from 'react';
 
 import { useSWRStatic } from '@growi/core/dist/swr';
-import { type SWRResponse } from 'swr';
+import type { SWRResponse } from 'swr';
 
-export type CurrentPageYjsDataStates = {
-  hasDraft?: boolean,
-  awarenessStateSize?: number,
-}
+import type { CurrentPageYjsData } from '~/interfaces/yjs';
 
 type CurrentPageYjsDataUtils = {
   updateHasDraft(hasYjsDraft: boolean): void
   updateAwarenessStateSize(awarenessStateSize: number): void
 }
 
-export const useCurrentPageYjsData = (): SWRResponse<CurrentPageYjsDataStates, Error> & CurrentPageYjsDataUtils => {
-  const swrResponse = useSWRStatic<CurrentPageYjsDataStates, Error>('currentPageYjsData', undefined);
+export const useCurrentPageYjsData = (): SWRResponse<CurrentPageYjsData, Error> & CurrentPageYjsDataUtils => {
+  const swrResponse = useSWRStatic<CurrentPageYjsData, Error>('currentPageYjsData', undefined);
 
   const updateHasDraft = useCallback((hasDraft: boolean) => {
     swrResponse.mutate({ ...swrResponse.data, hasDraft });