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

Merge pull request #10760 from growilabs/feat/175879-realtime-increment-view-count

feat: Realtime Increment View Count Without Refreshing Pages
mergify[bot] 2 месяцев назад
Родитель
Сommit
89538c8029

+ 2 - 0
apps/app/src/client/components/Page/EditablePageEffects.tsx

@@ -1,5 +1,6 @@
 import type { JSX } from 'react';
 import type { JSX } from 'react';
 
 
+import { usePageSeenUsersUpdatedEffect } from '~/client/services/side-effects/page-seen-users-updated';
 import { usePageUpdatedEffect } from '~/client/services/side-effects/page-updated';
 import { usePageUpdatedEffect } from '~/client/services/side-effects/page-updated';
 import {
 import {
   useAwarenessSyncingEffect,
   useAwarenessSyncingEffect,
@@ -9,6 +10,7 @@ import {
 
 
 export const EditablePageEffects = (): JSX.Element => {
 export const EditablePageEffects = (): JSX.Element => {
   usePageUpdatedEffect();
   usePageUpdatedEffect();
+  usePageSeenUsersUpdatedEffect();
 
 
   useCurrentPageYjsDataAutoLoadEffect();
   useCurrentPageYjsDataAutoLoadEffect();
   useNewlyYjsDataSyncingEffect();
   useNewlyYjsDataSyncingEffect();

+ 33 - 0
apps/app/src/client/services/side-effects/page-seen-users-updated.ts

@@ -0,0 +1,33 @@
+import { useCallback, useEffect } from 'react';
+
+import { SocketEventName } from '~/interfaces/websocket';
+import { useCurrentPageId } from '~/states/page';
+import { useGlobalSocket } from '~/states/socket-io';
+import { useSWRxPageInfo } from '~/stores/page';
+
+export const usePageSeenUsersUpdatedEffect = (): void => {
+  const socket = useGlobalSocket();
+  const currentPageId = useCurrentPageId();
+  const { mutate: mutatePageInfo } = useSWRxPageInfo(currentPageId);
+
+  const seenUsersUpdatedHandler = useCallback(
+    (data: { pageId: string }) => {
+      if (currentPageId != null && currentPageId === data.pageId) {
+        mutatePageInfo();
+      }
+    },
+    [currentPageId, mutatePageInfo],
+  );
+
+  useEffect(() => {
+    if (socket == null) {
+      return;
+    }
+
+    socket.on(SocketEventName.PageSeenUsersUpdated, seenUsersUpdatedHandler);
+
+    return () => {
+      socket.off(SocketEventName.PageSeenUsersUpdated, seenUsersUpdatedHandler);
+    };
+  }, [seenUsersUpdatedHandler, socket]);
+};

+ 1 - 0
apps/app/src/interfaces/websocket.ts

@@ -48,6 +48,7 @@ export const SocketEventName = {
   PageCreated: 'page:create',
   PageCreated: 'page:create',
   PageUpdated: 'page:update',
   PageUpdated: 'page:update',
   PageDeleted: 'page:delete',
   PageDeleted: 'page:delete',
+  PageSeenUsersUpdated: 'page:seenUsersUpdated',
 
 
   // Yjs
   // Yjs
   YjsAwarenessStateSizeUpdated: 'yjs:awareness-state-size-update',
   YjsAwarenessStateSizeUpdated: 'yjs:awareness-state-size-update',

+ 17 - 0
apps/app/src/server/service/system-events/sync-page-status.ts

@@ -1,3 +1,4 @@
+import { SocketEventName } from '~/interfaces/websocket';
 import type Crowi from '~/server/crowi';
 import type Crowi from '~/server/crowi';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
@@ -136,6 +137,22 @@ class SyncPageStatusService implements S2sMessageHandlable {
 
 
       this.publishToOtherServers('page:delete', { s2cMessagePageUpdated });
       this.publishToOtherServers('page:delete', { s2cMessagePageUpdated });
     });
     });
+
+    this.emitter.on('addSeenUsers', (page) => {
+      logger.debug("'addSeenUsers' event emitted.");
+
+      const pageId = page._id.toString();
+
+      // emit to the room for each page
+      socketIoService
+        .getDefaultSocket()
+        .in(getRoomNameWithId(RoomPrefix.PAGE, page._id))
+        .emit(SocketEventName.PageSeenUsersUpdated, { pageId });
+
+      this.publishToOtherServers(SocketEventName.PageSeenUsersUpdated, {
+        pageId,
+      });
+    });
   }
   }
 }
 }