From 417df31aa76f9fb49058171eb7acd4fd57cb865c Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Sun, 9 Nov 2025 15:17:11 +0800 Subject: [PATCH] feat: Add file color coding in file manager - Files: blue (text-blue-400) - Folders: red (text-red-400) - Symlinks: green (text-green-400) - Add toggle in User Profile settings - Store preference in localStorage - Support i18n (en, zh) - Can be disabled via settings - Matches dark theme color scheme --- src/locales/en/translation.json | 2 + src/locales/zh/translation.json | 2 + .../apps/file-manager/FileManagerGrid.tsx | 42 +++++++++++++------ src/ui/desktop/user/UserProfile.tsx | 28 +++++++++++++ 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 28296a66..0fe90342 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -1479,6 +1479,8 @@ "local": "Local", "external": "External (OIDC)", "selectPreferredLanguage": "Select your preferred language for the interface", + "fileColorCoding": "File Color Coding", + "fileColorCodingDesc": "Color-code files by type: folders (red), files (blue), symlinks (green)", "currentPassword": "Current Password", "passwordChangedSuccess": "Password changed successfully! Please log in again.", "failedToChangePassword": "Failed to change password. Please check your current password and try again." diff --git a/src/locales/zh/translation.json b/src/locales/zh/translation.json index 3495f971..5561e41c 100644 --- a/src/locales/zh/translation.json +++ b/src/locales/zh/translation.json @@ -1442,6 +1442,8 @@ "local": "本地", "external": "外部 (OIDC)", "selectPreferredLanguage": "选择您的界面首选语言", + "fileColorCoding": "文件颜色编码", + "fileColorCodingDesc": "按类型对文件进行颜色编码:文件夹(红色)、文件(蓝色)、符号链接(绿色)", "currentPassword": "当前密码", "passwordChangedSuccess": "密码修改成功!请重新登录。", "failedToChangePassword": "修改密码失败。请检查您当前的密码并重试。" diff --git a/src/ui/desktop/apps/file-manager/FileManagerGrid.tsx b/src/ui/desktop/apps/file-manager/FileManagerGrid.tsx index 8809a7bd..5c1a0ac8 100644 --- a/src/ui/desktop/apps/file-manager/FileManagerGrid.tsx +++ b/src/ui/desktop/apps/file-manager/FileManagerGrid.tsx @@ -96,15 +96,33 @@ interface FileManagerGridProps { onNewFolder?: () => void; } -const getFileIcon = (file: FileItem, viewMode: "grid" | "list" = "grid") => { - const iconClass = viewMode === "grid" ? "w-8 h-8" : "w-6 h-6"; +const getFileTypeColor = (file: FileItem): string => { + const colorEnabled = localStorage.getItem("fileColorCoding") !== "false"; + if (!colorEnabled) { + return "text-muted-foreground"; + } if (file.type === "directory") { - return ; + return "text-red-400"; } if (file.type === "link") { - return ; + return "text-green-400"; + } + + return "text-blue-400"; +}; + +const getFileIcon = (file: FileItem, viewMode: "grid" | "list" = "grid") => { + const iconClass = viewMode === "grid" ? "w-8 h-8" : "w-6 h-6"; + const colorClass = getFileTypeColor(file); + + if (file.type === "directory") { + return ; + } + + if (file.type === "link") { + return ; } const ext = file.name.split(".").pop()?.toLowerCase(); @@ -113,30 +131,30 @@ const getFileIcon = (file: FileItem, viewMode: "grid" | "list" = "grid") => { case "txt": case "md": case "readme": - return ; + return ; case "png": case "jpg": case "jpeg": case "gif": case "bmp": case "svg": - return ; + return ; case "mp4": case "avi": case "mkv": case "mov": - return ; + return ; case "mp3": case "wav": case "flac": case "ogg": - return ; + return ; case "zip": case "tar": case "gz": case "rar": case "7z": - return ; + return ; case "js": case "ts": case "jsx": @@ -150,7 +168,7 @@ const getFileIcon = (file: FileItem, viewMode: "grid" | "list" = "grid") => { case "rb": case "go": case "rs": - return ; + return ; case "json": case "xml": case "yaml": @@ -159,9 +177,9 @@ const getFileIcon = (file: FileItem, viewMode: "grid" | "list" = "grid") => { case "ini": case "conf": case "config": - return ; + return ; default: - return ; + return ; } }; diff --git a/src/ui/desktop/user/UserProfile.tsx b/src/ui/desktop/user/UserProfile.tsx index dfc9c709..77734431 100644 --- a/src/ui/desktop/user/UserProfile.tsx +++ b/src/ui/desktop/user/UserProfile.tsx @@ -10,6 +10,7 @@ import { TabsTrigger, } from "@/components/ui/tabs.tsx"; import { Separator } from "@/components/ui/separator.tsx"; +import { Switch } from "@/components/ui/switch.tsx"; import { User, Shield, AlertCircle } from "lucide-react"; import { TOTPSetup } from "@/ui/desktop/user/TOTPSetup.tsx"; import { @@ -87,6 +88,9 @@ export function UserProfile({ isTopbarOpen = true }: UserProfileProps) { const [deletePassword, setDeletePassword] = useState(""); const [deleteLoading, setDeleteLoading] = useState(false); const [deleteError, setDeleteError] = useState(null); + const [fileColorCoding, setFileColorCoding] = useState( + localStorage.getItem("fileColorCoding") !== "false" + ); useEffect(() => { fetchUserInfo(); @@ -128,6 +132,13 @@ export function UserProfile({ isTopbarOpen = true }: UserProfileProps) { } }; + const handleFileColorCodingToggle = (enabled: boolean) => { + setFileColorCoding(enabled); + localStorage.setItem("fileColorCoding", enabled.toString()); + // Trigger a re-render by dispatching a custom event + window.dispatchEvent(new Event("fileColorCodingChanged")); + }; + const handleDeleteAccount = async (e: React.FormEvent) => { e.preventDefault(); setDeleteLoading(true); @@ -325,6 +336,23 @@ export function UserProfile({ isTopbarOpen = true }: UserProfileProps) { +
+
+
+ +

+ {t("profile.fileColorCodingDesc")} +

+
+ +
+
+