fix(view):更换虚拟列表支持库,以解决缩放存在的问题。
This commit is contained in:
@@ -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<EventEmitter>(EventBusContext);
|
||||
const virtualListRef = useRef<VariableSizeList | null>();
|
||||
const virtualListRef = useRef<VirtuosoHandle | null>(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) && (
|
||||
<VariableSizeList
|
||||
itemData={files}
|
||||
itemCount={fileCount}
|
||||
itemSize={index => fileHeights[index]}
|
||||
itemKey={index => files[index].id}
|
||||
height={viewHeight}
|
||||
width="100%"
|
||||
<Virtuoso
|
||||
style={{ height: viewHeight }}
|
||||
ref={virtualListRef}
|
||||
onItemsRendered={handleOnRenderAction}
|
||||
>
|
||||
{({ index, style, data }) => (
|
||||
totalCount={fileCount}
|
||||
computeItemKey={index => files[index].id}
|
||||
rangeChanged={handleOnRenderAction}
|
||||
itemContent={index => (
|
||||
<div
|
||||
style={mergeLeft(style, {
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'flex-start'
|
||||
})}
|
||||
alignItems: 'flex-start',
|
||||
width: '100%',
|
||||
height: files[index].height * (maxImageWidth / files[index].width)
|
||||
}}
|
||||
>
|
||||
<img src={data[index].path} style={{ width: data[index].width * (zoom / 100) }} />
|
||||
<img src={files[index].path} style={{ width: maxImageWidth }} />
|
||||
</div>
|
||||
)}
|
||||
</VariableSizeList>
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -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<EventEmitter>(EventBusContext);
|
||||
const filesCount = useMemo(() => length(files), [files]);
|
||||
const [parentRef, { height: parentHeight }] = useMeasure();
|
||||
const listRef = useRef<FixedSizeList | null>();
|
||||
const listRef = useRef<VirtuosoHandle | null>(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) && (
|
||||
<FixedSizeList itemCount={filesCount} itemSize={35} height={parentHeight} ref={listRef}>
|
||||
{({ index, style }) => (
|
||||
<Virtuoso
|
||||
style={{ height: parentHeight }}
|
||||
totalCount={filesCount}
|
||||
ref={listRef}
|
||||
itemContent={index => (
|
||||
<Box
|
||||
bg={includes(files[index].filename, activeFiles) && 'grape'}
|
||||
key={index}
|
||||
px={4}
|
||||
py={2}
|
||||
onClick={() => 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
|
||||
}
|
||||
})}
|
||||
>
|
||||
<Tooltip label={files[index].filename}>
|
||||
<Tooltip label={files[index].filename} zIndex={999}>
|
||||
<Text truncate>{files[index].filename}</Text>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
)}
|
||||
</FixedSizeList>
|
||||
/>
|
||||
)}
|
||||
{isEmpty(files) && (
|
||||
<Center h="100%">
|
||||
|
||||
Reference in New Issue
Block a user