From d2440c5ba18e22c633af8a8af32c8d2bafaebe66 Mon Sep 17 00:00:00 2001 From: Jaime Idolpx Date: Mon, 8 Jun 2026 13:47:26 -0400 Subject: [PATCH] feat(MediaBrowser, MediaManager): enhance file type handling and improve icon representation --- src/app/components/MediaBrowser.tsx | 64 ++++++++++++++++++------- src/app/components/MediaManager.tsx | 72 ++++++++++++++--------------- 2 files changed, 82 insertions(+), 54 deletions(-) diff --git a/src/app/components/MediaBrowser.tsx b/src/app/components/MediaBrowser.tsx index f24a3eb..ea342e3 100644 --- a/src/app/components/MediaBrowser.tsx +++ b/src/app/components/MediaBrowser.tsx @@ -1,20 +1,30 @@ import { useEffect, useRef, useState } from 'react'; import { - Folder, + ArrowLeft, + BookOpen, + Braces, + CassetteTape, + Check, + ChevronRight, + Code2, + Cpu, + Disc, + Save, File, FileText, - HardDrive, - Image as ImageIcon, - ChevronRight, - Home, - RefreshCw, - Upload, + Folder, FolderPlus, - ArrowLeft, + HardDrive, + Home, + Image as ImageIcon, Loader2, MoreVertical, - Check, + Music, + Package, + RefreshCw, + SlidersHorizontal, Trash2, + Upload, } from 'lucide-react'; import { createFolder, @@ -37,17 +47,37 @@ import { DialogDescription, } from './ui/dialog'; -const TEXT_EXTS = new Set(['txt','cfg','ini','bas','asm','seq','rel','prg','log','csv','s','lst','md','markdown','json','xml','svg','html','htm']); -const IMAGE_EXTS = new Set(['png','jpg','jpeg','gif','bmp','webp']); -const DISK_EXTS = new Set(['d64','d71','d81','d82','g64','g71','t64','tap','crt','nib']); +const TEXT_EXTS = new Set(['txt','cfg','ini','bas','asm','seq','rel','prg','log','csv','s','lst']); +const MD_EXTS = new Set(['md','markdown']); +const JSON_EXTS = new Set(['json']); +const XML_EXTS = new Set(['xml','svg','html','htm','rss','atom','xsl']); +const IMAGE_EXTS = new Set(['png','jpg','jpeg','gif','bmp','webp']); +const AUDIO_EXTS = new Set(['sid','psid','mus','vgm']); +const ROM_EXTS = new Set(['bin','rom','crt']); +const TAPE_EXTS = new Set(['tap','t64','tcrt']); +const DISK_EXTS = new Set(['d41','d64','d71','d80','d81','d82','d8b','dfi','g64','g71','g81','p64','p71','p81','nib']); +const DISC_EXTS = new Set(['iso','img','cue']); +const HD_EXTS = new Set(['d1m','d2m','d4m','d90','dhd','hdd']); +const ARCHIVE_EXTS = new Set(['zip','7z','tar','gz','bz2','xz','rar','arj','lzh','ace','z','lha','cab','lbr','arc','ark','lnx']); +const CONFIG_EXTS = new Set(['config']); function EntryIcon({ entry }: { entry: EntryInfo }) { - if (entry.type === 'folder') return ; + if (entry.type === 'folder') return ; const ext = entry.name.split('.').pop()?.toLowerCase() ?? ''; - if (IMAGE_EXTS.has(ext)) return ; - if (DISK_EXTS.has(ext)) return ; - if (TEXT_EXTS.has(ext)) return ; - return ; + if (IMAGE_EXTS.has(ext)) return ; + if (DISK_EXTS.has(ext)) return ; + if (HD_EXTS.has(ext)) return ; + if (DISC_EXTS.has(ext)) return ; + if (TAPE_EXTS.has(ext)) return ; + if (ROM_EXTS.has(ext)) return ; + if (AUDIO_EXTS.has(ext)) return ; + if (ARCHIVE_EXTS.has(ext)) return ; + if (CONFIG_EXTS.has(ext)) return ; + if (JSON_EXTS.has(ext)) return ; + if (XML_EXTS.has(ext)) return ; + if (MD_EXTS.has(ext)) return ; + if (TEXT_EXTS.has(ext)) return ; + return ; } interface MediaBrowserProps { diff --git a/src/app/components/MediaManager.tsx b/src/app/components/MediaManager.tsx index daf4a14..148e2f1 100644 --- a/src/app/components/MediaManager.tsx +++ b/src/app/components/MediaManager.tsx @@ -4,6 +4,7 @@ import { ArrowLeft, BookOpen, Braces, + CassetteTape, Check, CheckSquare, ChevronLeft, @@ -11,6 +12,8 @@ import { ClipboardPaste, Code2, Copy, + Cpu, + Disc, Download, Eye, File, @@ -25,6 +28,8 @@ import { Loader2, MoreVertical, Move, + Music, + Package, SlidersHorizontal, Pencil, RefreshCw, @@ -70,40 +75,23 @@ import { type SortKey = 'name' | 'size' | 'date'; type Clipboard = { op: 'copy' | 'move'; paths: string[] }; -type FileCategory = 'text' | 'image' | 'disk' | 'binary'; -type ViewMode = 'text' | 'markdown' | 'json' | 'xml' | 'hex' | 'image' | 'config'; +type ViewMode = 'text' | 'markdown' | 'json' | 'xml' | 'hex' | 'image' | 'config'; // ─── Extension sets ────────────────────────────────────────────────────────── -const TEXT_EXTS = new Set(['txt', 'cfg', 'ini', 'bas', 'asm', 'seq', 'rel', 'prg', 'log', 'csv', 's', 'lst']); -const MD_EXTS = new Set(['md', 'markdown']); -const JSON_EXTS = new Set(['json']); -const XML_EXTS = new Set(['xml', 'svg', 'html', 'htm', 'rss', 'atom', 'xsl']); -const IMAGE_EXTS = new Set(['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp']); -const AUDIO_EXTS = new Set(['sid', 'psid', 'mus', 'vgm']); -const ROM_EXTS = new Set(['bin', 'rom', 'crt']); -const TAPE_EXTS = new Set(['tap', 't64', 'tcrt']); -const DISK_EXTS = new Set(['d41', 'd64', 'd71', 'd80', 'd81', 'd82', 'd90', 'd8b', 'dfi', 'g64', 'g71', 'g81', 'p64', 'p71', 'p81', 'nib']); -const DISC_EXTS = new Set(['iso', 'img', 'cue']); -const HD_EXTS = new Set(['d1m', 'd2m', 'd4m', 'dhd', 'hdd']); -const ARCHIVE_EXTS = new Set(['zip', '7z', 'tar', 'gz', 'bz2', 'xz', 'rar', 'arj', 'lzh', 'ace', 'z', 'lha', 'cab', 'lbr', 'arc', 'ark', 'lnx']); -const CONFIG_EXTS = new Set(['config']); - -function fileCategory(entry: EntryInfo): FileCategory { - if (entry.type === 'folder') return 'binary'; - const ext = entry.name.split('.').pop()?.toLowerCase() ?? ''; - if (IMAGE_EXTS.has(ext)) return 'image'; - if (DISK_EXTS.has(ext)) return 'disk'; - if (HD_EXTS.has(ext)) return 'disk'; - if (ROM_EXTS.has(ext)) return 'disk'; - if (TAPE_EXTS.has(ext)) return 'disk'; - if (AUDIO_EXTS.has(ext)) return 'disk'; - if (ARCHIVE_EXTS.has(ext)) return 'disk'; - if (DISC_EXTS.has(ext)) return 'disk'; - if (CONFIG_EXTS.has(ext)) return 'text'; - if (TEXT_EXTS.has(ext) || MD_EXTS.has(ext) || JSON_EXTS.has(ext) || XML_EXTS.has(ext)) return 'text'; - return 'binary'; -} +const TEXT_EXTS = new Set(['txt', 'cfg', 'ini', 'bas', 'asm', 'seq', 'rel', 'prg', 'log', 'csv', 's', 'lst']); +const MD_EXTS = new Set(['md', 'markdown']); +const JSON_EXTS = new Set(['json']); +const XML_EXTS = new Set(['xml', 'svg', 'html', 'htm', 'rss', 'atom', 'xsl']); +const IMAGE_EXTS = new Set(['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp']); +const AUDIO_EXTS = new Set(['sid', 'psid', 'mus', 'vgm']); +const ROM_EXTS = new Set(['bin', 'rom', 'crt']); +const TAPE_EXTS = new Set(['tap', 'htap', 't64', 'tcrt']); +const DISK_EXTS = new Set(['d41', 'd64', 'd71', 'd80', 'd81', 'd82', 'g64', 'g71', 'g81', 'p64', 'p71', 'p81', 'nib']); +const DISC_EXTS = new Set(['iso', 'img', 'cue']); +const HD_EXTS = new Set(['d1m', 'd2m', 'd4m', 'd90', 'dhd', 'hdd']); +const ARCHIVE_EXTS = new Set(['zip', '7z', 'tar', 'gz', 'bz2', 'xz', 'rar', 'arj', 'lzh', 'ace', 'z', 'lha', 'cab', 'lbr', 'arc', 'ark', 'lnx', 'bbt', 'd8b', 'dfi']); +const CONFIG_EXTS = new Set(['config']); function defaultViewMode(entry: EntryInfo): ViewMode { const ext = entry.name.split('.').pop()?.toLowerCase() ?? ''; @@ -258,12 +246,22 @@ function MarkdownEditor({ text, onSave }: { text: string; onSave?: (s: string) = // ─── Entry icon ─────────────────────────────────────────────────────────────── function EntryIcon({ entry }: { entry: EntryInfo }) { - if (entry.type === 'folder') return ; - const cat = fileCategory(entry); - if (cat === 'image') return ; - if (cat === 'disk') return ; - if (cat === 'text') return ; - return ; + if (entry.type === 'folder') return ; + const ext = entry.name.split('.').pop()?.toLowerCase() ?? ''; + if (IMAGE_EXTS.has(ext)) return ; + if (DISK_EXTS.has(ext)) return ; + if (HD_EXTS.has(ext)) return ; + if (DISC_EXTS.has(ext)) return ; + if (TAPE_EXTS.has(ext)) return ; + if (ROM_EXTS.has(ext)) return ; + if (AUDIO_EXTS.has(ext)) return ; + if (ARCHIVE_EXTS.has(ext)) return ; + if (CONFIG_EXTS.has(ext)) return ; + if (JSON_EXTS.has(ext)) return ; + if (XML_EXTS.has(ext)) return ; + if (MD_EXTS.has(ext)) return ; + if (TEXT_EXTS.has(ext)) return ; + return ; } // ─── ActionsModal ─────────────────────────────────────────────────────────────