From 0908822924c2c75214ad451f1324d341ab7f7752 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Sun, 29 Jun 2025 20:33:05 -0300 Subject: [PATCH] feat: Add mobile chat interface and command input to footer component --- app/drive/page.tsx | 81 +++++--- app/footer.tsx | 446 +++++++++++++++++++++++++++++++---------- app/theme-provider.tsx | 5 - prompt.md | 1 + 4 files changed, 390 insertions(+), 143 deletions(-) create mode 100644 prompt.md diff --git a/app/drive/page.tsx b/app/drive/page.tsx index a56676d..f0c4599 100644 --- a/app/drive/page.tsx +++ b/app/drive/page.tsx @@ -27,7 +27,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet'; // Simple date formatting functions -const formatDate = (dateString) => { +const formatDate = (dateString: string) => { const date = new Date(dateString); return date.toLocaleDateString('en-US', { month: 'short', @@ -36,7 +36,7 @@ const formatDate = (dateString) => { }); }; -const formatDateTime = (dateString) => { +const formatDateTime = (dateString: string) => { const date = new Date(dateString); return date.toLocaleString('en-US', { month: 'short', @@ -48,7 +48,7 @@ const formatDateTime = (dateString) => { }); }; -const formatDistanceToNow = (date) => { +const formatDistanceToNow = (date: string) => { const now = new Date(); const diffMs = now.getTime() - new Date(date).getTime(); const diffMinutes = Math.floor(diffMs / (1000 * 60)); @@ -167,7 +167,7 @@ const fileSystemData = { } }; -const getFileIcon = (item) => { +const getFileIcon = (item: any) => { if (item.is_dir) { return ; } @@ -188,14 +188,14 @@ const getFileIcon = (item) => { return iconMap[item.type] || ; }; -const formatFileSize = (bytes) => { +const formatFileSize = (bytes: number) => { if (!bytes) return ''; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(1024)); return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`; }; -const FileContextMenu = ({ file, children, onAction }) => { +const FileContextMenu = ({ file, children, onAction }: any) => { const contextMenuItems = [ { icon: Eye, label: "Open", action: "open" }, { icon: Download, label: "Download", action: "download" }, @@ -228,7 +228,7 @@ const FileContextMenu = ({ file, children, onAction }) => { { icon: Trash2, label: "Move to trash", action: "trash", destructive: true }, ]; - const renderContextMenuItem = (item, index) => { + const renderContextMenuItem = (item: any, index: number) => { if (item.separator) { return ; } @@ -241,7 +241,7 @@ const FileContextMenu = ({ file, children, onAction }) => { {item.label} - {item.submenu.map((subItem, subIndex) => ( + {item.submenu.map((subItem: any, subIndex: number) => ( onAction(subItem.action, file)} @@ -283,10 +283,20 @@ const FileContextMenu = ({ file, children, onAction }) => { ); }; -const FolderTree = ({ onSelect, selectedPath = undefined, isCollapsed = undefined, isMobile = undefined }) => { +const TreeLine = ({ depth }: { depth: number }) => { + return ( + + {Array.from({ length: depth }).map((_, i) => ( + + ))} + + ); +}; + +const FolderTree = ({ onSelect, selectedPath = "", isCollapsed = false, isMobile = false }: any) => { const [expanded, setExpanded] = useState({ "": true, "projects": true }); - const toggleExpand = (path) => { + const toggleExpand = (path: string) => { setExpanded(prev => ({ ...prev, [path]: !prev[path] })); onSelect(path); }; @@ -299,7 +309,7 @@ const FolderTree = ({ onSelect, selectedPath = undefined, isCollapsed = undefine { title: "Trash", path: "trash", icon: Trash2 }, ]; - const renderTreeItem = (path, level = 0) => { + const renderTreeItem = (path: string, level = 0) => { const item = fileSystemData[path]; if (!item || !item.is_dir) return null; @@ -318,6 +328,7 @@ const FolderTree = ({ onSelect, selectedPath = undefined, isCollapsed = undefine > {!isCollapsed && ( <> + {getFileIcon(item)} {item.name} @@ -328,7 +339,7 @@ const FolderTree = ({ onSelect, selectedPath = undefined, isCollapsed = undefine {!isCollapsed && isExpanded && item.children && (
- {item.children.map(childPath => { + {item.children.map((childPath: string) => { const fullPath = path ? `${path}/${childPath}` : childPath; return renderTreeItem(fullPath, level + 1); })} @@ -342,14 +353,17 @@ const FolderTree = ({ onSelect, selectedPath = undefined, isCollapsed = undefine
{!isCollapsed && ( @@ -383,24 +400,24 @@ const FolderTree = ({ onSelect, selectedPath = undefined, isCollapsed = undefine ); }; -const FileList = ({ path, searchTerm, filterType, selectedFile, setSelectedFile, onContextAction, isMobile }) => { +const FileList = ({ path, searchTerm, filterType, selectedFile, setSelectedFile, onContextAction, isMobile }: any) => { const files = useMemo(() => { const currentItem = fileSystemData[path]; if (!currentItem || !currentItem.is_dir || !currentItem.children) return []; - let items = currentItem.children.map(childName => { + let items = currentItem.children.map((childName: string) => { const childPath = path ? `${path}/${childName}` : childName; return fileSystemData[childPath]; }).filter(Boolean); if (searchTerm) { - items = items.filter(item => + items = items.filter((item: any) => item.name.toLowerCase().includes(searchTerm.toLowerCase()) ); } if (filterType && filterType !== 'all') { - items = items.filter(item => { + items = items.filter((item: any) => { if (filterType === 'folders') return item.is_dir; if (filterType === 'files') return !item.is_dir; if (filterType === 'starred') return item.starred; @@ -408,7 +425,7 @@ const FileList = ({ path, searchTerm, filterType, selectedFile, setSelectedFile, }); } - return items.sort((a, b) => { + return items.sort((a: any, b: any) => { if (a.is_dir && !b.is_dir) return -1; if (!a.is_dir && b.is_dir) return 1; return a.name.localeCompare(b.name); @@ -418,7 +435,7 @@ const FileList = ({ path, searchTerm, filterType, selectedFile, setSelectedFile, return (
- {files.map((item) => ( + {files.map((item: any) => (
- {formatDistanceToNow(new Date(item.modified))} + {formatDistanceToNow(item.modified)}
@@ -455,7 +472,7 @@ const FileList = ({ path, searchTerm, filterType, selectedFile, setSelectedFile, ); }; -const FileDisplay = ({ file, isMobile }) => { +const FileDisplay = ({ file, isMobile }: any) => { if (!file) { return (
@@ -563,10 +580,10 @@ export default function FileManager() { const [currentPath, setCurrentPath] = useState(''); const [searchTerm, setSearchTerm] = useState(''); const [filterType, setFilterType] = useState('all'); - const [selectedFile, setSelectedFile] = useState(null); + const [selectedFile, setSelectedFile] = useState(null); const [isMobile, setIsMobile] = useState(false); const [showMobileMenu, setShowMobileMenu] = useState(false); - const [activePanel, setActivePanel] = useState('files'); // 'tree', 'files', 'preview' + const [activePanel, setActivePanel] = useState('files'); const currentItem = fileSystemData[currentPath]; @@ -597,7 +614,7 @@ export default function FileManager() { ] ]; - const handleContextAction = (action, file) => { + const handleContextAction = (action: string, file: any) => { console.log(`Context action: ${action}`, file); switch (action) { case 'star': @@ -645,7 +662,7 @@ export default function FileManager() { }, []); useEffect(() => { - const handleKeyDown = (e) => { + const handleKeyDown = (e: KeyboardEvent) => { const isCtrl = e.ctrlKey || e.metaKey; const isShift = e.shiftKey; @@ -660,7 +677,7 @@ export default function FileManager() { console.log('Upload shortcut'); } else if (isCtrl && e.key === 'f') { e.preventDefault(); - document.querySelector('input[placeholder="Search files"]').focus(); + document.querySelector('input[placeholder="Search files"]')?.focus(); } else if (e.key === 'Delete' && selectedFile) { e.preventDefault(); console.log('Delete shortcut'); @@ -680,7 +697,7 @@ export default function FileManager() {
- + +
+
+
+ + + +
+
+
+ + OUTPUT +
+
+
+ READY +
+
+
+ {messages.length === 0 ? ( +
+
● SYSTEM READY ●
+
Awaiting input...
+
+ ) : ( + messages.map((message, index) => ( +
+
+ [{formatTime(message.timestamp)}] {message.sender.toUpperCase()}: +
+
+ {message.text} +
+
+ )) + )} +
+
+ + +
+ ); + } return ( -
- {/* XTreeGold-style two-row footer */} -
- {/* First row - F1-F10 keys */} -
-
- {shortcutGroups[0].map((shortcut, index) => ( -
- {shortcut.key} - {shortcut.label} -
- ))} -
-
- - {/* Second row - Other keys */} -
-
- {shortcutGroups[1].map((shortcut, index) => ( -
- {shortcut.key} - {shortcut.label} -
- ))} -
- - {/* Right side - Status/AI Assistant */} -
- - Ready - - - -
-
-
- - {/* Chat Window (optional) */} - {isChatOpen && !isChatMinimized && ( -
-
-
+
+ + +
+
-
- General Bots Assistant + + SYSTEM v3.0
-
- - +
+ + {formatTime(currentTime)} +
- -
- General Bots Assistant is ready to help with file operations. +
+
+ {shortcutGroups[0].map((shortcut, index) => ( + + ))} +
+
+
+
+ {shortcutGroups[1].map((shortcut, index) => ( + + ))}
- -
- -
-
- )} + + + +
+
+
+ + INPUT +
+
+ CMD +
+
+
+
+
+ COMMAND LINE INTERFACE +
+
+
+ > +