Przeglądaj źródła

Merge pull request #6249 from weseek/fix/blink-on-init

fix: Blink section header on init
Yuki Takei 3 lat temu
rodzic
commit
c4889e4a17

+ 0 - 2
packages/app/src/client/legacy/crowi.js

@@ -1,5 +1,3 @@
-const { blinkElem, blinkSectionHeaderAtBoot } = require('../util/blink-section-header');
-
 /* eslint-disable react/jsx-filename-extension */
 require('jquery.cookie');
 

+ 1 - 0
packages/app/src/client/util/blink-section-header.ts

@@ -23,5 +23,6 @@ export const blinkSectionHeaderAtBoot = (): HTMLElement | undefined => {
   const elem = document.getElementById(id);
   if (elem != null && elem.tagName.match(/h\d+/i)) { // match h1, h2, h3...
     blinkElem(elem);
+    return elem;
   }
 };

+ 57 - 18
packages/app/src/components/Page.jsx

@@ -1,16 +1,19 @@
-import React, { useEffect, useRef } from 'react';
+import React, {
+  useCallback, useEffect, useMemo, useRef, useState,
+} from 'react';
 
 import PropTypes from 'prop-types';
-
+import { debounce } from 'throttle-debounce';
 
 import MarkdownTable from '~/client/models/MarkdownTable';
 import AppContainer from '~/client/services/AppContainer';
 import EditorContainer from '~/client/services/EditorContainer';
 import PageContainer from '~/client/services/PageContainer';
+import { blinkSectionHeaderAtBoot } from '~/client/util/blink-section-header';
 import { getOptionsToSave } from '~/client/util/editor';
 import GrowiRenderer from '~/services/renderer/growi-renderer';
 import {
-  useCurrentPagePath, useIsGuestUser,
+  useCurrentPagePath, useIsGuestUser, useIsBlinkedHeaderAtBoot,
 } from '~/stores/context';
 import { useSWRxSlackChannels, useIsSlackEnabled, usePageTagsForEditors } from '~/stores/editor';
 import { useViewRenderer } from '~/stores/renderer';
@@ -196,9 +199,43 @@ const PageWrapper = (props) => {
   const { data: grantGroupId } = useSelectedGrantGroupId();
   const { data: grantGroupName } = useSelectedGrantGroupName();
   const { data: growiRenderer } = useViewRenderer();
+  const { data: isBlinkedAtBoot, mutate: mutateBlinkedAtBoot } = useIsBlinkedHeaderAtBoot();
 
   const pageRef = useRef(null);
 
+  // *************************** Blink header at boot ***************************
+  const blinkOnInit = useCallback(() => {
+
+    const result = blinkSectionHeaderAtBoot();
+
+    if (result != null) {
+      mutateBlinkedAtBoot(true);
+    }
+  }, [mutateBlinkedAtBoot]);
+
+  const blinkOnInitDebounced = useMemo(() => debounce(500, blinkOnInit), [blinkOnInit]);
+
+  const observerForBlinkingOnInit = useCallback((elem) => {
+    if (isBlinkedAtBoot || elem == null) {
+      return;
+    }
+
+    const observerCallback = (mutationRecords) => {
+      mutationRecords.forEach(() => blinkOnInitDebounced());
+    };
+
+    const observer = new MutationObserver(observerCallback);
+    observer.observe(elem, { childList: true, subtree: true });
+
+    // first call for the situation that all rendering is complete at this point
+    blinkOnInitDebounced();
+
+    return function cleanup() {
+      observer.disconnect();
+    };
+  }, [blinkOnInitDebounced, isBlinkedAtBoot]);
+  // *******************************  end  *******************************
+
   // set handler to open DrawioModal
   useEffect(() => {
     const handler = (beginLineNumber, endLineNumber) => {
@@ -233,21 +270,23 @@ const PageWrapper = (props) => {
 
 
   return (
-    <Page
-      {...props}
-      ref={pageRef}
-      growiRenderer={growiRenderer}
-      pagePath={currentPagePath}
-      editorMode={editorMode}
-      isGuestUser={isGuestUser}
-      isMobile={isMobile}
-      isSlackEnabled={isSlackEnabled}
-      pageTags={pageTags}
-      slackChannels={slackChannelsData.toString()}
-      grant={grant}
-      grantGroupId={grantGroupId}
-      grantGroupName={grantGroupName}
-    />
+    <div ref={observerForBlinkingOnInit}>
+      <Page
+        {...props}
+        ref={pageRef}
+        growiRenderer={growiRenderer}
+        pagePath={currentPagePath}
+        editorMode={editorMode}
+        isGuestUser={isGuestUser}
+        isMobile={isMobile}
+        isSlackEnabled={isSlackEnabled}
+        pageTags={pageTags}
+        slackChannels={slackChannelsData.toString()}
+        grant={grant}
+        grantGroupId={grantGroupId}
+        grantGroupName={grantGroupName}
+      />
+    </div>
   );
 };
 

+ 4 - 0
packages/app/src/stores/context.tsx

@@ -190,6 +190,10 @@ export const useGrowiRendererConfig = (initialData?: GrowiRendererConfig): SWRRe
   return useStaticSWR('growiRendererConfig', initialData);
 };
 
+export const useIsBlinkedHeaderAtBoot = (): SWRResponse<boolean, Error> => {
+  return useStaticSWR('isBlinkedAtBoot', undefined, { fallbackData: false });
+};
+
 
 /** **********************************************************
  *                     Computed contexts