Files
Netcatty/components/sftp/SftpPaneTreeView.types.ts
T
陈大猫 074acc3bed feat(sftp): add right-click extract for archives (#3042)
* feat(sftp): add right-click extract for archives

Let SFTP list and tree views unpack zip/tar/gz archives in place via remote SSH exec (or local tar/unzip), so users do not need to switch to another file manager.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(sftp): keep extract from clobbering files or dying on unzip output

Write gzip/bzip2/xz results to a staging path and replace the destination only after a zero exit. Drain unzip progress instead of treating routine stdout as a hard failure.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(sftp): quote extract cleanup trap and use unique staging files

Remote gzip/bzip2/xz nested a quoted path inside trap, so names with spaces failed before decode. Staging now exclusively creates a unique sibling, and local .gz uses Node zlib.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(sftp): refuse single-file extract onto an existing directory

Remote mv would otherwise drop the staging file inside that directory and still report success.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(sftp): restore the previous file if Windows extract replace fails

Rename the destination aside before publishing the staging file, instead of deleting it first.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 12:00:16 +08:00

37 lines
2.0 KiB
TypeScript

import type { SftpFileEntry } from '../../types';
import type { SftpPane } from '../../application/state/sftp/types';
import type { SftpTransferSource } from './SftpContext';
import type { UseSftpPaneSortingResult } from '../../application/state/sftp/useSftpPaneSorting';
export interface SftpPaneTreeViewProps {
pane: SftpPane;
side: 'left' | 'right';
onPrepareSelection: () => void;
onLoadChildren: (path: string) => Promise<SftpFileEntry[]>;
onMoveEntriesToPath: (sourcePaths: string[], targetPath: string) => Promise<void>;
onNavigateUp: () => void;
onNavigateTo: (path: string) => void;
onRefresh: () => void;
onOpenEntry: (entry: SftpFileEntry, fullPath?: string) => void;
onDragStart: (files: SftpTransferSource[], side: 'left' | 'right') => void;
onDragEnd: () => void;
openRenameDialog: (entryPath: string) => void;
openDeleteConfirm: (targets: string[]) => void;
onCopyToOtherPane: (files: SftpTransferSource[]) => void;
onReceiveFromOtherPane: (files: SftpTransferSource[]) => void;
onOpenFileWithSystemDefault?: (entry: SftpFileEntry, fullPath?: string) => void;
onOpenFileWith?: (entry: SftpFileEntry, fullPath?: string) => void;
onEditFile?: (entry: SftpFileEntry, fullPath?: string) => void;
onDownloadFile?: (entry: SftpFileEntry, fullPath?: string) => void;
onExtractArchive?: (entry: SftpFileEntry, fullPath?: string) => void | Promise<void>;
onEditPermissions?: (entry: SftpFileEntry, fullPath?: string) => void;
draggedFiles: (SftpTransferSource & { side: 'left' | 'right' })[] | null;
openNewFolderDialog: (targetPath: string) => void;
openNewFileDialog: (targetPath: string) => void;
onUploadExternalFiles?: (dataTransfer: DataTransfer, targetPath?: string) => Promise<void>;
onUploadExternalFileList?: (fileList: FileList, targetPath?: string) => Promise<void>;
onUploadExternalFolder?: (targetPath?: string) => Promise<void>;
sorting: UseSftpPaneSortingResult;
reloadRequest: { token: number; paths?: string[]; full?: boolean };
}