Compare commits
5 Commits
803f8c5d72
...
06f94fe27e
Author | SHA1 | Date | |
---|---|---|---|
|
06f94fe27e | ||
|
6a6dc56fa8 | ||
|
cf724bb17f | ||
|
44c7f78363 | ||
|
067990a1e5 |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 182 KiB |
|
@ -4,11 +4,11 @@ import { indexOf, isEmpty, length, map, mergeLeft, pluck, range } from 'ramda';
|
|||
import { FC, useCallback, useContext, useEffect, useMemo, useRef } from 'react';
|
||||
import { VariableSizeList } from 'react-window';
|
||||
import { EventBusContext } from '../EventBus';
|
||||
import { useFileListStore } from '../states/files';
|
||||
import { sortedFilesSelector, useFileListStore } from '../states/files';
|
||||
import { useZoomState } from '../states/zoom';
|
||||
|
||||
export const ContinuationView: FC = () => {
|
||||
const { files } = useFileListStore();
|
||||
const files = useFileListStore(sortedFilesSelector());
|
||||
const zoom = useZoomState.use.currentZoom();
|
||||
const viewHeight = useZoomState.use.viewHeight();
|
||||
const updateActives = useFileListStore.use.updateActiveFiles();
|
||||
|
@ -25,8 +25,6 @@ export const ContinuationView: FC = () => {
|
|||
useEffect(() => {
|
||||
ebus?.addListener('navigate_offset', ({ filename }) => {
|
||||
let index = indexOf(filename, pluck('filename', files));
|
||||
console.log('[debug]filenames', pluck('filename', files));
|
||||
console.log('[debug]navigate: ', filename, index);
|
||||
virtualListRef.current?.scrollToItem(index);
|
||||
});
|
||||
ebus?.addListener('reset_views', () => {
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
//@ts-nocheck
|
||||
import { Box, Center, Text } from '@mantine/core';
|
||||
import EventEmitter from 'events';
|
||||
import { includes, isEmpty, map, not, pipe, sort } from 'ramda';
|
||||
import { FC, useCallback, useContext } from 'react';
|
||||
import { head, includes, indexOf, isEmpty, length, mergeLeft, not, pluck } from 'ramda';
|
||||
import { FC, useCallback, useContext, useLayoutEffect, useMemo, useRef } from 'react';
|
||||
import { useMeasure } from 'react-use';
|
||||
import { FixedSizeList } from 'react-window';
|
||||
import { EventBusContext } from '../EventBus';
|
||||
import { useFileListStore } from '../states/files';
|
||||
import { sortedFilesSelector, useFileListStore } from '../states/files';
|
||||
|
||||
export const FileList: FC = () => {
|
||||
const files = useFileListStore.use.files();
|
||||
const files = useFileListStore(sortedFilesSelector());
|
||||
const activeFiles = useFileListStore.use.actives();
|
||||
const ebus = useContext<EventEmitter>(EventBusContext);
|
||||
const filesCount = useMemo(() => length(files), [files]);
|
||||
const [parentRef, { height: parentHeight }] = useMeasure();
|
||||
const listRef = useRef<FixedSizeList | null>();
|
||||
const handleFileSelectAction = useCallback(
|
||||
(filename: string) => {
|
||||
ebus.emit('navigate_offset', { filename });
|
||||
|
@ -17,26 +22,43 @@ export const FileList: FC = () => {
|
|||
[ebus]
|
||||
);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
let firstActived = head(activeFiles);
|
||||
let firstActivedIndex = indexOf(firstActived, pluck('filename', files));
|
||||
listRef.current?.scrollToItem(firstActivedIndex, 'smart');
|
||||
}, [activeFiles]);
|
||||
|
||||
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
|
||||
bg={includes(item.filename, activeFiles) && 'grape'}
|
||||
key={item.filename}
|
||||
px={4}
|
||||
py={2}
|
||||
onClick={() => handleFileSelectAction(item.filename)}
|
||||
sx={theme => ({
|
||||
cursor: 'pointer',
|
||||
'&:hover': { color: not(includes(item.filename, activeFiles)) && theme.colors.red }
|
||||
})}
|
||||
>
|
||||
{item.filename}
|
||||
</Box>
|
||||
))
|
||||
)(files)}
|
||||
<Box
|
||||
w="100%"
|
||||
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}
|
||||
py={2}
|
||||
onClick={() => handleFileSelectAction(files[index].filename)}
|
||||
sx={theme =>
|
||||
mergeLeft(style, {
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
color: not(includes(files[index].filename, activeFiles)) && theme.colors.red
|
||||
}
|
||||
})
|
||||
}
|
||||
>
|
||||
{files[index].filename}
|
||||
</Box>
|
||||
)}
|
||||
</FixedSizeList>
|
||||
)}
|
||||
{isEmpty(files) && (
|
||||
<Center h="100%">
|
||||
<Text size="xs">请先打开一个文件夹。</Text>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { convertFileSrc } from '@tauri-apps/api/tauri';
|
||||
import { addIndex, map, mergeLeft } from 'ramda';
|
||||
import { addIndex, map, mergeLeft, sort } from 'ramda';
|
||||
import { FileItem } from '../models';
|
||||
import { SyncObjectCallback } from '../types';
|
||||
import { createStoreHook } from '../utils/store_creator';
|
||||
|
@ -36,3 +36,7 @@ export const useFileListStore = createStoreHook<FileListState & FileListActions>
|
|||
});
|
||||
}
|
||||
}));
|
||||
|
||||
export function sortedFilesSelector(): SyncObjectCallback<FileListState, FileItem[]> {
|
||||
return state => sort((fa, fb) => fa.sort - fb.sort, state.files);
|
||||
}
|
||||
|
|