enhance(list):文件列表增加跟随滚动的功能。
This commit is contained in:
		| @@ -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' }}> |     <Box | ||||||
|       {pipe( |       w="100%" | ||||||
|         sort((fa, fb) => fa.sort - fb.sort), |       h="100%" | ||||||
|         map(item => ( |       pl={4} | ||||||
|           <Box |       sx={{ flexGrow: 1, overflowY: 'auto', contain: 'strict', overflowX: 'hidden' }} | ||||||
|             bg={includes(item.filename, activeFiles) && 'grape'} |       ref={parentRef} | ||||||
|             key={item.filename} |     > | ||||||
|             px={4} |       {!isEmpty(files) && ( | ||||||
|             py={2} |         <FixedSizeList itemCount={filesCount} itemSize={35} height={parentHeight} ref={listRef}> | ||||||
|             onClick={() => handleFileSelectAction(item.filename)} |           {({ index, style }) => ( | ||||||
|             sx={theme => ({ |             <Box | ||||||
|               cursor: 'pointer', |               bg={includes(files[index].filename, activeFiles) && 'grape'} | ||||||
|               '&:hover': { color: not(includes(item.filename, activeFiles)) && theme.colors.red } |               key={index} | ||||||
|             })} |               px={4} | ||||||
|           > |               py={2} | ||||||
|             {item.filename} |               onClick={() => handleFileSelectAction(files[index].filename)} | ||||||
|           </Box> |               sx={theme => | ||||||
|         )) |                 mergeLeft(style, { | ||||||
|       )(files)} |                   cursor: 'pointer', | ||||||
|  |                   '&:hover': { | ||||||
|  |                     color: not(includes(files[index].filename, activeFiles)) && theme.colors.red | ||||||
|  |                   } | ||||||
|  |                 }) | ||||||
|  |               } | ||||||
|  |             > | ||||||
|  |               {files[index].filename} | ||||||
|  |             </Box> | ||||||
|  |           )} | ||||||
|  |         </FixedSizeList> | ||||||
|  |       )} | ||||||
|       {isEmpty(files) && ( |       {isEmpty(files) && ( | ||||||
|         <Center h="100%"> |         <Center h="100%"> | ||||||
|           <Text size="xs">请先打开一个文件夹。</Text> |           <Text size="xs">请先打开一个文件夹。</Text> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user