diff --git a/src/assets/svgs/bxs--file-export.svg b/src/assets/svgs/bxs--file-export.svg new file mode 100644 index 0000000..72a4578 --- /dev/null +++ b/src/assets/svgs/bxs--file-export.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/filehandle/components/FileContent.tsx b/src/filehandle/components/FileContent.tsx index 8f991f2..18ced19 100644 --- a/src/filehandle/components/FileContent.tsx +++ b/src/filehandle/components/FileContent.tsx @@ -13,7 +13,7 @@ import AddFileModal from './AddFileModal'; import { FileSystemContext } from './FilePanel'; import styles from './styles/FileContent.module.less'; import type { FileInfo } from '../utils/fileManager'; -import { FileType } from '../utils/fileManager'; +import { exportDirectory, exportFile, FileType } from '../utils/fileManager'; import { fileOperationWarning } from '../utils/operationWarning'; function MountWebdavModal(props: { open: boolean; close(): void }) { @@ -270,6 +270,22 @@ const FileContent: React.FC = (props) => { }); }; + const handleExportFile = async () => { + const curr = selection[0]; + + if (!curr) return void 0; + + try { + await (curr.handle.kind === 'directory' + ? exportDirectory(curr.handle) + : exportFile(curr.handle)); + + success(`已为你导出文件 ${curr.name}。`); + } catch (err) { + error((err as Error).message); + } + }; + const handleOk = async (name: string, type: FileType) => { try { await create(name, type); @@ -334,6 +350,14 @@ const FileContent: React.FC = (props) => { icon: , onClick: importDirectory }, + { + name: '导出文件', + icon: , + style: { + display: selection.length ? void 0 : 'none' + }, + onClick: handleExportFile + }, { name: '删除', icon: , diff --git a/src/filehandle/utils/fileManager.ts b/src/filehandle/utils/fileManager.ts index 15bedbf..a472071 100644 --- a/src/filehandle/utils/fileManager.ts +++ b/src/filehandle/utils/fileManager.ts @@ -69,8 +69,6 @@ export async function getHandleType(handle: DH | FH) { } export async function importFile(directory: DH, options?: FilePickerOptions) { - if (!window.showOpenFilePicker) return false; - const files = await window.showOpenFilePicker(options); await Promise.all( @@ -81,8 +79,6 @@ export async function importFile(directory: DH, options?: FilePickerOptions) { } export async function importDirectory(directory: DH, options?: DirectoryPickerOptions) { - if (!window.showDirectoryPicker) return false; - const folder = await window.showDirectoryPicker(options); await move(folder, await createDirectory(directory, folder.name)); @@ -90,6 +86,25 @@ export async function importDirectory(directory: DH, options?: DirectoryPickerOp return true; } +export async function exportFile(file: FH) { + const handle = await window.showSaveFilePicker({ + suggestedName: file.name, + types: [{ description: 'export file', accept: {} }] + }); + + await writeFile(handle, await file.getFile()); + + return true; +} + +export async function exportDirectory(directory: DH) { + const handle = await window.showDirectoryPicker({ mode: 'readwrite' }); + + await moveDirectoryWithSelf(directory, handle); + + return true; +} + export async function writeFile(file: FH, data: FileDataType) { const writable = await file.createWritable(); await writable.write(data); @@ -123,15 +138,24 @@ export async function moveFile(origin: DH, target: DH, name: string, copy = true return handle; } +export async function moveDirectoryWithSelf(origin: DH, target: DH) { + const _target = await target.getDirectoryHandle(origin.name, { create: true }); + + await move(origin, _target); + + return true; +} + export async function moveDirectory(origin: DH, target: DH, name: string, copy = true) { const _origin = await origin.getDirectoryHandle(name); const _target = await createDirectory(target, name); - for await (const [key, handle] of _origin.entries()) { + const entries = _origin.entries(); + for await (const [key, handle] of entries) { if ((await getHandleType(handle)) === FileType.FILE) { - return await moveFile(_origin, _target, key, copy); + await moveFile(_origin, _target, key, copy); } else { - return await moveDirectory(_origin, _target, key); + await moveDirectory(_origin, _target, key); } } diff --git a/types/filesystem.d.ts b/types/filesystem.d.ts index 987c520..8f8f0b2 100644 --- a/types/filesystem.d.ts +++ b/types/filesystem.d.ts @@ -99,7 +99,7 @@ declare interface SaveFilePickerOptions { } declare interface Window { - showDirectoryPicker: (options?: DirectoryPickerOptions) => Promise; + showDirectoryPicker(options?: DirectoryPickerOptions): Promise; showOpenFilePicker(options?: FilePickerOptions): Promise; showSaveFilePicker(options?: SaveFilePickerOptions): Promise; }