diff --git a/src/components/test/test-item.tsx b/src/components/test/test-item.tsx index faee6e37..a63e4c17 100644 --- a/src/components/test/test-item.tsx +++ b/src/components/test/test-item.tsx @@ -20,7 +20,7 @@ import delayManager from "@/services/delay"; import { cmdTestDelay, downloadIconCache } from "@/services/cmds"; import { listen, UnlistenFn } from "@tauri-apps/api/event"; import { convertFileSrc } from "@tauri-apps/api/core"; - +import { useListen } from "@/hooks/use-listen"; interface Props { id: string; itemData: IVergeTestItem; @@ -47,6 +47,7 @@ export const TestItem = (props: Props) => { const [delay, setDelay] = useState(-1); const { uid, name, icon, url } = itemData; const [iconCachePath, setIconCachePath] = useState(""); + const { addListener } = useListen(); useEffect(() => { initIconCachePath(); @@ -91,7 +92,7 @@ export const TestItem = (props: Props) => { const listenTsetEvent = async () => { eventListener(); - eventListener = await listen("verge://test-all", () => { + eventListener = await addListener("verge://test-all", () => { onDelay(); }); }; diff --git a/src/hooks/use-listen.ts b/src/hooks/use-listen.ts new file mode 100644 index 00000000..87abac39 --- /dev/null +++ b/src/hooks/use-listen.ts @@ -0,0 +1,34 @@ +import { listen, UnlistenFn, EventCallback } from "@tauri-apps/api/event"; +import { event } from "@tauri-apps/api"; + +export const useListen = () => { + let unlistenFns: UnlistenFn[] = []; + + const addListener = async function ( + eventName: string, + handler: EventCallback + ) { + const unlisten = await listen(eventName, handler); + unlistenFns.push(unlisten); + return unlisten; + }; + const removeAllListeners = async function () { + for (const unlisten of unlistenFns) { + Promise.resolve(unlisten()).catch(console.error); + } + unlistenFns = []; + }; + + const setupCloseListener = async function () { + await event.once("tauri://close-requested", async () => { + console.log("Window close requested."); + await removeAllListeners(); + }); + }; + + return { + addListener, + removeAllListeners, + setupCloseListener, + }; +}; diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx index 9a7b6629..c62855ae 100644 --- a/src/pages/_layout.tsx +++ b/src/pages/_layout.tsx @@ -27,6 +27,7 @@ import "dayjs/locale/zh-cn"; import { getPortableFlag } from "@/services/cmds"; import React from "react"; import { TransitionGroup, CSSTransition } from "react-transition-group"; +import { useListen } from "@/hooks/use-listen"; const appWindow = getCurrentWebviewWindow(); export let portableFlag = false; @@ -46,10 +47,13 @@ const Layout = () => { const navigate = useNavigate(); const location = useLocation(); const routersEles = useRoutes(routers); + const { addListener, setupCloseListener } = useListen(); if (!routersEles) return null; + setupCloseListener(); + useEffect(() => { - listen("verge://refresh-clash-config", async () => { + addListener("verge://refresh-clash-config", async () => { // the clash info may be updated await getAxios(true); mutate("getProxies"); @@ -59,10 +63,10 @@ const Layout = () => { }); // update the verge config - listen("verge://refresh-verge-config", () => mutate("getVergeConfig")); + addListener("verge://refresh-verge-config", () => mutate("getVergeConfig")); // 设置提示监听 - listen("verge://notice-message", ({ payload }) => { + addListener("verge://notice-message", ({ payload }) => { const [status, msg] = payload as [string, string]; switch (status) { case "import_sub_url::ok":