From a03312b8168390f62a28bf02bcabd6ebeaa94e31 Mon Sep 17 00:00:00 2001 From: fantasticit Date: Sat, 18 Jun 2022 00:13:02 +0800 Subject: [PATCH] tiptap: add lazy render for flow and mind --- packages/client/package.json | 1 + .../src/tiptap/core/wrappers/flow/index.tsx | 79 +++++++++------ .../src/tiptap/core/wrappers/mind/index.tsx | 98 ++++++++++++------- pnpm-lock.yaml | 31 +++--- 4 files changed, 123 insertions(+), 86 deletions(-) diff --git a/packages/client/package.json b/packages/client/package.json index 18ca1993..e1c7f94f 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -90,6 +90,7 @@ "react-pdf": "^5.7.2", "react-query": "^3.39.0", "react-split-pane": "^0.1.92", + "react-visibility-sensor": "^5.1.1", "requestidlecallback-polyfill": "^1.0.2", "resize-observer-polyfill": "^1.5.1", "scroll-into-view-if-needed": "^2.2.29", diff --git a/packages/client/src/tiptap/core/wrappers/flow/index.tsx b/packages/client/src/tiptap/core/wrappers/flow/index.tsx index 1b2a8572..719ac12f 100644 --- a/packages/client/src/tiptap/core/wrappers/flow/index.tsx +++ b/packages/client/src/tiptap/core/wrappers/flow/index.tsx @@ -5,6 +5,7 @@ import { IconFlow, IconMindCenter, IconZoomIn, IconZoomOut } from 'components/ic import { Resizeable } from 'components/resizeable'; import { useToggle } from 'hooks/use-toggle'; import { useCallback, useEffect, useRef, useState } from 'react'; +import VisibilitySensor from 'react-visibility-sensor'; import { load, renderXml } from 'thirtypart/diagram'; import { Flow } from 'tiptap/core/extensions/flow'; import { getEditorContainerDOMSize } from 'tiptap/prose-utils'; @@ -22,6 +23,7 @@ export const FlowWrapper = ({ editor, node, updateAttributes }) => { const $graph = useRef(null); const $container = useRef(); const [bgColor, setBgColor] = useState('var(--semi-color-bg-3)'); + const [visible, toggleVisible] = useToggle(false); const [loading, toggleLoading] = useToggle(true); const [error, setError] = useState(null); @@ -77,6 +79,15 @@ export const FlowWrapper = ({ editor, node, updateAttributes }) => { [render] ); + const onViewportChange = useCallback( + (visible) => { + if (visible) { + toggleVisible(true); + } + }, + [toggleVisible] + ); + useEffect(() => { load() .catch(setError) @@ -85,40 +96,44 @@ export const FlowWrapper = ({ editor, node, updateAttributes }) => { return ( - -
- {loading && ( -
- - {/* FIXME: semi-design 的问题,不加 div,文字会换行! */} -
-
-
- )} - {error && {(error && error.message) || '未知错误'}} - {!loading && !error &&
} -
+ + +
+ {loading && ( +
+ + {/* FIXME: semi-design 的问题,不加 div,文字会换行! */} +
+
+
+ )} -
- - - - - 流程图 - -
+ {error && {(error && error.message) || '未知错误'}} -
- -
- + {!loading && !error && visible &&
} +
+ +
+ + + + + 流程图 + +
+ +
+ +
+
+
); }; diff --git a/packages/client/src/tiptap/core/wrappers/mind/index.tsx b/packages/client/src/tiptap/core/wrappers/mind/index.tsx index 4dd7e991..f914af24 100644 --- a/packages/client/src/tiptap/core/wrappers/mind/index.tsx +++ b/packages/client/src/tiptap/core/wrappers/mind/index.tsx @@ -7,6 +7,7 @@ import { Tooltip } from 'components/tooltip'; import deepEqual from 'deep-equal'; import { useToggle } from 'hooks/use-toggle'; import { useCallback, useEffect, useRef, useState } from 'react'; +import VisibilitySensor from 'react-visibility-sensor'; import { load, renderMind } from 'thirtypart/kityminder'; import { Mind } from 'tiptap/core/extensions/mind'; import { MAX_ZOOM, MIN_ZOOM, ZOOM_STEP } from 'tiptap/core/menus/mind/constant'; @@ -24,6 +25,7 @@ export const MindWrapper = ({ editor, node, updateAttributes }) => { const isActive = editor.isActive(Mind.name); const { width: maxWidth } = getEditorContainerDOMSize(editor); const { data, width, height } = node.attrs; + const [visible, toggleVisible] = useToggle(false); const [loading, toggleLoading] = useToggle(true); const [error, setError] = useState(null); @@ -76,6 +78,15 @@ export const MindWrapper = ({ editor, node, updateAttributes }) => { [render] ); + const onViewportChange = useCallback( + (visible) => { + if (visible) { + toggleVisible(true); + } + }, + [toggleVisible] + ); + useEffect(() => { load() .catch(setError) @@ -98,46 +109,59 @@ export const MindWrapper = ({ editor, node, updateAttributes }) => { return ( - -
- {error && ( -
- {error.message || error} + + +
+ {error && ( +
+ {error.message || error} +
+ )} + + {loading && } + + {!loading && !error && visible && ( +
+ )} + +
+ + + + + 思维导图 +
- )} - {loading && } - {!loading && !error && ( -
- )} -
- - - - - 思维导图 - +
+ +
- -
- -
-
-
+ +
); }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 43392068..5ee6947e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -135,6 +135,7 @@ importers: react-pdf: ^5.7.2 react-query: ^3.39.0 react-split-pane: ^0.1.92 + react-visibility-sensor: ^5.1.1 requestidlecallback-polyfill: ^1.0.2 resize-observer-polyfill: ^1.5.1 scroll-into-view-if-needed: ^2.2.29 @@ -228,6 +229,7 @@ importers: react-pdf: 5.7.2_react-dom@17.0.2+react@17.0.2 react-query: 3.39.0_react-dom@17.0.2+react@17.0.2 react-split-pane: 0.1.92_react-dom@17.0.2+react@17.0.2 + react-visibility-sensor: 5.1.1_react-dom@17.0.2+react@17.0.2 requestidlecallback-polyfill: 1.0.2 resize-observer-polyfill: 1.5.1 scroll-into-view-if-needed: 2.2.29 @@ -246,7 +248,7 @@ importers: eslint: 8.14.0 eslint-config-prettier: 8.5.0_eslint@8.14.0 eslint-plugin-import: 2.26.0_eslint@8.14.0 - eslint-plugin-prettier: 4.0.0_74ebb802163a9b4fa8f89d76ed02f62a + eslint-plugin-prettier: 4.0.0_740be41c8168d0cc214a306089357ad0 eslint-plugin-react: 7.29.4_eslint@8.14.0 eslint-plugin-react-hooks: 4.5.0_eslint@8.14.0 eslint-plugin-simple-import-sort: 7.0.0_eslint@8.14.0 @@ -5603,22 +5605,6 @@ packages: prettier-linter-helpers: 1.0.0 dev: true - /eslint-plugin-prettier/4.0.0_74ebb802163a9b4fa8f89d76ed02f62a: - resolution: {integrity: sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==} - engines: {node: '>=6.0.0'} - peerDependencies: - eslint: '>=7.28.0' - eslint-config-prettier: '*' - prettier: '>=2.0.0' - peerDependenciesMeta: - eslint-config-prettier: - optional: true - dependencies: - eslint: 8.14.0 - eslint-config-prettier: 8.5.0_eslint@8.14.0 - prettier-linter-helpers: 1.0.0 - dev: true - /eslint-plugin-react-hooks/4.5.0_eslint@8.14.0: resolution: {integrity: sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw==} engines: {node: '>=10'} @@ -9611,6 +9597,17 @@ packages: prop-types: 15.8.1 dev: false + /react-visibility-sensor/5.1.1_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-cTUHqIK+zDYpeK19rzW6zF9YfT4486TIgizZW53wEZ+/GPBbK7cNS0EHyJVyHYacwFEvvHLEKfgJndbemWhB/w==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + prop-types: 15.8.1 + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + dev: false + /react-window/1.8.6_react-dom@17.0.2+react@17.0.2: resolution: {integrity: sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg==} engines: {node: '>8.0.0'}