Implement draggable file windows - Windows Explorer style

Added comprehensive draggable window system with the following features:

🪟 **DraggableWindow Component**:
- Full drag and drop functionality with title bar dragging
- Window resizing from all edges and corners
- Maximize/minimize/close window controls
- Double-click title bar to maximize/restore
- Auto position adjustment to prevent off-screen windows
- Windows-style blue gradient title bar

📁 **FileViewer Component**:
- Multi-format file support (text, code, images, videos, audio)
- Syntax highlighting distinction for code files
- Editable text files with real-time content tracking
- File metadata display (size, modified date, permissions)
- Save and download functionality
- Unsaved changes indicator

🎯 **WindowManager System**:
- Multi-window support with proper z-index management
- Window factory pattern for dynamic component creation
- Focus management - clicking brings window to front
- Smart window positioning with auto-offset
- Memory leak prevention with proper cleanup

🔗 **FileWindow Integration**:
- SSH file loading with error handling
- Auto-detect editable file types
- Real-time file saving to remote server
- Download files as binary blobs
- Loading states and progress feedback

 **User Experience**:
- Double-click any file to open in draggable window
- Multiple files can be open simultaneously
- Windows behave like native Windows Explorer
- Smooth animations and transitions
- Responsive design that works on all screen sizes

This transforms the file manager from a basic browser into a full
desktop-class application with native OS window management behavior.
This commit is contained in:
ZacharyZcR
2025-09-16 17:22:21 +08:00
parent 501de06266
commit 22ac7d8596
5 changed files with 882 additions and 3 deletions

View File

@@ -3,6 +3,8 @@ import { FileManagerGrid } from "./FileManagerGrid";
import { FileManagerContextMenu } from "./FileManagerContextMenu";
import { useFileSelection } from "./hooks/useFileSelection";
import { useDragAndDrop } from "./hooks/useDragAndDrop";
import { WindowManager, useWindowManager } from "./components/WindowManager";
import { FileWindow } from "./components/FileWindow";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { toast } from "sonner";
@@ -47,7 +49,9 @@ interface FileManagerModernProps {
onClose?: () => void;
}
export function FileManagerModern({ initialHost, onClose }: FileManagerModernProps) {
// 内部组件,使用窗口管理器
function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
const { openWindow } = useWindowManager();
const { t } = useTranslation();
// State
@@ -329,8 +333,38 @@ export function FileManagerModern({ initialHost, onClose }: FileManagerModernPro
if (file.type === 'directory') {
setCurrentPath(file.path);
} else {
// 打开文件编辑器或预览
console.log("Open file:", file);
// 在新窗口中打开文件
if (!sshSessionId) {
toast.error(t("fileManager.noSSHConnection"));
return;
}
// 计算窗口位置(稍微错开)
const windowCount = Date.now() % 10; // 简单的偏移计算
const offsetX = 120 + (windowCount * 30);
const offsetY = 120 + (windowCount * 30);
// 创建窗口组件工厂函数
const createWindowComponent = (windowId: string) => (
<FileWindow
windowId={windowId}
file={file}
sshSessionId={sshSessionId}
initialX={offsetX}
initialY={offsetY}
/>
);
openWindow({
title: file.name,
x: offsetX,
y: offsetY,
width: 800,
height: 600,
isMaximized: false,
isMinimized: false,
component: createWindowComponent
});
}
}
@@ -538,4 +572,13 @@ export function FileManagerModern({ initialHost, onClose }: FileManagerModernPro
</div>
</div>
);
}
// 主要的导出组件,包装了 WindowManager
export function FileManagerModern({ initialHost, onClose }: FileManagerModernProps) {
return (
<WindowManager>
<FileManagerContent initialHost={initialHost} onClose={onClose} />
</WindowManager>
);
}