From a9892a3fa83a8197f47de1544c33af922a47c585 Mon Sep 17 00:00:00 2001 From: fantasticit Date: Sat, 17 Sep 2022 17:17:53 +0800 Subject: [PATCH 1/2] client: improve perf --- .../src/components/color-picker/index.tsx | 44 ++-- .../src/components/data-render/constant.tsx | 30 ++- .../src/components/data-render/index.tsx | 7 +- .../document/collaboration/index.tsx | 56 ++-- .../src/components/document/editor/editor.tsx | 1 + .../src/components/document/editor/index.tsx | 20 +- .../src/components/emoji-picker/index.tsx | 70 ++--- .../client/src/components/message/index.tsx | 246 ++++++++++-------- .../client/src/components/size-setter.tsx | 7 +- .../client/src/components/wiki/tocs/tree.tsx | 1 + .../src/layouts/app-double-column/index.tsx | 4 +- .../src/layouts/app-router-header/recent.tsx | 102 ++++---- .../src/layouts/app-router-header/wiki.tsx | 110 ++++---- .../src/layouts/app-single-column/index.tsx | 12 +- .../src/layouts/double-column/index.tsx | 4 +- .../layouts/public-double-column/index.tsx | 4 +- .../src/layouts/single-column/index.tsx | 12 +- .../core/bubble-menu/bubble-menu-plugin.tsx | 5 +- .../src/tiptap/core/bubble-menu/index.tsx | 10 +- .../client/src/tiptap/core/menus/commands.tsx | 4 +- .../core/menus/document-reference/bubble.tsx | 63 +++-- .../src/tiptap/core/menus/heading/index.tsx | 23 +- .../src/tiptap/core/menus/insert/index.tsx | 42 +-- .../src/tiptap/core/menus/search/index.tsx | 24 +- .../collaboration/collaboration/index.tsx | 12 +- 25 files changed, 496 insertions(+), 417 deletions(-) diff --git a/packages/client/src/components/color-picker/index.tsx b/packages/client/src/components/color-picker/index.tsx index 8bcf22e0..0ea7ba69 100644 --- a/packages/client/src/components/color-picker/index.tsx +++ b/packages/client/src/components/color-picker/index.tsx @@ -89,25 +89,26 @@ export const ColorPicker: React.FC<{ const [visible, toggleVisible] = useToggle(false); const content = useMemo( - () => ( -
-
onSetColor(null)}> - - 无颜色 -
+ () => + !visible ? null : ( +
+
onSetColor(null)}> + + 无颜色 +
-
- {colors.map((color) => { - return ( -
onSetColor(color)}> - -
- ); - })} +
+ {colors.map((color) => { + return ( +
onSetColor(color)}> + +
+ ); + })} +
-
- ), - [onSetColor, isMobile] + ), + [onSetColor, isMobile, visible] ); if (disabled) return {children}; @@ -132,7 +133,14 @@ export const ColorPicker: React.FC<{ ) : ( - + {children} )} diff --git a/packages/client/src/components/data-render/constant.tsx b/packages/client/src/components/data-render/constant.tsx index 37847854..a0a78b41 100644 --- a/packages/client/src/components/data-render/constant.tsx +++ b/packages/client/src/components/data-render/constant.tsx @@ -4,25 +4,29 @@ import React, { useMemo } from 'react'; const { Text } = Typography; -export const defaultLoading = ; +export const defaultLoading = ( +
+ +
+); export const defaultRenderError = (error) => { return {(error && error.message) || '未知错误'}; }; +const emptyStyle: React.CSSProperties = { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column', + position: 'relative', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', +}; + export const defaultEmpty = ( -
+
diff --git a/packages/client/src/components/data-render/index.tsx b/packages/client/src/components/data-render/index.tsx index db8627e5..2b05bea1 100644 --- a/packages/client/src/components/data-render/index.tsx +++ b/packages/client/src/components/data-render/index.tsx @@ -1,3 +1,4 @@ +import deepEqual from 'deep-equal'; import React from 'react'; import { defaultEmpty, defaultLoading, defaultRenderError, Render } from './constant'; @@ -15,7 +16,7 @@ interface IProps { normalContent: RenderProps; } -export const DataRender: React.FC = ({ +export const _DataRender: React.FC = ({ loading, error, empty, @@ -36,3 +37,7 @@ export const DataRender: React.FC = ({ ); }; + +export const DataRender = React.memo(_DataRender, (prevProps, nextProps) => { + return deepEqual(prevProps, nextProps); +}); diff --git a/packages/client/src/components/document/collaboration/index.tsx b/packages/client/src/components/document/collaboration/index.tsx index 986d0979..bda5856a 100644 --- a/packages/client/src/components/document/collaboration/index.tsx +++ b/packages/client/src/components/document/collaboration/index.tsx @@ -16,27 +16,40 @@ interface IProps { const { Text } = Typography; +const mobileContainerStyle: React.CSSProperties = { maxWidth: '96vw', maxHeight: '60vh', overflow: 'auto' }; + +const pcContainerStyle: React.CSSProperties = { + width: 412, + maxWidth: '96vw', + padding: '0 24px', + maxHeight: '60vh', + overflow: 'auto', +}; + export const DocumentCollaboration: React.FC = ({ wikiId, documentId, disabled = false }) => { const { isMobile } = IsOnMobile.useHook(); const toastedUsersRef = useRef([]); const { user: currentUser } = useUser(); const [visible, toggleVisible] = useToggle(false); const [collaborationUsers, setCollaborationUsers] = useState([]); + const content = useMemo( - () => ( -
- -
- ), - [documentId] + () => + !visible ? null : ( +
+ +
+ ), + [visible, documentId] ); + const btn = useMemo( () => ( - ) : null - } - collapsible - > - {renderedList.map((list) => { - return ( - -
- {(list.data || []).map((ex) => ( -
selectEmoji(ex)}> - {ex} -
- ))} -
-
- ); - })} - -
- ), - [showClear, renderedList, selectEmoji, clear] + () => + !visible ? null : ( +
+ + 清除 + + ) : null + } + collapsible + > + {renderedList.map((list) => { + return ( + +
+ {(list.data || []).map((ex) => ( +
selectEmoji(ex)}> + {ex} +
+ ))} +
+
+ ); + })} +
+
+ ), + [visible, showClear, renderedList, selectEmoji, clear] ); useEffect(() => { diff --git a/packages/client/src/components/message/index.tsx b/packages/client/src/components/message/index.tsx index ae19d3bc..7d425ea7 100644 --- a/packages/client/src/components/message/index.tsx +++ b/packages/client/src/components/message/index.tsx @@ -8,7 +8,7 @@ import { IsOnMobile } from 'hooks/use-on-mobile'; import { useToggle } from 'hooks/use-toggle'; import { EmptyBoxIllustration } from 'illustrations/empty-box'; import Link from 'next/link'; -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import styles from './index.module.scss'; import { Placeholder } from './placeholder'; @@ -17,72 +17,74 @@ const { Text } = Typography; const PAGE_SIZE = 6; const MessagesRender = ({ messageData, loading, error, onClick = null, page = 1, onPageChange = null }) => { - const total = (messageData && messageData.total) || 0; - const messages = (messageData && messageData.data) || []; + const [messages, total] = useMemo( + () => [(messageData && messageData.data) || [], (messageData && messageData.total) || 0], + [messageData] + ); - const handleRead = (messageId) => { - onClick && onClick(messageId); - }; + const handleRead = useCallback( + (messageId) => { + onClick && onClick(messageId); + }, + [onClick] + ); + + const renderNormalContent = useCallback(() => { + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + }} + > + {messages.length ? ( + <> + {messages.map((msg) => { + return ( +
handleRead(msg.id)}> + + +
+ + {msg.title} + +
+
+ +
+ ); + })} + {total > PAGE_SIZE && ( +
+ +
+ )} + + ) : ( + } message="暂无消息" /> + )} +
+ ); + }, [handleRead, messages, onPageChange, page, total]); return ( - } - error={error} - normalContent={() => { - return ( -
{ - e.preventDefault(); - e.stopPropagation(); - }} - > - {messages.length ? ( - <> - {messages.map((msg) => { - return ( -
handleRead(msg.id)}> - - -
- - {msg.title} - -
-
- -
- ); - })} - {total > PAGE_SIZE && ( -
- -
- )} - - ) : ( - } message="暂无消息" /> - )} -
- ); - }} - /> + } error={error} normalContent={renderNormalContent} /> ); }; @@ -106,60 +108,83 @@ const MessageBox = () => { setPage: unreadSetPage, } = useUnreadMessages(); - const clearAll = () => { + const clearAll = useCallback(() => { Promise.all( (unreadMsgs.data || []).map((msg) => { return readMessage(msg.id); }) ); - }; + }, [readMessage, unreadMsgs]); const openModalOnMobile = useCallback(() => { if (!isMobile) return; toggleVisible(true); }, [isMobile, toggleVisible]); - const content = ( - 0 ? ( - - 全部已读 - - ) : null - } - > - - - - - - - - - - + const content = useMemo( + () => + visible ? ( + 0 ? ( + + 全部已读 + + ) : null + } + > + + + + + + + + + + + ) : null, + [ + allError, + allLoading, + allMsgs, + allPage, + allSetPage, + clearAll, + readError, + readLoading, + readMessage, + readMsgs, + readPage, + readSetPage, + unreadError, + unreadLoading, + unreadMsgs, + unreadPage, + unreadSetPage, + visible, + ] ); const btn = ( @@ -197,6 +222,8 @@ const MessageBox = () => { ) : ( {content}
} @@ -210,5 +237,8 @@ const MessageBox = () => { export const Message = () => { const { loading, error } = useUser(); - return } />; + + const renderNormalContent = useCallback(() => , []); + + return ; }; diff --git a/packages/client/src/components/size-setter.tsx b/packages/client/src/components/size-setter.tsx index a575e4c0..1ecec190 100644 --- a/packages/client/src/components/size-setter.tsx +++ b/packages/client/src/components/size-setter.tsx @@ -11,6 +11,9 @@ interface IProps { onOk: (arg: ISize) => void; } +const containerStyle = { padding: '0 12px 12px' }; +const inlineBlockStyle = { display: 'inline-block' }; + export const SizeSetter: React.FC = ({ width, maxWidth, height, onOk, children }) => { const $form = useRef(); @@ -27,7 +30,7 @@ export const SizeSetter: React.FC = ({ width, maxWidth, height, onOk, ch position={'bottomLeft'} spacing={10} render={ -
+
($form.current = formApi)} labelPosition="left"> @@ -38,7 +41,7 @@ export const SizeSetter: React.FC = ({ width, maxWidth, height, onOk, ch
} > - {children} + {children} ); }; diff --git a/packages/client/src/components/wiki/tocs/tree.tsx b/packages/client/src/components/wiki/tocs/tree.tsx index 87423261..2b8bf2f6 100644 --- a/packages/client/src/components/wiki/tocs/tree.tsx +++ b/packages/client/src/components/wiki/tocs/tree.tsx @@ -136,6 +136,7 @@ export const _Tree = ({ data, docAsLink, getDocLink, isShareMode = false, needAd defaultExpandedKeys={expandedKeys} expandedKeys={expandedKeys} onExpand={setExpandedKeys} + motion={false} /> {needAddDocument && }
diff --git a/packages/client/src/layouts/app-double-column/index.tsx b/packages/client/src/layouts/app-double-column/index.tsx index 39e20300..4788ed64 100644 --- a/packages/client/src/layouts/app-double-column/index.tsx +++ b/packages/client/src/layouts/app-double-column/index.tsx @@ -16,6 +16,8 @@ interface IProps { rightNode: React.ReactNode; } +const style = { width: '100%', height: '100%' }; + export const AppDoubleColumnLayout: React.FC = ({ leftNode, rightNode }) => { const { minWidth, maxWidth, width, isCollapsed, updateWidth, toggleCollapsed } = useDragableWidth(); const debounceUpdate = useMemo(() => throttle(updateWidth, 200), [updateWidth]); @@ -25,7 +27,7 @@ export const AppDoubleColumnLayout: React.FC = ({ leftNode, rightNode }) - +