feat(file):增加修改文件名称的功能。

This commit is contained in:
徐涛 2023-03-23 09:52:26 +08:00
parent 65943e33b9
commit 0eb69d777d
4 changed files with 77 additions and 6 deletions

View File

@ -1,4 +1,7 @@
use std::{fs::DirEntry, path::Path}; use std::{
fs::{self, DirEntry},
path::{Path, PathBuf},
};
use mountpoints::mountinfos; use mountpoints::mountinfos;
use serde::Serialize; use serde::Serialize;
@ -193,3 +196,17 @@ pub async fn scan_for_child_dirs<R: Runtime>(
child_dirs.sort_by(|a, b| a.dirname.partial_cmp(&b.dirname).unwrap()); child_dirs.sort_by(|a, b| a.dirname.partial_cmp(&b.dirname).unwrap());
Ok(child_dirs) Ok(child_dirs)
} }
#[tauri::command]
pub async fn rename_file<R: Runtime>(
_app: tauri::AppHandle<R>,
_window: tauri::Window<R>,
store_path: String,
origin_name: String,
new_name: String,
) -> Result<(), String> {
let origin_file = PathBuf::from(store_path.clone()).join(origin_name);
let new_file = PathBuf::from(store_path).join(new_name);
fs::rename(origin_file, new_file).map_err(|e| format!("重命名问文件失败,{}", e))?;
Ok(())
}

View File

@ -15,7 +15,8 @@ fn main() {
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
commands::prelude::scan_directory, commands::prelude::scan_directory,
commands::prelude::show_drives, commands::prelude::show_drives,
commands::prelude::scan_for_child_dirs commands::prelude::scan_for_child_dirs,
commands::prelude::rename_file
]) ])
.setup(|app| { .setup(|app| {
let main_window = app.get_window("main").unwrap(); let main_window = app.get_window("main").unwrap();

View File

@ -123,6 +123,7 @@ export const DirTree: FC = () => {
const roots = useDirTreeStore(currentRootsSelector()); const roots = useDirTreeStore(currentRootsSelector());
const { focused, focus, unfocus, selected, foldDir } = useDirTreeStore(); const { focused, focus, unfocus, selected, foldDir } = useDirTreeStore();
const [viewRef, { width }] = useMeasure(); const [viewRef, { width }] = useMeasure();
const storeFiles = useFileListStore.use.updateFiles();
const ebus = useContext<EventEmitter>(EventBusContext); const ebus = useContext<EventEmitter>(EventBusContext);
const handleFocusAction = useCallback(() => { const handleFocusAction = useCallback(() => {

View File

@ -1,18 +1,34 @@
//@ts-nocheck //@ts-nocheck
import { Box, Center, Text, Tooltip } from '@mantine/core'; import { Box, Center, Group, Text, TextInput, Tooltip } from '@mantine/core';
import { notifications } from '@mantine/notifications';
import { invoke } from '@tauri-apps/api';
import EventEmitter from 'events'; import EventEmitter from 'events';
import { head, includes, indexOf, isEmpty, length, not, pluck } from 'ramda'; import { equals, find, head, includes, indexOf, isEmpty, length, not, pluck, propEq } from 'ramda';
import { FC, useCallback, useContext, useLayoutEffect, useMemo, useRef } from 'react'; import {
FC,
KeyboardEvent,
useCallback,
useContext,
useLayoutEffect,
useMemo,
useRef,
useState
} from 'react';
import { useMeasure } from 'react-use'; import { useMeasure } from 'react-use';
import { Virtuoso, VirtuosoHandle } from 'react-virtuoso'; import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';
import { EventBusContext } from '../EventBus'; import { EventBusContext } from '../EventBus';
import { useDirTreeStore } from '../states/dirs';
import { sortedFilesSelector, useFileListStore } from '../states/files'; import { sortedFilesSelector, useFileListStore } from '../states/files';
export const FileList: FC = () => { export const FileList: FC = () => {
const files = useFileListStore(sortedFilesSelector()); const files = useFileListStore(sortedFilesSelector());
const storeFiles = useFileListStore.use.updateFiles();
const activeFiles = useFileListStore.use.actives(); const activeFiles = useFileListStore.use.actives();
const cwd = useDirTreeStore.use.selected();
const directories = useDirTreeStore.use.directories();
const ebus = useContext<EventEmitter>(EventBusContext); const ebus = useContext<EventEmitter>(EventBusContext);
const filesCount = useMemo(() => length(files), [files]); const filesCount = useMemo(() => length(files), [files]);
const [editingFile, setEditing] = useState<string | null>(null);
const [parentRef, { height: parentHeight }] = useMeasure(); const [parentRef, { height: parentHeight }] = useMeasure();
const listRef = useRef<VirtuosoHandle | null>(null); const listRef = useRef<VirtuosoHandle | null>(null);
const handleFileSelectAction = useCallback( const handleFileSelectAction = useCallback(
@ -21,6 +37,30 @@ export const FileList: FC = () => {
}, },
[ebus] [ebus]
); );
const handleFileRenameAction = useCallback(
async (fileId: string, event: KeyboardEvent<HTMLInputElement>) => {
if (equals(event.key, 'Enter')) {
const newFileName = event.target.value;
const originalFile = find(propEq('id', fileId), files);
const storeDirectory = find(propEq('id', cwd), directories);
try {
await invoke('rename_file', {
storePath: storeDirectory?.path,
originName: originalFile?.filename,
newName: newFileName
});
const refreshedFiles = await invoke('scan_directory', { target: storeDirectory?.path });
storeFiles(refreshedFiles);
ebus.emit('reset_views');
} catch (e) {
console.error('[debug]重命名文件:', e);
notifications.show({ message: `重命名文件失败,${e}`, color: 'red' });
}
setEditing(null);
}
},
[files, cwd, directories]
);
useLayoutEffect(() => { useLayoutEffect(() => {
let firstActived = head(activeFiles); let firstActived = head(activeFiles);
@ -51,6 +91,7 @@ export const FileList: FC = () => {
px={4} px={4}
py={2} py={2}
onClick={() => handleFileSelectAction(files[index].filename)} onClick={() => handleFileSelectAction(files[index].filename)}
onDoubleClick={() => setEditing(files[index].id)}
sx={theme => ({ sx={theme => ({
cursor: 'pointer', cursor: 'pointer',
'&:hover': { '&:hover': {
@ -59,7 +100,18 @@ export const FileList: FC = () => {
})} })}
> >
<Tooltip label={files[index].filename} zIndex={999}> <Tooltip label={files[index].filename} zIndex={999}>
{propEq('id', editingFile)(files[index]) ? (
<Group>
<TextInput
defaultValue={files[index].filename}
size="xs"
variant="unstyled"
onKeyDown={event => handleFileRenameAction(files[index].id, event)}
/>
</Group>
) : (
<Text truncate>{files[index].filename}</Text> <Text truncate>{files[index].filename}</Text>
)}
</Tooltip> </Tooltip>
</Box> </Box>
)} )}