From daf726ebbf8db3e6dfd574ba49636db4ce1cb9b8 Mon Sep 17 00:00:00 2001 From: MystiPanda Date: Fri, 15 Mar 2024 16:42:17 +0800 Subject: [PATCH] feat: Try to cache remote images #603 --- src-tauri/src/cmds.rs | 17 +++++++++++++ src-tauri/src/main.rs | 1 + src/components/proxy/proxy-render.tsx | 22 +++++++++++++++- src/components/setting/mods/layout-viewer.tsx | 1 - src/components/test/test-item.tsx | 25 +++++++++++++++++-- src/services/cmds.ts | 4 +++ 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs index 75586a2b..6ae22872 100644 --- a/src-tauri/src/cmds.rs +++ b/src-tauri/src/cmds.rs @@ -275,6 +275,23 @@ pub fn get_app_dir() -> CmdResult { Ok(app_home_dir) } +#[tauri::command] +pub async fn download_icon_cache(url: String, name: String) -> CmdResult { + let icon_cache_dir = wrap_err!(dirs::app_home_dir())?.join("icons").join("cache"); + let icon_path = icon_cache_dir.join(name); + if !icon_cache_dir.exists() { + let _ = std::fs::create_dir_all(&icon_cache_dir); + } + if !icon_path.exists() { + let response = wrap_err!(reqwest::get(url).await)?; + + let mut file = wrap_err!(std::fs::File::create(&icon_path))?; + + let content = wrap_err!(response.bytes().await)?; + wrap_err!(std::io::copy(&mut content.as_ref(), &mut file))?; + } + Ok(icon_path.to_string_lossy().to_string()) +} #[tauri::command] pub fn copy_icon_file(path: String, name: String) -> CmdResult { let file_path = std::path::Path::new(&path); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1201eabd..255bac07 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -57,6 +57,7 @@ fn main() -> std::io::Result<()> { cmds::test_delay, cmds::get_app_dir, cmds::copy_icon_file, + cmds::download_icon_cache, cmds::open_devtools, cmds::exit_app, // cmds::update_hotkeys, diff --git a/src/components/proxy/proxy-render.tsx b/src/components/proxy/proxy-render.tsx index 6fb1c6e8..1c2fcb27 100644 --- a/src/components/proxy/proxy-render.tsx +++ b/src/components/proxy/proxy-render.tsx @@ -19,6 +19,9 @@ import type { IRenderItem } from "./use-render-list"; import { useVerge } from "@/hooks/use-verge"; import { useRecoilState } from "recoil"; import { atomThemeMode } from "@/services/states"; +import { useEffect, useState } from "react"; +import { convertFileSrc } from "@tauri-apps/api/tauri"; +import { downloadIconCache } from "@/services/cmds"; interface RenderProps { item: IRenderItem; @@ -38,6 +41,23 @@ export const ProxyRender = (props: RenderProps) => { const [mode] = useRecoilState(atomThemeMode); const isDark = mode === "light" ? false : true; const itembackgroundcolor = isDark ? "#282A36" : "#ffffff"; + const [iconCachePath, setIconCachePath] = useState(""); + + useEffect(() => { + initIconCachePath(); + }, [group]); + + async function initIconCachePath() { + if (group.icon && group.icon.trim().startsWith("http")) { + const fileName = getFileName(group.icon); + const iconPath = await downloadIconCache(group.icon, fileName); + setIconCachePath(convertFileSrc(iconPath)); + } + } + + function getFileName(url: string) { + return url.substring(url.lastIndexOf("/") + 1); + } if (type === 0 && !group.hidden) { return ( @@ -55,7 +75,7 @@ export const ProxyRender = (props: RenderProps) => { group.icon && group.icon.trim().startsWith("http") && ( diff --git a/src/components/setting/mods/layout-viewer.tsx b/src/components/setting/mods/layout-viewer.tsx index 4c0fdd78..154d2baf 100644 --- a/src/components/setting/mods/layout-viewer.tsx +++ b/src/components/setting/mods/layout-viewer.tsx @@ -19,7 +19,6 @@ export const LayoutViewer = forwardRef((props, ref) => { const [sysproxyIcon, setSysproxyIcon] = useState(""); const [tunIcon, setTunIcon] = useState(""); - // const { menu_icon } = verge ?? {}; useEffect(() => { initIconPath(); }, []); diff --git a/src/components/test/test-item.tsx b/src/components/test/test-item.tsx index 21be7740..883d4e7e 100644 --- a/src/components/test/test-item.tsx +++ b/src/components/test/test-item.tsx @@ -17,8 +17,9 @@ import { LanguageTwoTone } from "@mui/icons-material"; import { Notice } from "@/components/base"; import { TestBox } from "./test-box"; import delayManager from "@/services/delay"; -import { cmdTestDelay } from "@/services/cmds"; +import { cmdTestDelay, downloadIconCache } from "@/services/cmds"; import { listen, Event, UnlistenFn } from "@tauri-apps/api/event"; +import { convertFileSrc } from "@tauri-apps/api/tauri"; interface Props { id: string; @@ -39,6 +40,23 @@ export const TestItem = (props: Props) => { const [position, setPosition] = useState({ left: 0, top: 0 }); const [delay, setDelay] = useState(-1); const { uid, name, icon, url } = itemData; + const [iconCachePath, setIconCachePath] = useState(""); + + useEffect(() => { + initIconCachePath(); + }, [icon]); + + async function initIconCachePath() { + if (icon && icon.trim().startsWith("http")) { + const fileName = getFileName(icon); + const iconPath = await downloadIconCache(icon, fileName); + setIconCachePath(convertFileSrc(iconPath)); + } + } + + function getFileName(url: string) { + return url.substring(url.lastIndexOf("/") + 1); + } const onDelay = async () => { setDelay(-2); @@ -104,7 +122,10 @@ export const TestItem = (props: Props) => { {icon && icon.trim() !== "" ? ( {icon.trim().startsWith("http") && ( - + )} {icon.trim().startsWith("data") && ( diff --git a/src/services/cmds.ts b/src/services/cmds.ts index 9cc31968..ceae0915 100644 --- a/src/services/cmds.ts +++ b/src/services/cmds.ts @@ -227,3 +227,7 @@ export async function copyIconFile( ) { return invoke("copy_icon_file", { path, name }); } + +export async function downloadIconCache(url: string, name: string) { + return invoke("download_icon_cache", { url, name }); +}