feat(MediaBrowser, MediaManager): enhance file type handling and improve icon representation
This commit is contained in:
parent
b70c98d69a
commit
d2440c5ba1
|
|
@ -1,20 +1,30 @@
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Folder,
|
ArrowLeft,
|
||||||
|
BookOpen,
|
||||||
|
Braces,
|
||||||
|
CassetteTape,
|
||||||
|
Check,
|
||||||
|
ChevronRight,
|
||||||
|
Code2,
|
||||||
|
Cpu,
|
||||||
|
Disc,
|
||||||
|
Save,
|
||||||
File,
|
File,
|
||||||
FileText,
|
FileText,
|
||||||
HardDrive,
|
Folder,
|
||||||
Image as ImageIcon,
|
|
||||||
ChevronRight,
|
|
||||||
Home,
|
|
||||||
RefreshCw,
|
|
||||||
Upload,
|
|
||||||
FolderPlus,
|
FolderPlus,
|
||||||
ArrowLeft,
|
HardDrive,
|
||||||
|
Home,
|
||||||
|
Image as ImageIcon,
|
||||||
Loader2,
|
Loader2,
|
||||||
MoreVertical,
|
MoreVertical,
|
||||||
Check,
|
Music,
|
||||||
|
Package,
|
||||||
|
RefreshCw,
|
||||||
|
SlidersHorizontal,
|
||||||
Trash2,
|
Trash2,
|
||||||
|
Upload,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import {
|
import {
|
||||||
createFolder,
|
createFolder,
|
||||||
|
|
@ -37,15 +47,35 @@ import {
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
} from './ui/dialog';
|
} 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 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 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 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 }) {
|
function EntryIcon({ entry }: { entry: EntryInfo }) {
|
||||||
if (entry.type === 'folder') return <Folder className="w-5 h-5 text-blue-500 flex-shrink-0" />;
|
if (entry.type === 'folder') return <Folder className="w-5 h-5 text-blue-500 flex-shrink-0" />;
|
||||||
const ext = entry.name.split('.').pop()?.toLowerCase() ?? '';
|
const ext = entry.name.split('.').pop()?.toLowerCase() ?? '';
|
||||||
if (IMAGE_EXTS.has(ext)) return <ImageIcon className="w-5 h-5 text-purple-500 flex-shrink-0" />;
|
if (IMAGE_EXTS.has(ext)) return <ImageIcon className="w-5 h-5 text-purple-500 flex-shrink-0" />;
|
||||||
if (DISK_EXTS.has(ext)) return <HardDrive className="w-5 h-5 text-amber-500 flex-shrink-0" />;
|
if (DISK_EXTS.has(ext)) return <Save className="w-5 h-5 text-amber-500 flex-shrink-0" />;
|
||||||
|
if (HD_EXTS.has(ext)) return <HardDrive className="w-5 h-5 text-orange-500 flex-shrink-0" />;
|
||||||
|
if (DISC_EXTS.has(ext)) return <Disc className="w-5 h-5 text-sky-500 flex-shrink-0" />;
|
||||||
|
if (TAPE_EXTS.has(ext)) return <CassetteTape className="w-5 h-5 text-rose-400 flex-shrink-0" />;
|
||||||
|
if (ROM_EXTS.has(ext)) return <Cpu className="w-5 h-5 text-red-500 flex-shrink-0" />;
|
||||||
|
if (AUDIO_EXTS.has(ext)) return <Music className="w-5 h-5 text-teal-500 flex-shrink-0" />;
|
||||||
|
if (ARCHIVE_EXTS.has(ext)) return <Package className="w-5 h-5 text-yellow-600 flex-shrink-0" />;
|
||||||
|
if (CONFIG_EXTS.has(ext)) return <SlidersHorizontal className="w-5 h-5 text-slate-400 flex-shrink-0" />;
|
||||||
|
if (JSON_EXTS.has(ext)) return <Braces className="w-5 h-5 text-yellow-500 flex-shrink-0" />;
|
||||||
|
if (XML_EXTS.has(ext)) return <Code2 className="w-5 h-5 text-cyan-500 flex-shrink-0" />;
|
||||||
|
if (MD_EXTS.has(ext)) return <BookOpen className="w-5 h-5 text-sky-400 flex-shrink-0" />;
|
||||||
if (TEXT_EXTS.has(ext)) return <FileText className="w-5 h-5 text-green-600 flex-shrink-0" />;
|
if (TEXT_EXTS.has(ext)) return <FileText className="w-5 h-5 text-green-600 flex-shrink-0" />;
|
||||||
return <File className="w-5 h-5 text-neutral-400 flex-shrink-0" />;
|
return <File className="w-5 h-5 text-neutral-400 flex-shrink-0" />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import {
|
||||||
ArrowLeft,
|
ArrowLeft,
|
||||||
BookOpen,
|
BookOpen,
|
||||||
Braces,
|
Braces,
|
||||||
|
CassetteTape,
|
||||||
Check,
|
Check,
|
||||||
CheckSquare,
|
CheckSquare,
|
||||||
ChevronLeft,
|
ChevronLeft,
|
||||||
|
|
@ -11,6 +12,8 @@ import {
|
||||||
ClipboardPaste,
|
ClipboardPaste,
|
||||||
Code2,
|
Code2,
|
||||||
Copy,
|
Copy,
|
||||||
|
Cpu,
|
||||||
|
Disc,
|
||||||
Download,
|
Download,
|
||||||
Eye,
|
Eye,
|
||||||
File,
|
File,
|
||||||
|
|
@ -25,6 +28,8 @@ import {
|
||||||
Loader2,
|
Loader2,
|
||||||
MoreVertical,
|
MoreVertical,
|
||||||
Move,
|
Move,
|
||||||
|
Music,
|
||||||
|
Package,
|
||||||
SlidersHorizontal,
|
SlidersHorizontal,
|
||||||
Pencil,
|
Pencil,
|
||||||
RefreshCw,
|
RefreshCw,
|
||||||
|
|
@ -70,7 +75,6 @@ import {
|
||||||
|
|
||||||
type SortKey = 'name' | 'size' | 'date';
|
type SortKey = 'name' | 'size' | 'date';
|
||||||
type Clipboard = { op: 'copy' | 'move'; paths: string[] };
|
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 ──────────────────────────────────────────────────────────
|
// ─── Extension sets ──────────────────────────────────────────────────────────
|
||||||
|
|
@ -82,29 +86,13 @@ const XML_EXTS = new Set(['xml', 'svg', 'html', 'htm', 'rss', 'atom', 'xsl']);
|
||||||
const IMAGE_EXTS = new Set(['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp']);
|
const IMAGE_EXTS = new Set(['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp']);
|
||||||
const AUDIO_EXTS = new Set(['sid', 'psid', 'mus', 'vgm']);
|
const AUDIO_EXTS = new Set(['sid', 'psid', 'mus', 'vgm']);
|
||||||
const ROM_EXTS = new Set(['bin', 'rom', 'crt']);
|
const ROM_EXTS = new Set(['bin', 'rom', 'crt']);
|
||||||
const TAPE_EXTS = new Set(['tap', 't64', 'tcrt']);
|
const TAPE_EXTS = new Set(['tap', 'htap', 't64', 'tcrt']);
|
||||||
const DISK_EXTS = new Set(['d41', 'd64', 'd71', 'd80', 'd81', 'd82', 'd90', 'd8b', 'dfi', 'g64', 'g71', 'g81', 'p64', 'p71', 'p81', 'nib']);
|
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 DISC_EXTS = new Set(['iso', 'img', 'cue']);
|
||||||
const HD_EXTS = new Set(['d1m', 'd2m', 'd4m', 'dhd', 'hdd']);
|
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 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']);
|
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';
|
|
||||||
}
|
|
||||||
|
|
||||||
function defaultViewMode(entry: EntryInfo): ViewMode {
|
function defaultViewMode(entry: EntryInfo): ViewMode {
|
||||||
const ext = entry.name.split('.').pop()?.toLowerCase() ?? '';
|
const ext = entry.name.split('.').pop()?.toLowerCase() ?? '';
|
||||||
if (IMAGE_EXTS.has(ext)) return 'image';
|
if (IMAGE_EXTS.has(ext)) return 'image';
|
||||||
|
|
@ -259,10 +247,20 @@ function MarkdownEditor({ text, onSave }: { text: string; onSave?: (s: string) =
|
||||||
|
|
||||||
function EntryIcon({ entry }: { entry: EntryInfo }) {
|
function EntryIcon({ entry }: { entry: EntryInfo }) {
|
||||||
if (entry.type === 'folder') return <Folder className="w-5 h-5 text-blue-500 flex-shrink-0" />;
|
if (entry.type === 'folder') return <Folder className="w-5 h-5 text-blue-500 flex-shrink-0" />;
|
||||||
const cat = fileCategory(entry);
|
const ext = entry.name.split('.').pop()?.toLowerCase() ?? '';
|
||||||
if (cat === 'image') return <ImageIcon className="w-5 h-5 text-purple-500 flex-shrink-0" />;
|
if (IMAGE_EXTS.has(ext)) return <ImageIcon className="w-5 h-5 text-purple-500 flex-shrink-0" />;
|
||||||
if (cat === 'disk') return <HardDrive className="w-5 h-5 text-amber-500 flex-shrink-0" />;
|
if (DISK_EXTS.has(ext)) return <Save className="w-5 h-5 text-amber-500 flex-shrink-0" />;
|
||||||
if (cat === 'text') return <FileText className="w-5 h-5 text-green-600 flex-shrink-0" />;
|
if (HD_EXTS.has(ext)) return <HardDrive className="w-5 h-5 text-orange-500 flex-shrink-0" />;
|
||||||
|
if (DISC_EXTS.has(ext)) return <Disc className="w-5 h-5 text-sky-500 flex-shrink-0" />;
|
||||||
|
if (TAPE_EXTS.has(ext)) return <CassetteTape className="w-5 h-5 text-rose-400 flex-shrink-0" />;
|
||||||
|
if (ROM_EXTS.has(ext)) return <Cpu className="w-5 h-5 text-red-500 flex-shrink-0" />;
|
||||||
|
if (AUDIO_EXTS.has(ext)) return <Music className="w-5 h-5 text-teal-500 flex-shrink-0" />;
|
||||||
|
if (ARCHIVE_EXTS.has(ext)) return <Package className="w-5 h-5 text-yellow-600 flex-shrink-0" />;
|
||||||
|
if (CONFIG_EXTS.has(ext)) return <SlidersHorizontal className="w-5 h-5 text-slate-400 flex-shrink-0" />;
|
||||||
|
if (JSON_EXTS.has(ext)) return <Braces className="w-5 h-5 text-yellow-500 flex-shrink-0" />;
|
||||||
|
if (XML_EXTS.has(ext)) return <Code2 className="w-5 h-5 text-cyan-500 flex-shrink-0" />;
|
||||||
|
if (MD_EXTS.has(ext)) return <BookOpen className="w-5 h-5 text-sky-400 flex-shrink-0" />;
|
||||||
|
if (TEXT_EXTS.has(ext)) return <FileText className="w-5 h-5 text-green-600 flex-shrink-0" />;
|
||||||
return <File className="w-5 h-5 text-neutral-400 flex-shrink-0" />;
|
return <File className="w-5 h-5 text-neutral-400 flex-shrink-0" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user