refactor(view):调整无限列表功能所使用的库。
This commit is contained in:
		| @@ -1,13 +1,11 @@ | ||||
| import { Box, Stack } from '@mantine/core'; | ||||
| import { useVirtualizer } from '@tanstack/react-virtual'; | ||||
| import EventEmitter from 'events'; | ||||
| import { filter, indexOf, isEmpty, length, map, pluck } from 'ramda'; | ||||
| import { FC, useContext, useLayoutEffect, useMemo, useRef } from 'react'; | ||||
| import { indexOf, isEmpty, length, map, mergeLeft, pluck, range } from 'ramda'; | ||||
| import { FC, useCallback, useContext, useMemo, useRef } from 'react'; | ||||
| import { useLifecycles } from 'react-use'; | ||||
| import { VariableSizeList } from 'react-window'; | ||||
| import { EventBusContext } from '../EventBus'; | ||||
| import { useFileListStore } from '../states/files'; | ||||
| import { useZoomState } from '../states/zoom'; | ||||
| import { withinRange } from '../utils/offset_func'; | ||||
|  | ||||
| export const ContinuationView: FC = () => { | ||||
|   const { files } = useFileListStore(); | ||||
| @@ -15,23 +13,24 @@ export const ContinuationView: FC = () => { | ||||
|   const viewHeight = useZoomState.use.viewHeight(); | ||||
|   const updateActives = useFileListStore.use.updateActiveFiles(); | ||||
|   const fileCount = useMemo(() => length(files), [files]); | ||||
|   const parentRef = useRef(); | ||||
|   const ebus = useContext<EventEmitter>(EventBusContext); | ||||
|   const virtualizer = useVirtualizer({ | ||||
|     count: fileCount, | ||||
|     getScrollElement: () => parentRef.current, | ||||
|     estimateSize: () => 100 | ||||
|   }); | ||||
|   const items = virtualizer.getVirtualItems(); | ||||
|   const virtualListRef = useRef<VariableSizeList | null>(); | ||||
|   const handleOnRenderAction = useCallback( | ||||
|     ({ visibleStartIndex, visibleStopIndex }) => { | ||||
|       console.log('[debug]on render:', visibleStartIndex, visibleStopIndex); | ||||
|       updateActives(map(i => files[i].filename, range(visibleStartIndex, visibleStopIndex + 1))); | ||||
|     }, | ||||
|     [files] | ||||
|   ); | ||||
|  | ||||
|   useLifecycles( | ||||
|     () => { | ||||
|       ebus?.addListener('navigate_offset', ({ filename }) => { | ||||
|         let index = indexOf(filename, pluck('filename', files)); | ||||
|         virtualizer.scrollToIndex(index); | ||||
|         virtualListRef.current?.scrollToItem(index); | ||||
|       }); | ||||
|       ebus?.addListener('reset_views', () => { | ||||
|         virtualizer.scrollToOffset(0); | ||||
|         virtualListRef.current?.scrollTo(0); | ||||
|       }); | ||||
|     }, | ||||
|     () => { | ||||
| @@ -40,43 +39,37 @@ export const ContinuationView: FC = () => { | ||||
|     } | ||||
|   ); | ||||
|  | ||||
|   useLayoutEffect(() => { | ||||
|     let rangeStart = virtualizer.scrollOffset; | ||||
|     let rangeEnd = virtualizer.scrollOffset + viewHeight; | ||||
|     let onShowItems = pluck( | ||||
|       'index', | ||||
|       filter(item => withinRange(item.start, item.end, rangeStart, rangeEnd), items) | ||||
|     ); | ||||
|     updateActives(map(i => files[i].filename, onShowItems)); | ||||
|   }, [virtualizer.scrollOffset, viewHeight, items]); | ||||
|  | ||||
|   return ( | ||||
|     <div style={{ overflow: 'auto', contain: 'strict', height: '100%' }} ref={parentRef}> | ||||
|     <div | ||||
|       style={{ | ||||
|         overflow: 'auto', | ||||
|         contain: 'strict', | ||||
|         height: '100%' | ||||
|       }} | ||||
|     > | ||||
|       {!isEmpty(files) && ( | ||||
|         <Box pos="relative" w="100%" h={virtualizer.getTotalSize()}> | ||||
|           <Stack | ||||
|             pos="absolute" | ||||
|             top={0} | ||||
|             left={0} | ||||
|             w="100%" | ||||
|             justify="start" | ||||
|             align="center" | ||||
|             spacing={0} | ||||
|             style={{ | ||||
|               transform: `translateY(${items[0].start}px)` | ||||
|             }} | ||||
|           > | ||||
|             {items.map(row => ( | ||||
|               <img | ||||
|                 key={files[row.index].filename} | ||||
|                 src={files[row.index].path} | ||||
|                 ref={virtualizer.measureElement} | ||||
|                 data-index={row.index} | ||||
|                 style={{ width: `${zoom}%` }} | ||||
|               /> | ||||
|             ))} | ||||
|           </Stack> | ||||
|         </Box> | ||||
|         <VariableSizeList | ||||
|           itemData={files} | ||||
|           itemCount={fileCount} | ||||
|           itemSize={index => files[index].height * (zoom / 100)} | ||||
|           height={viewHeight} | ||||
|           width="100%" | ||||
|           ref={virtualListRef} | ||||
|           onItemsRendered={handleOnRenderAction} | ||||
|         > | ||||
|           {({ index, style, data }) => ( | ||||
|             <div | ||||
|               style={mergeLeft(style, { | ||||
|                 display: 'flex', | ||||
|                 flexDirection: 'row', | ||||
|                 justifyContent: 'center', | ||||
|                 alignItems: 'flex-start' | ||||
|               })} | ||||
|             > | ||||
|               <img src={data[index].path} style={{ width: data[index].width * (zoom / 100) }} /> | ||||
|             </div> | ||||
|           )} | ||||
|         </VariableSizeList> | ||||
|       )} | ||||
|     </div> | ||||
|   ); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user