feat: Try to cache remote images

#603
This commit is contained in:
MystiPanda 2024-03-15 16:42:17 +08:00
parent 88dd886687
commit daf726ebbf
6 changed files with 66 additions and 4 deletions

View File

@ -275,6 +275,23 @@ pub fn get_app_dir() -> CmdResult<String> {
Ok(app_home_dir)
}
#[tauri::command]
pub async fn download_icon_cache(url: String, name: String) -> CmdResult<String> {
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<String> {
let file_path = std::path::Path::new(&path);

View File

@ -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,

View File

@ -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") && (
<img
src={group.icon}
src={iconCachePath === "" ? group.icon : iconCachePath}
height="32px"
style={{ marginRight: "12px", borderRadius: "6px" }}
/>

View File

@ -19,7 +19,6 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
const [sysproxyIcon, setSysproxyIcon] = useState("");
const [tunIcon, setTunIcon] = useState("");
// const { menu_icon } = verge ?? {};
useEffect(() => {
initIconPath();
}, []);

View File

@ -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() !== "" ? (
<Box sx={{ display: "flex", justifyContent: "center" }}>
{icon.trim().startsWith("http") && (
<img src={icon} height="40px" />
<img
src={iconCachePath === "" ? icon : iconCachePath}
height="40px"
/>
)}
{icon.trim().startsWith("data") && (
<img src={icon} height="40px" />

View File

@ -227,3 +227,7 @@ export async function copyIconFile(
) {
return invoke<void>("copy_icon_file", { path, name });
}
export async function downloadIconCache(url: string, name: string) {
return invoke<string>("download_icon_cache", { url, name });
}