mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-05-13 07:49:59 +08:00
feat: add file type categorization and size formatting in FileListView
This commit is contained in:
@@ -239,6 +239,20 @@
|
||||
"Type": "Type",
|
||||
"Folder": "Folder",
|
||||
"File": "File",
|
||||
"Image": "Image",
|
||||
"Video": "Video",
|
||||
"Audio": "Audio",
|
||||
"PDF": "PDF",
|
||||
"Word": "Word",
|
||||
"Spreadsheet": "Spreadsheet",
|
||||
"Presentation": "Presentation",
|
||||
"Archive": "Archive",
|
||||
"Code": "Code",
|
||||
"Markdown": "Markdown",
|
||||
"Text": "Text",
|
||||
"Font": "Font",
|
||||
"Database": "Database",
|
||||
"Config": "Config",
|
||||
"Path": "Path",
|
||||
"Path copied to clipboard": "Path copied to clipboard",
|
||||
"Copy failed": "Copy failed",
|
||||
|
||||
@@ -258,6 +258,20 @@
|
||||
"Type": "类型",
|
||||
"Folder": "文件夹",
|
||||
"File": "文件",
|
||||
"Image": "图片",
|
||||
"Video": "视频",
|
||||
"Audio": "音频",
|
||||
"PDF": "PDF",
|
||||
"Word": "Word 文档",
|
||||
"Spreadsheet": "表格",
|
||||
"Presentation": "演示文稿",
|
||||
"Archive": "压缩包",
|
||||
"Code": "代码",
|
||||
"Markdown": "Markdown",
|
||||
"Text": "文本",
|
||||
"Font": "字体",
|
||||
"Database": "数据库",
|
||||
"Config": "配置",
|
||||
"Path": "路径",
|
||||
"Path copied to clipboard": "路径已复制到剪贴板",
|
||||
"Copy failed": "复制失败",
|
||||
@@ -775,7 +789,6 @@
|
||||
"Users": "用户",
|
||||
"Create User": "创建用户",
|
||||
"Create Role": "创建角色",
|
||||
"Edit": "编辑",
|
||||
"Submit": "提交",
|
||||
"Super Admin": "超级管理员",
|
||||
"Disabled": "已禁用",
|
||||
@@ -796,14 +809,11 @@
|
||||
"Is Regex": "正则表达式",
|
||||
"Priority": "优先级",
|
||||
"Higher value = higher priority": "数值越大优先级越高",
|
||||
"Permissions": "权限",
|
||||
"System Permissions": "系统权限",
|
||||
"Download and preview files": "下载和预览文件",
|
||||
"Upload and modify files": "上传和修改文件",
|
||||
"Delete files and folders": "删除文件和目录",
|
||||
"Create share links": "创建分享链接",
|
||||
"Share": "分享",
|
||||
"Delete": "删除",
|
||||
"permission.category.system": "系统",
|
||||
"permission.category.adapter": "存储适配器"
|
||||
}
|
||||
|
||||
@@ -19,6 +19,45 @@ interface FileListViewProps {
|
||||
onContextMenu: (e: React.MouseEvent, entry: VfsEntry) => void;
|
||||
}
|
||||
|
||||
const fileTypeGroups: Array<{ key: string; exts: string[] }> = [
|
||||
{ key: 'Image', exts: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'ico', 'tiff'] },
|
||||
{ key: 'Video', exts: ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'webm', 'm4v', '3gp'] },
|
||||
{ key: 'Audio', exts: ['mp3', 'wav', 'flac', 'aac', 'ogg', 'wma', 'm4a'] },
|
||||
{ key: 'PDF', exts: ['pdf'] },
|
||||
{ key: 'Word', exts: ['doc', 'docx'] },
|
||||
{ key: 'Spreadsheet', exts: ['xls', 'xlsx', 'csv'] },
|
||||
{ key: 'Presentation', exts: ['ppt', 'pptx'] },
|
||||
{ key: 'Archive', exts: ['zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz'] },
|
||||
{ key: 'Code', exts: ['js', 'jsx', 'ts', 'tsx', 'vue', 'html', 'htm', 'css', 'scss', 'sass', 'less', 'json', 'xml', 'yaml', 'yml', 'py', 'java', 'cpp', 'cc', 'cxx', 'c', 'h', 'hpp', 'hxx', 'php', 'rb', 'go', 'rs', 'rust', 'swift', 'kt', 'scala', 'clj', 'cljs', 'cs', 'vb', 'fs', 'pl', 'pm', 'r', 'lua', 'dart', 'elm'] },
|
||||
{ key: 'Markdown', exts: ['md', 'markdown'] },
|
||||
{ key: 'Text', exts: ['txt', 'log', 'ini', 'cfg', 'conf', 'sh', 'bash', 'zsh', 'fish', 'ps1', 'bat', 'cmd', 'dockerfile', 'makefile', 'gradle', 'cmake', 'gitignore', 'gitattributes', 'editorconfig', 'prettierrc'] },
|
||||
{ key: 'Font', exts: ['ttf', 'otf', 'woff', 'woff2', 'eot'] },
|
||||
{ key: 'Database', exts: ['db', 'sqlite', 'sql'] },
|
||||
{ key: 'Config', exts: ['env', 'config', 'properties', 'toml'] },
|
||||
];
|
||||
|
||||
const formatFileSize = (size: number) => {
|
||||
if (!Number.isFinite(size) || size < 0) return '-';
|
||||
const units = ['B', 'KB', 'MB', 'GB'];
|
||||
let value = size;
|
||||
let unitIndex = 0;
|
||||
while (value >= 1024 && unitIndex < units.length - 1) {
|
||||
value /= 1024;
|
||||
unitIndex += 1;
|
||||
}
|
||||
if (unitIndex === 0) return `${value} ${units[unitIndex]}`;
|
||||
return `${value.toFixed(2)} ${units[unitIndex]}`;
|
||||
};
|
||||
|
||||
const getFileTypeLabel = (entry: VfsEntry, t: (key: string) => string) => {
|
||||
if (entry.type === 'mount') return t('Mount Point');
|
||||
if (entry.is_dir) return t('Folder');
|
||||
|
||||
const ext = entry.name.split('.').pop()?.toLowerCase() || '';
|
||||
const group = fileTypeGroups.find(item => item.exts.includes(ext));
|
||||
return t(group?.key || 'File');
|
||||
};
|
||||
|
||||
export const FileListView: React.FC<FileListViewProps> = ({
|
||||
entries,
|
||||
selectedEntries,
|
||||
@@ -63,7 +102,8 @@ export const FileListView: React.FC<FileListViewProps> = ({
|
||||
</span>
|
||||
)
|
||||
},
|
||||
{ title: t('Size'), dataIndex: 'size', width: 100, render: (v: number, r: VfsEntry) => r.is_dir ? '-' : v },
|
||||
{ title: t('Type'), key: 'fileType', width: 110, render: (_: any, r: VfsEntry) => getFileTypeLabel(r, t) },
|
||||
{ title: t('Size'), dataIndex: 'size', width: 120, render: (v: number, r: VfsEntry) => r.is_dir ? '-' : formatFileSize(v) },
|
||||
{ title: t('Modified Time'), dataIndex: 'mtime', width: 160, render: (v: number) => v ? new Date(v * 1000).toLocaleString() : '-' },
|
||||
{
|
||||
title: t('Actions'),
|
||||
|
||||
Reference in New Issue
Block a user