57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
![]() |
import { useState, useEffect } from 'react';
|
||
|
import { invoke } from '@tauri-apps/api/tauri';
|
||
|
|
||
|
interface FileItem {
|
||
|
name: string;
|
||
|
path: string;
|
||
|
is_dir: boolean;
|
||
|
}
|
||
|
|
||
|
const FileTree = ({ onSelect }: { onSelect: (path: string) => void }) => {
|
||
|
const [tree, setTree] = useState<FileItem[]>([]);
|
||
|
const [expanded, setExpanded] = useState<Record<string, boolean>>({});
|
||
|
|
||
|
useEffect(() => {
|
||
|
const loadTree = async () => {
|
||
|
try {
|
||
|
const result = await invoke<FileItem[]>('list_files', { path: '' });
|
||
|
setTree(result.filter(item => item.is_dir));
|
||
|
} catch (error) {
|
||
|
console.error('Error loading file tree:', error);
|
||
|
}
|
||
|
};
|
||
|
loadTree();
|
||
|
}, []);
|
||
|
|
||
|
const toggleExpand = async (path: string) => {
|
||
|
setExpanded(prev => ({ ...prev, [path]: !prev[path] }));
|
||
|
onSelect(path);
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<div className="w-64 border-r border-gray-300 p-4 overflow-y-auto">
|
||
|
<h3 className="text-lg font-semibold mb-4">File Tree</h3>
|
||
|
<ul className="space-y-1">
|
||
|
{tree.map((item) => (
|
||
|
<li key={item.path} className="pl-2">
|
||
|
<div
|
||
|
onClick={() => toggleExpand(item.path)}
|
||
|
className="flex items-center cursor-pointer hover:bg-gray-100 p-1 rounded"
|
||
|
>
|
||
|
<span>{expanded[item.path] ? '📂' : '📁'}</span>
|
||
|
<span className="ml-2">{item.name}</span>
|
||
|
</div>
|
||
|
{expanded[item.path] && (
|
||
|
<div className="pl-4">
|
||
|
<FileBrowser path={item.path} />
|
||
|
</div>
|
||
|
)}
|
||
|
</li>
|
||
|
))}
|
||
|
</ul>
|
||
|
</div>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
export default FileTree;
|