From 3e6b89ab394456105be38ec2498dab8f06db629f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Tue, 21 Mar 2023 13:49:24 +0800 Subject: [PATCH] =?UTF-8?q?fix(view):=E6=9B=B4=E6=8D=A2=E8=99=9A=E6=8B=9F?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=94=AF=E6=8C=81=E5=BA=93=EF=BC=8C=E4=BB=A5?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E7=BC=A9=E6=94=BE=E5=AD=98=E5=9C=A8=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- pnpm-lock.yaml | 20 +++++------- src/components/ContinuationView.tsx | 47 ++++++++++++++--------------- src/components/FileList.tsx | 37 +++++++++++++---------- 4 files changed, 51 insertions(+), 55 deletions(-) diff --git a/package.json b/package.json index 575fad6..0fc0ac8 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-use": "^17.4.0", - "react-window": "^1.8.8", + "react-virtuoso": "^4.1.0", "use-immer": "^0.8.1", "zustand": "^4.2.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0516282..27cbedc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,7 +28,7 @@ specifiers: react: ^18.2.0 react-dom: ^18.2.0 react-use: ^17.4.0 - react-window: ^1.8.8 + react-virtuoso: ^4.1.0 typescript: ^4.6.4 use-immer: ^0.8.1 vite: ^4.0.0 @@ -53,7 +53,7 @@ dependencies: react: 18.2.0 react-dom: 18.2.0_react@18.2.0 react-use: 17.4.0_biqbaboplfbrettd7655fr4n2y - react-window: 1.8.8_biqbaboplfbrettd7655fr4n2y + react-virtuoso: 4.1.0_biqbaboplfbrettd7655fr4n2y use-immer: 0.8.1_immer@9.0.19+react@18.2.0 zustand: 4.3.6_immer@9.0.19+react@18.2.0 @@ -1526,10 +1526,6 @@ packages: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} dev: false - /memoize-one/5.2.1: - resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} - dev: false - /ms/2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true @@ -1750,15 +1746,13 @@ packages: tslib: 2.5.0 dev: false - /react-window/1.8.8_biqbaboplfbrettd7655fr4n2y: - resolution: {integrity: sha512-D4IiBeRtGXziZ1n0XklnFGu7h9gU684zepqyKzgPNzrsrk7xOCxni+TCckjg2Nr/DiaEEGVVmnhYSlT2rB47dQ==} - engines: {node: '>8.0.0'} + /react-virtuoso/4.1.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-Vcq5WXn18PvPT55kdeGQ8BN3K95XyPe7hum8zG6Tx7g1CtUYVsQKN7fouMxBSy+XymEDB5ynGy8JWhuqyLLtPw==} + engines: {node: '>=10'} peerDependencies: - react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react: '>=16 || >=17 || >= 18' + react-dom: '>=16 || >=17 || >= 18' dependencies: - '@babel/runtime': 7.21.0 - memoize-one: 5.2.1 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 dev: false diff --git a/src/components/ContinuationView.tsx b/src/components/ContinuationView.tsx index 669e143..df6bc9a 100644 --- a/src/components/ContinuationView.tsx +++ b/src/components/ContinuationView.tsx @@ -1,35 +1,34 @@ //@ts-nocheck import EventEmitter from 'events'; -import { indexOf, isEmpty, length, map, mergeLeft, pluck, range } from 'ramda'; +import { indexOf, isEmpty, length, map, pluck, range } from 'ramda'; import { FC, useCallback, useContext, useEffect, useMemo, useRef } from 'react'; -import { VariableSizeList } from 'react-window'; +import { ListRange, Virtuoso, VirtuosoHandle } from 'react-virtuoso'; import { EventBusContext } from '../EventBus'; import { sortedFilesSelector, useFileListStore } from '../states/files'; import { useZoomState } from '../states/zoom'; export const ContinuationView: FC = () => { const files = useFileListStore(sortedFilesSelector()); - const zoom = useZoomState.use.currentZoom(); - const viewHeight = useZoomState.use.viewHeight(); + const { currentZoom: zoom, viewWidth, viewHeight } = useZoomState(); const updateActives = useFileListStore.use.updateActiveFiles(); const fileCount = useMemo(() => length(files), [files]); const ebus = useContext(EventBusContext); - const virtualListRef = useRef(); + const virtualListRef = useRef(null); const handleOnRenderAction = useCallback( - ({ visibleStartIndex, visibleStopIndex }) => { - updateActives(map(i => files[i].filename, range(visibleStartIndex, visibleStopIndex + 1))); + ({ startIndex, endIndex }: ListRange) => { + updateActives(map(i => files[i].filename, range(startIndex, endIndex + 1))); }, [files] ); - const fileHeights = useMemo(() => map(item => item.height * (zoom / 100), files), [files, zoom]); + const maxImageWidth = useMemo(() => viewWidth * (zoom / 100), [viewWidth, zoom]); useEffect(() => { ebus?.addListener('navigate_offset', ({ filename }) => { let index = indexOf(filename, pluck('filename', files)); - virtualListRef.current?.scrollToItem(index); + virtualListRef.current?.scrollToIndex({ index, align: 'start', behavior: 'smooth' }); }); ebus?.addListener('reset_views', () => { - virtualListRef.current?.scrollTo(0); + virtualListRef.current?.scrollTo({ top: 0 }); }); return () => { ebus?.removeAllListeners('navigate_offset'); @@ -46,29 +45,27 @@ export const ContinuationView: FC = () => { }} > {!isEmpty(files) && ( - fileHeights[index]} - itemKey={index => files[index].id} - height={viewHeight} - width="100%" + - {({ index, style, data }) => ( + totalCount={fileCount} + computeItemKey={index => files[index].id} + rangeChanged={handleOnRenderAction} + itemContent={index => (
- +
)} -
+ /> )} ); diff --git a/src/components/FileList.tsx b/src/components/FileList.tsx index 2dd41d4..17800bb 100644 --- a/src/components/FileList.tsx +++ b/src/components/FileList.tsx @@ -1,10 +1,10 @@ //@ts-nocheck import { Box, Center, Text, Tooltip } from '@mantine/core'; import EventEmitter from 'events'; -import { head, includes, indexOf, isEmpty, length, mergeLeft, not, pluck } from 'ramda'; +import { head, includes, indexOf, isEmpty, length, not, pluck } from 'ramda'; import { FC, useCallback, useContext, useLayoutEffect, useMemo, useRef } from 'react'; import { useMeasure } from 'react-use'; -import { FixedSizeList } from 'react-window'; +import { Virtuoso, VirtuosoHandle } from 'react-virtuoso'; import { EventBusContext } from '../EventBus'; import { sortedFilesSelector, useFileListStore } from '../states/files'; @@ -14,7 +14,7 @@ export const FileList: FC = () => { const ebus = useContext(EventBusContext); const filesCount = useMemo(() => length(files), [files]); const [parentRef, { height: parentHeight }] = useMeasure(); - const listRef = useRef(); + const listRef = useRef(null); const handleFileSelectAction = useCallback( (filename: string) => { ebus.emit('navigate_offset', { filename }); @@ -25,7 +25,11 @@ export const FileList: FC = () => { useLayoutEffect(() => { let firstActived = head(activeFiles); let firstActivedIndex = indexOf(firstActived, pluck('filename', files)); - listRef.current?.scrollToItem(firstActivedIndex, 'smart'); + listRef.current?.scrollToIndex({ + index: firstActivedIndex, + align: 'center', + behavior: 'auto' + }); }, [activeFiles]); return ( @@ -37,29 +41,30 @@ export const FileList: FC = () => { ref={parentRef} > {!isEmpty(files) && ( - - {({ index, style }) => ( + ( handleFileSelectAction(files[index].filename)} - sx={theme => - mergeLeft(style, { - cursor: 'pointer', - '&:hover': { - color: not(includes(files[index].filename, activeFiles)) && theme.colors.red - } - }) - } + sx={theme => ({ + cursor: 'pointer', + '&:hover': { + color: not(includes(files[index].filename, activeFiles)) && theme.colors.red + } + })} > - + {files[index].filename} )} - + /> )} {isEmpty(files) && (