Browse Source

feat: support ico format for tray icon (#911)

MystiPanda 1 year ago
parent
commit
e014fdf3da

+ 12 - 1
src-tauri/Cargo.lock

@@ -2411,6 +2411,16 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "ico"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "031530fe562d8c8d71c0635013d6d155bbfe8ba0aa4b4d2d24ce8af6b71047bd"
+dependencies = [
+ "byteorder",
+ "png",
+]
+
 [[package]]
 name = "ico"
 version = "0.3.0"
@@ -5248,6 +5258,7 @@ dependencies = [
  "gtk",
  "heck 0.4.1",
  "http 0.2.11",
+ "ico 0.2.0",
  "ignore",
  "indexmap 1.9.3",
  "infer 0.9.0",
@@ -5316,7 +5327,7 @@ checksum = "a1554c5857f65dbc377cefb6b97c8ac77b1cb2a90d30d3448114d5d6b48a77fc"
 dependencies = [
  "base64 0.21.7",
  "brotli",
- "ico",
+ "ico 0.3.0",
  "json-patch",
  "plist",
  "png",

+ 1 - 1
src-tauri/Cargo.toml

@@ -37,7 +37,7 @@ serde = { version = "1.0", features = ["derive"] }
 reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
 sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" }
 auto-launch = { git="https://github.com/zzzgydi/auto-launch", branch = "main" }
-tauri = { version = "1.6", features = [ "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
+tauri = { version = "1.6", features = [ "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
 
 [target.'cfg(windows)'.dependencies]
 runas = "=1.2.0"

+ 10 - 2
src-tauri/src/cmds.rs

@@ -299,9 +299,17 @@ pub fn copy_icon_file(path: String, name: String) -> CmdResult<String> {
     if !icon_dir.exists() {
         let _ = std::fs::create_dir_all(&icon_dir);
     }
-    let dest_path = icon_dir.join(name);
-
+    let ext = match file_path.extension() {
+        Some(e) => e.to_string_lossy().to_string(),
+        None => "ico".to_string(),
+    };
+
+    let png_dest_path = icon_dir.join(format!("{name}.png"));
+    let ico_dest_path = icon_dir.join(format!("{name}.ico"));
+    let dest_path = icon_dir.join(format!("{name}.{ext}"));
     if file_path.exists() {
+        std::fs::remove_file(png_dest_path).unwrap_or_default();
+        std::fs::remove_file(ico_dest_path).unwrap_or_default();
         match std::fs::copy(file_path, &dest_path) {
             Ok(_) => Ok(dest_path.to_string_lossy().to_string()),
             Err(err) => Err(err.to_string()),

+ 21 - 9
src-tauri/src/core/tray.rs

@@ -182,9 +182,13 @@ impl Tray {
             #[cfg(target_os = "macos")]
             let mut icon = include_bytes!("../../icons/mac-tray-icon-sys.png").to_vec();
             if *sysproxy_tray_icon {
-                let path = dirs::app_home_dir()?.join("icons").join("sysproxy.png");
-                if path.exists() {
-                    icon = std::fs::read(path).unwrap();
+                let icon_dir_path = dirs::app_home_dir()?.join("icons");
+                let png_path = icon_dir_path.join("sysproxy.png");
+                let ico_path = icon_dir_path.join("sysproxy.ico");
+                if ico_path.exists() {
+                    icon = std::fs::read(ico_path).unwrap();
+                } else if png_path.exists() {
+                    icon = std::fs::read(png_path).unwrap();
                 }
             }
             icon
@@ -194,9 +198,13 @@ impl Tray {
             #[cfg(target_os = "macos")]
             let mut icon = include_bytes!("../../icons/mac-tray-icon.png").to_vec();
             if *common_tray_icon {
-                let path = dirs::app_home_dir()?.join("icons").join("common.png");
-                if path.exists() {
-                    icon = std::fs::read(path).unwrap();
+                let icon_dir_path = dirs::app_home_dir()?.join("icons");
+                let png_path = icon_dir_path.join("common.png");
+                let ico_path = icon_dir_path.join("common.ico");
+                if ico_path.exists() {
+                    icon = std::fs::read(ico_path).unwrap();
+                } else if png_path.exists() {
+                    icon = std::fs::read(png_path).unwrap();
                 }
             }
             icon
@@ -208,9 +216,13 @@ impl Tray {
             #[cfg(target_os = "macos")]
             let mut icon = include_bytes!("../../icons/mac-tray-icon-tun.png").to_vec();
             if *tun_tray_icon {
-                let path = dirs::app_home_dir()?.join("icons").join("tun.png");
-                if path.exists() {
-                    icon = std::fs::read(path).unwrap();
+                let icon_dir_path = dirs::app_home_dir()?.join("icons");
+                let png_path = icon_dir_path.join("tun.png");
+                let ico_path = icon_dir_path.join("tun.ico");
+                if ico_path.exists() {
+                    icon = std::fs::read(ico_path).unwrap();
+                } else if png_path.exists() {
+                    icon = std::fs::read(png_path).unwrap();
                 }
             }
             indication_icon = icon

+ 4 - 0
src-tauri/tauri.conf.json

@@ -66,6 +66,10 @@
       },
       "path": {
         "all": true
+      },
+      "fs": {
+        "exists": true,
+        "scope": ["$APPDATA/**", "$RESOURCE/../**"]
       }
     },
     "windows": [],

+ 31 - 12
src/components/setting/mods/layout-viewer.tsx

@@ -9,6 +9,7 @@ import { open as openDialog } from "@tauri-apps/api/dialog";
 import { convertFileSrc } from "@tauri-apps/api/tauri";
 import { copyIconFile, getAppDir } from "@/services/cmds";
 import { join } from "@tauri-apps/api/path";
+import { exists } from "@tauri-apps/api/fs";
 
 export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
   const { t } = useTranslation();
@@ -26,12 +27,27 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
   async function initIconPath() {
     const appDir = await getAppDir();
     const icon_dir = await join(appDir, "icons");
-    const common_icon = await join(icon_dir, "common.png");
-    const sysproxy_icon = await join(icon_dir, "sysproxy.png");
-    const tun_icon = await join(icon_dir, "tun.png");
-    setCommonIcon(common_icon);
-    setSysproxyIcon(sysproxy_icon);
-    setTunIcon(tun_icon);
+    const common_icon_png = await join(icon_dir, "common.png");
+    const common_icon_ico = await join(icon_dir, "common.ico");
+    const sysproxy_icon_png = await join(icon_dir, "sysproxy.png");
+    const sysproxy_icon_ico = await join(icon_dir, "sysproxy.ico");
+    const tun_icon_png = await join(icon_dir, "tun.png");
+    const tun_icon_ico = await join(icon_dir, "tun.ico");
+    if (await exists(common_icon_ico)) {
+      setCommonIcon(common_icon_ico);
+    } else {
+      setCommonIcon(common_icon_png);
+    }
+    if (await exists(sysproxy_icon_ico)) {
+      setSysproxyIcon(sysproxy_icon_ico);
+    } else {
+      setSysproxyIcon(sysproxy_icon_png);
+    }
+    if (await exists(tun_icon_ico)) {
+      setTunIcon(tun_icon_ico);
+    } else {
+      setTunIcon(tun_icon_png);
+    }
   }
 
   useImperativeHandle(ref, () => ({
@@ -140,12 +156,13 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
                     filters: [
                       {
                         name: "Tray Icon Image",
-                        extensions: ["png"],
+                        extensions: ["png", "ico"],
                       },
                     ],
                   });
                   if (path?.length) {
-                    await copyIconFile(`${path}`, "common.png");
+                    await copyIconFile(`${path}`, "common");
+                    await initIconPath();
                     onChangeData({ common_tray_icon: true });
                     patchVerge({ common_tray_icon: true });
                   }
@@ -184,12 +201,13 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
                     filters: [
                       {
                         name: "Tray Icon Image",
-                        extensions: ["png"],
+                        extensions: ["png", "ico"],
                       },
                     ],
                   });
                   if (path?.length) {
-                    await copyIconFile(`${path}`, "sysproxy.png");
+                    await copyIconFile(`${path}`, "sysproxy");
+                    await initIconPath();
                     onChangeData({ sysproxy_tray_icon: true });
                     patchVerge({ sysproxy_tray_icon: true });
                   }
@@ -226,12 +244,13 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
                     filters: [
                       {
                         name: "Tray Icon Image",
-                        extensions: ["png"],
+                        extensions: ["png", "ico"],
                       },
                     ],
                   });
                   if (path?.length) {
-                    await copyIconFile(`${path}`, "tun.png");
+                    await copyIconFile(`${path}`, "tun");
+                    await initIconPath();
                     onChangeData({ tun_tray_icon: true });
                     patchVerge({ tun_tray_icon: true });
                   }

+ 1 - 1
src/services/cmds.ts

@@ -223,7 +223,7 @@ export async function exitApp() {
 
 export async function copyIconFile(
   path: string,
-  name: "common.png" | "sysproxy.png" | "tun.png"
+  name: "common" | "sysproxy" | "tun"
 ) {
   return invoke<void>("copy_icon_file", { path, name });
 }