mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-13 05:20:28 +08:00
refactor(icon): extract icon cache logic into reusable hook
This commit is contained in:
parent
f3b9eedcf7
commit
522eccdd0e
@ -9,10 +9,8 @@ import {
|
||||
alpha,
|
||||
styled,
|
||||
} from "@mui/material";
|
||||
import { convertFileSrc } from "@tauri-apps/api/core";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { downloadIconCache } from "@/services/cmds";
|
||||
import { useIconCache } from "@/hooks/use-icon-cache";
|
||||
interface Props {
|
||||
type: "prepend" | "original" | "delete" | "append";
|
||||
group: IProxyGroupConfig;
|
||||
@ -38,40 +36,10 @@ export const GroupItem = (props: Props) => {
|
||||
const dragListeners = sortable ? sortableListeners : undefined;
|
||||
const dragNodeRef = sortable ? sortableSetNodeRef : undefined;
|
||||
|
||||
const [iconCachePath, setIconCachePath] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const initIconCachePath = async () => {
|
||||
const icon = group.icon?.trim() ?? "";
|
||||
if (icon.startsWith("http")) {
|
||||
try {
|
||||
const fileName =
|
||||
group.name.replaceAll(" ", "") + "-" + getFileName(icon);
|
||||
const iconPath = await downloadIconCache(icon, fileName);
|
||||
if (!cancelled) {
|
||||
setIconCachePath(convertFileSrc(iconPath));
|
||||
}
|
||||
} catch {
|
||||
if (!cancelled) {
|
||||
setIconCachePath("");
|
||||
}
|
||||
}
|
||||
} else if (!cancelled) {
|
||||
setIconCachePath("");
|
||||
}
|
||||
};
|
||||
|
||||
void initIconCachePath();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [group.icon, group.name]);
|
||||
|
||||
function getFileName(url: string) {
|
||||
return url.substring(url.lastIndexOf("/") + 1);
|
||||
}
|
||||
const iconCachePath = useIconCache({
|
||||
icon: group.icon,
|
||||
cacheKey: group.name.replaceAll(" ", ""),
|
||||
});
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
|
||||
@ -13,12 +13,11 @@ import {
|
||||
Chip,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import { convertFileSrc } from "@tauri-apps/api/core";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useIconCache } from "@/hooks/use-icon-cache";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { downloadIconCache } from "@/services/cmds";
|
||||
import { useThemeMode } from "@/services/states";
|
||||
|
||||
import { ProxyHead } from "./proxy-head";
|
||||
@ -57,26 +56,11 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
const mode = useThemeMode();
|
||||
const isDark = mode === "light" ? false : true;
|
||||
const itembackgroundcolor = isDark ? "#282A36" : "#ffffff";
|
||||
const [iconCachePath, setIconCachePath] = useState("");
|
||||
|
||||
const initIconCachePath = useCallback(async () => {
|
||||
if (group.icon && group.icon.trim().startsWith("http")) {
|
||||
const fileName =
|
||||
group.name.replaceAll(" ", "") + "-" + getFileName(group.icon);
|
||||
const iconPath = await downloadIconCache(group.icon, fileName);
|
||||
setIconCachePath(convertFileSrc(iconPath));
|
||||
} else {
|
||||
setIconCachePath("");
|
||||
}
|
||||
}, [group.icon, group.name]);
|
||||
|
||||
useEffect(() => {
|
||||
initIconCachePath();
|
||||
}, [initIconCachePath]);
|
||||
|
||||
function getFileName(url: string) {
|
||||
return url.substring(url.lastIndexOf("/") + 1);
|
||||
}
|
||||
const iconCachePath = useIconCache({
|
||||
icon: group.icon,
|
||||
cacheKey: group.name.replaceAll(" ", ""),
|
||||
enabled: enable_group_icon,
|
||||
});
|
||||
|
||||
const proxyColItemsMemo = useMemo(() => {
|
||||
if (type !== 4 || !proxyCol) {
|
||||
|
||||
@ -2,15 +2,15 @@ import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { LanguageRounded } from "@mui/icons-material";
|
||||
import { Box, Divider, MenuItem, Menu, styled, alpha } from "@mui/material";
|
||||
import { convertFileSrc } from "@tauri-apps/api/core";
|
||||
import { UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { BaseLoading } from "@/components/base";
|
||||
import { useIconCache } from "@/hooks/use-icon-cache";
|
||||
import { useListen } from "@/hooks/use-listen";
|
||||
import { cmdTestDelay, downloadIconCache } from "@/services/cmds";
|
||||
import { cmdTestDelay } from "@/services/cmds";
|
||||
import delayManager from "@/services/delay";
|
||||
import { showNotice } from "@/services/notice-service";
|
||||
import { debugLog } from "@/utils/debug";
|
||||
@ -46,7 +46,7 @@ export const TestItem = ({
|
||||
const [position, setPosition] = useState({ left: 0, top: 0 });
|
||||
const [delay, setDelay] = useState(-1);
|
||||
const { uid, name, icon, url } = itemData;
|
||||
const [iconCachePath, setIconCachePath] = useState("");
|
||||
const iconCachePath = useIconCache({ icon, cacheKey: uid });
|
||||
const { addListener } = useListen();
|
||||
|
||||
const onDelay = useCallback(async () => {
|
||||
@ -55,24 +55,6 @@ export const TestItem = ({
|
||||
setDelay(result);
|
||||
}, [url]);
|
||||
|
||||
const initIconCachePath = useCallback(async () => {
|
||||
if (icon && icon.trim().startsWith("http")) {
|
||||
const fileName = uid + "-" + getFileName(icon);
|
||||
const iconPath = await downloadIconCache(icon, fileName);
|
||||
setIconCachePath(convertFileSrc(iconPath));
|
||||
} else {
|
||||
setIconCachePath("");
|
||||
}
|
||||
}, [icon, uid]);
|
||||
|
||||
useEffect(() => {
|
||||
void initIconCachePath();
|
||||
}, [initIconCachePath]);
|
||||
|
||||
function getFileName(url: string) {
|
||||
return url.substring(url.lastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
const onEditTest = () => {
|
||||
setAnchorEl(null);
|
||||
onEdit();
|
||||
|
||||
54
src/hooks/use-icon-cache.ts
Normal file
54
src/hooks/use-icon-cache.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { convertFileSrc } from "@tauri-apps/api/core";
|
||||
import { useMemo } from "react";
|
||||
import useSWR from "swr";
|
||||
|
||||
import { downloadIconCache } from "@/services/cmds";
|
||||
import { SWR_DEFAULTS } from "@/services/config";
|
||||
|
||||
export interface UseIconCacheOptions {
|
||||
icon?: string | null;
|
||||
cacheKey?: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
const getFileNameFromUrl = (url: string) => {
|
||||
const lastSlashIndex = url.lastIndexOf("/");
|
||||
return lastSlashIndex >= 0 ? url.slice(lastSlashIndex + 1) : url;
|
||||
};
|
||||
|
||||
export const useIconCache = ({
|
||||
icon,
|
||||
cacheKey,
|
||||
enabled = true,
|
||||
}: UseIconCacheOptions) => {
|
||||
const iconValue = icon?.trim() ?? "";
|
||||
const cacheKeyValue = cacheKey?.trim() ?? "";
|
||||
|
||||
const swrKey = useMemo(() => {
|
||||
if (!enabled || !iconValue.startsWith("http") || cacheKeyValue === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ["icon-cache", iconValue, cacheKeyValue] as const;
|
||||
}, [enabled, iconValue, cacheKeyValue]);
|
||||
|
||||
const { data } = useSWR(
|
||||
swrKey,
|
||||
async () => {
|
||||
try {
|
||||
const fileName = `${cacheKeyValue}-${getFileNameFromUrl(iconValue)}`;
|
||||
const iconPath = await downloadIconCache(iconValue, fileName);
|
||||
return convertFileSrc(iconPath);
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
SWR_DEFAULTS,
|
||||
);
|
||||
|
||||
if (!swrKey) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return data ?? "";
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user