From 3003ac965f04b41ec5ff534460b1a84560627c10 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Fri, 12 Nov 2021 19:36:04 +0800 Subject: [PATCH] feat: wip: new-virtualized-list --- web/package.json | 2 + .../ChatMessageList/VirtualizedList.new.tsx | 175 ++++++++++++++++++ .../ChatBox/ChatMessageList/index.tsx | 3 +- yarn.lock | 29 ++- 4 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 web/src/components/ChatBox/ChatMessageList/VirtualizedList.new.tsx diff --git a/web/package.json b/web/package.json index d9af4a3b..24a31d35 100644 --- a/web/package.json +++ b/web/package.json @@ -39,6 +39,7 @@ "react-router-dom": "^5.2.0", "react-transition-group": "^4.4.2", "react-use-gesture": "^9.1.3", + "react-virtualized": "^9.22.3", "react-virtualized-auto-sizer": "^1.0.6", "socket.io-client": "^4.1.2", "str2int": "^1.1.0", @@ -63,6 +64,7 @@ "@types/react-router": "^5.1.15", "@types/react-router-dom": "^5.1.7", "@types/react-transition-group": "^4.4.2", + "@types/react-virtualized": "^9.21.14", "@types/react-virtualized-auto-sizer": "^1.0.1", "@types/webpack": "^5.28.0", "@types/webpack-dev-server": "^4.3.1", diff --git a/web/src/components/ChatBox/ChatMessageList/VirtualizedList.new.tsx b/web/src/components/ChatBox/ChatMessageList/VirtualizedList.new.tsx new file mode 100644 index 00000000..0ebaa3c0 --- /dev/null +++ b/web/src/components/ChatBox/ChatMessageList/VirtualizedList.new.tsx @@ -0,0 +1,175 @@ +import React, { + useEffect, + useLayoutEffect, + useMemo, + useRef, + useState, +} from 'react'; +import AutoSizer from 'react-virtualized-auto-sizer'; +import { ChatMessage, t, usePrevious, useUpdateRef } from 'tailchat-shared'; +import { messageReverseItemId } from './const'; +import { buildMessageItemRow } from './Item'; +import type { MessageListProps } from './types'; +import { + List, + CellMeasurer, + CellMeasurerCache, + ListRowRenderer, + InfiniteLoader, +} from 'react-virtualized'; + +// const OVERSCAN_COUNT_BACKWARD = 80; +// const OVERSCAN_COUNT_FORWARD = 80; +// const HEIGHT_TRIGGER_FOR_MORE_POSTS = 200; // 触发加载更多的方法 + +// const postListStyle = { +// padding: '14px 0px 7px', +// }; + +// const virtListStyles: React.CSSProperties = { +// position: 'absolute', +// bottom: 0, +// maxHeight: '100%', +// }; + +// const dynamicListStyle: React.CSSProperties = {}; // TODO + +export const VirtualizedMessageList: React.FC = React.memo( + (props) => { + const listRef = useRef(null); + // const postListRef = useRef(null); + // const [isBottom, setIsBottom] = useState(true); + // useLockScroll(props.messages, listRef); + + useEffect(() => { + listRef.current?.scrollToRow(props.messages.length - 1); + }, [props.messages]); + + // const handleScroll = (info: OnScrollInfo) => { + // const { + // clientHeight, + // scrollOffset, + // scrollHeight, + // scrollDirection, + // scrollUpdateWasRequested, + // } = info; + // if (scrollHeight <= 0) { + // return; + // } + + // const didUserScrollBackwards = + // scrollDirection === 'backward' && !scrollUpdateWasRequested; + // const isOffsetWithInRange = scrollOffset < HEIGHT_TRIGGER_FOR_MORE_POSTS; + + // if ( + // didUserScrollBackwards && + // isOffsetWithInRange && + // !props.isLoadingMore + // ) { + // // 加载更多历史信息 + // props.onLoadMore(); + // } + + // if (clientHeight + scrollOffset === scrollHeight) { + // // 当前滚动条位于底部 + // setIsBottom(true); + // props.onUpdateReadedMessage( + // props.messages[props.messages.length - 1]._id + // ); + // } + // }; + + // const onUpdateReadedMessageRef = useUpdateRef(props.onUpdateReadedMessage); + // useEffect(() => { + // if (props.messages.length === 0) { + // return; + // } + + // if (postListRef.current?.scrollTop === 0) { + // // 当前列表在最低 + // onUpdateReadedMessageRef.current( + // props.messages[props.messages.length - 1]._id + // ); + // } + // }, [props.messages.length]); + + /** + * 渲染列表元素 + */ + const rowRenderer: ListRowRenderer = ({ index, key, parent, style }) => { + // if (key === messageReverseItemId.OLDER_MESSAGES_LOADER) { + // return ( + //
+ // {t('加载中...')} + //
+ // ); + // } else if (key === messageReverseItemId.TEXT_CHANNEL_INTRO) { + // return ( + //
+ // {t('到顶了')} + //
+ // ); + // } + + return ( + + {({ measure, registerChild }) => ( +
el && registerChild && registerChild(el)} + onLoad={measure} + style={style} + > + {buildMessageItemRow(props.messages, props.messages[index]._id)} + {/* {buildMessageItemRow(props.messages, key)} */} +
+ )} +
+ ); + }; + // const itemData = useMemo( + // () => [ + // ...props.messages.map((m) => m._id).reverse(), + // props.hasMoreMessage + // ? messageReverseItemId.OLDER_MESSAGES_LOADER + // : messageReverseItemId.TEXT_CHANNEL_INTRO, + // ], + // [props.messages, props.hasMoreMessage] + // ); + + const measurerCache = useMemo( + () => + new CellMeasurerCache({ + fixedWidth: true, + minHeight: 24, + }), + [] + ); + + return ( + + {({ height, width }) => ( + console.log(startIndex)} + scrollToIndex={props.messages.length - 1} + scrollToAlignment="end" + /> + )} + + ); + } +); +VirtualizedMessageList.displayName = 'VirtualizedMessageList'; diff --git a/web/src/components/ChatBox/ChatMessageList/index.tsx b/web/src/components/ChatBox/ChatMessageList/index.tsx index 9d86017c..7dfe95ab 100644 --- a/web/src/components/ChatBox/ChatMessageList/index.tsx +++ b/web/src/components/ChatBox/ChatMessageList/index.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { NormalMessageList } from './NormalList'; import type { MessageListProps } from './types'; -import { VirtualizedMessageList } from './VirtualizedList'; +// import { VirtualizedMessageList } from './VirtualizedList'; +import { VirtualizedMessageList } from './VirtualizedList.new'; const useVirtualizedList = true; // 是否使用虚拟化列表 diff --git a/yarn.lock b/yarn.lock index 7074b1a1..536a43b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2134,6 +2134,14 @@ dependencies: "@types/react" "*" +"@types/react-virtualized@^9.21.14": + version "9.21.14" + resolved "https://registry.npmmirror.com/@types/react-virtualized/download/@types/react-virtualized-9.21.14.tgz#8d465aa54386a7bebc7b61f71afc588bb800b868" + integrity sha1-jUZapUOGp768e2H3GvxYi7gAuGg= + dependencies: + "@types/prop-types" "*" + "@types/react" "*" + "@types/react@*", "@types/react@^17.0.11": version "17.0.11" resolved "https://registry.npmjs.org/@types/react/-/react-17.0.11.tgz#67fcd0ddbf5a0b083a0f94e926c7d63f3b836451" @@ -3596,7 +3604,7 @@ cloneable-readable@^1.0.0: process-nextick-args "^2.0.0" readable-stream "^2.3.5" -clsx@^1.1.1: +clsx@^1.0.4, clsx@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== @@ -4418,7 +4426,7 @@ dom-converter@^0.2.0: dependencies: utila "~0.4" -dom-helpers@^5.0.1: +dom-helpers@^5.0.1, dom-helpers@^5.1.3: version "5.2.1" resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== @@ -9123,6 +9131,11 @@ react-is@^17.0.1: resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.npmmirror.com/react-lifecycles-compat/download/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha1-TxonOv38jzSIqMUWv9p4+HI1I2I= + "react-native-storage@npm:@trpgengine/react-native-storage@^1.0.1": version "1.0.1" resolved "https://registry.npmjs.org/@trpgengine/react-native-storage/-/react-native-storage-1.0.1.tgz#7571ec0d837150a4eec123ae7b938084b3c70413" @@ -9206,6 +9219,18 @@ react-virtualized-auto-sizer@^1.0.6: resolved "https://registry.nlark.com/react-virtualized-auto-sizer/download/react-virtualized-auto-sizer-1.0.6.tgz#66c5b1c9278064c5ef1699ed40a29c11518f97ca" integrity sha1-ZsWxySeAZMXvFpntQKKcEVGPl8o= +react-virtualized@^9.22.3: + version "9.22.3" + resolved "https://registry.nlark.com/react-virtualized/download/react-virtualized-9.22.3.tgz#f430f16beb0a42db420dbd4d340403c0de334421" + integrity sha1-9DDxa+sKQttCDb1NNAQDwN4zRCE= + dependencies: + "@babel/runtime" "^7.7.2" + clsx "^1.0.4" + dom-helpers "^5.1.3" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-lifecycles-compat "^3.0.4" + react@^17.0.2: version "17.0.2" resolved "https://registry.npmjs.org/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"