enhance(list):文件列表增加跟随滚动的功能。
This commit is contained in:
parent
44c7f78363
commit
cf724bb17f
@ -1,15 +1,20 @@
|
|||||||
//@ts-nocheck
|
//@ts-nocheck
|
||||||
import { Box, Center, Text } from '@mantine/core';
|
import { Box, Center, Text } from '@mantine/core';
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import { includes, isEmpty, map, not, pipe, sort } from 'ramda';
|
import { head, includes, indexOf, isEmpty, length, mergeLeft, not, pluck } from 'ramda';
|
||||||
import { FC, useCallback, useContext } from 'react';
|
import { FC, useCallback, useContext, useLayoutEffect, useMemo, useRef } from 'react';
|
||||||
|
import { useMeasure } from 'react-use';
|
||||||
|
import { FixedSizeList } from 'react-window';
|
||||||
import { EventBusContext } from '../EventBus';
|
import { EventBusContext } from '../EventBus';
|
||||||
import { useFileListStore } from '../states/files';
|
import { sortedFilesSelector, useFileListStore } from '../states/files';
|
||||||
|
|
||||||
export const FileList: FC = () => {
|
export const FileList: FC = () => {
|
||||||
const files = useFileListStore.use.files();
|
const files = useFileListStore(sortedFilesSelector());
|
||||||
const activeFiles = useFileListStore.use.actives();
|
const activeFiles = useFileListStore.use.actives();
|
||||||
const ebus = useContext<EventEmitter>(EventBusContext);
|
const ebus = useContext<EventEmitter>(EventBusContext);
|
||||||
|
const filesCount = useMemo(() => length(files), [files]);
|
||||||
|
const [parentRef, { height: parentHeight }] = useMeasure();
|
||||||
|
const listRef = useRef<FixedSizeList | null>();
|
||||||
const handleFileSelectAction = useCallback(
|
const handleFileSelectAction = useCallback(
|
||||||
(filename: string) => {
|
(filename: string) => {
|
||||||
ebus.emit('navigate_offset', { filename });
|
ebus.emit('navigate_offset', { filename });
|
||||||
@ -17,26 +22,43 @@ export const FileList: FC = () => {
|
|||||||
[ebus]
|
[ebus]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
let firstActived = head(activeFiles);
|
||||||
|
let firstActivedIndex = indexOf(firstActived, pluck('filename', files));
|
||||||
|
listRef.current?.scrollToItem(firstActivedIndex, 'smart');
|
||||||
|
}, [activeFiles]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box w="100%" h="100%" pl={4} sx={{ flexGrow: 1, overflowY: 'auto', overflowX: 'hidden' }}>
|
|
||||||
{pipe(
|
|
||||||
sort((fa, fb) => fa.sort - fb.sort),
|
|
||||||
map(item => (
|
|
||||||
<Box
|
<Box
|
||||||
bg={includes(item.filename, activeFiles) && 'grape'}
|
w="100%"
|
||||||
key={item.filename}
|
h="100%"
|
||||||
|
pl={4}
|
||||||
|
sx={{ flexGrow: 1, overflowY: 'auto', contain: 'strict', overflowX: 'hidden' }}
|
||||||
|
ref={parentRef}
|
||||||
|
>
|
||||||
|
{!isEmpty(files) && (
|
||||||
|
<FixedSizeList itemCount={filesCount} itemSize={35} height={parentHeight} ref={listRef}>
|
||||||
|
{({ index, style }) => (
|
||||||
|
<Box
|
||||||
|
bg={includes(files[index].filename, activeFiles) && 'grape'}
|
||||||
|
key={index}
|
||||||
px={4}
|
px={4}
|
||||||
py={2}
|
py={2}
|
||||||
onClick={() => handleFileSelectAction(item.filename)}
|
onClick={() => handleFileSelectAction(files[index].filename)}
|
||||||
sx={theme => ({
|
sx={theme =>
|
||||||
|
mergeLeft(style, {
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
'&:hover': { color: not(includes(item.filename, activeFiles)) && theme.colors.red }
|
'&:hover': {
|
||||||
})}
|
color: not(includes(files[index].filename, activeFiles)) && theme.colors.red
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{item.filename}
|
{files[index].filename}
|
||||||
</Box>
|
</Box>
|
||||||
))
|
)}
|
||||||
)(files)}
|
</FixedSizeList>
|
||||||
|
)}
|
||||||
{isEmpty(files) && (
|
{isEmpty(files) && (
|
||||||
<Center h="100%">
|
<Center h="100%">
|
||||||
<Text size="xs">请先打开一个文件夹。</Text>
|
<Text size="xs">请先打开一个文件夹。</Text>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user