feat: Advanced file editor and file tree improvements (#444)

# Features
- File drag and drop upload: Support uploading files and folders via drag and drop
- Binary file handling: Detect binary files and display a friendly message instead of trying to edit them
- Folder download: Download folders as ZIP files (using JSZip library)
- Context menu integration: Full right-click context menu for file operations (rename, delete, copy path, download, new file/folder)
This commit is contained in:
朱见
2026-03-03 20:19:46 +08:00
committed by GitHub
parent 503c384685
commit 97689588aa
30 changed files with 2270 additions and 94 deletions

View File

@@ -1,4 +1,4 @@
import type { ReactNode } from 'react';
import type { ReactNode, RefObject } from 'react';
import type { FileTreeNode as FileTreeNodeType, FileTreeViewMode } from '../types/types';
import FileTreeNode from './FileTreeNode';
@@ -10,6 +10,21 @@ type FileTreeListProps = {
renderFileIcon: (filename: string) => ReactNode;
formatFileSize: (bytes?: number) => string;
formatRelativeTime: (date?: string) => string;
onRename?: (item: FileTreeNodeType) => void;
onDelete?: (item: FileTreeNodeType) => void;
onNewFile?: (path: string) => void;
onNewFolder?: (path: string) => void;
onCopyPath?: (item: FileTreeNodeType) => void;
onDownload?: (item: FileTreeNodeType) => void;
onRefresh?: () => void;
// Rename state for inline editing
renamingItem?: FileTreeNodeType | null;
renameValue?: string;
setRenameValue?: (value: string) => void;
handleConfirmRename?: () => void;
handleCancelRename?: () => void;
renameInputRef?: RefObject<HTMLInputElement>;
operationLoading?: boolean;
};
export default function FileTreeList({
@@ -20,6 +35,20 @@ export default function FileTreeList({
renderFileIcon,
formatFileSize,
formatRelativeTime,
onRename,
onDelete,
onNewFile,
onNewFolder,
onCopyPath,
onDownload,
onRefresh,
renamingItem,
renameValue,
setRenameValue,
handleConfirmRename,
handleCancelRename,
renameInputRef,
operationLoading,
}: FileTreeListProps) {
return (
<div>
@@ -34,9 +63,22 @@ export default function FileTreeList({
renderFileIcon={renderFileIcon}
formatFileSize={formatFileSize}
formatRelativeTime={formatRelativeTime}
onRename={onRename}
onDelete={onDelete}
onNewFile={onNewFile}
onNewFolder={onNewFolder}
onCopyPath={onCopyPath}
onDownload={onDownload}
onRefresh={onRefresh}
renamingItem={renamingItem}
renameValue={renameValue}
setRenameValue={setRenameValue}
handleConfirmRename={handleConfirmRename}
handleCancelRename={handleCancelRename}
renameInputRef={renameInputRef}
operationLoading={operationLoading}
/>
))}
</div>
);
}