refactor(view):调整无限列表功能所使用的库。

This commit is contained in:
徐涛
2023-03-09 11:11:12 +08:00
parent db70eb25d9
commit b17b3d308e
3 changed files with 71 additions and 65 deletions

View File

@@ -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>
);