diff --git a/src/components/setting/mods/update-viewer.tsx b/src/components/setting/mods/update-viewer.tsx index ff9ec117..f853e5cd 100644 --- a/src/components/setting/mods/update-viewer.tsx +++ b/src/components/setting/mods/update-viewer.tsx @@ -1,5 +1,5 @@ import useSWR from "swr"; -import { forwardRef, useImperativeHandle, useState, useMemo } from "react"; +import { forwardRef, useImperativeHandle, useState, useMemo, useEffect } from "react"; import { useLockFn } from "ahooks"; import { Box, LinearProgress, Button } from "@mui/material"; import { useTranslation } from "react-i18next"; @@ -14,12 +14,11 @@ import ReactMarkdown from "react-markdown"; import { useListen } from "@/hooks/use-listen"; import { showNotice } from "@/services/noticeService"; -let eventListener: UnlistenFn | null = null; - export const UpdateViewer = forwardRef((props, ref) => { const { t } = useTranslation(); const [open, setOpen] = useState(false); + const [currentProgressListener, setCurrentProgressListener] = useState(null); const updateState = useUpdateState(); const setUpdateState = useSetUpdateState(); @@ -66,10 +65,12 @@ export const UpdateViewer = forwardRef((props, ref) => { } if (updateState) return; setUpdateState(true); - if (eventListener !== null) { - eventListener(); + + if (currentProgressListener) { + currentProgressListener(); } - eventListener = await addListener( + + const progressListener = await addListener( "tauri://update-download-progress", (e: Event) => { setTotal(e.payload.contentLength); @@ -79,6 +80,8 @@ export const UpdateViewer = forwardRef((props, ref) => { }); }, ); + setCurrentProgressListener(() => progressListener); + try { await updateInfo.downloadAndInstall(); await relaunch(); @@ -86,9 +89,22 @@ export const UpdateViewer = forwardRef((props, ref) => { showNotice('error', err?.message || err.toString()); } finally { setUpdateState(false); + if (progressListener) { + progressListener(); + } + setCurrentProgressListener(null); } }); + useEffect(() => { + return () => { + if (currentProgressListener) { + console.log("UpdateViewer unmounting, cleaning up progress listener."); + currentProgressListener(); + } + }; + }, [currentProgressListener]); + return ( void; } -let eventListener: UnlistenFn = () => {}; - export const TestItem = (props: Props) => { const { itemData, onEdit, onDelete: onDeleteItem } = props; const { @@ -42,6 +40,12 @@ export const TestItem = (props: Props) => { const [iconCachePath, setIconCachePath] = useState(""); const { addListener } = useListen(); + const onDelay = async () => { + setDelay(-2); + const result = await cmdTestDelay(url); + setDelay(result); + }; + useEffect(() => { initIconCachePath(); }, [icon]); @@ -58,12 +62,6 @@ export const TestItem = (props: Props) => { return url.substring(url.lastIndexOf("/") + 1); } - const onDelay = async () => { - setDelay(-2); - const result = await cmdTestDelay(url); - setDelay(result); - }; - const onEditTest = () => { setAnchorEl(null); onEdit(); @@ -83,16 +81,27 @@ export const TestItem = (props: Props) => { { label: "Delete", handler: onDelete }, ]; - const listenTsetEvent = async () => { - eventListener(); - eventListener = await addListener("verge://test-all", () => { - onDelay(); - }); - }; - useEffect(() => { - listenTsetEvent(); - }, [url]); + let unlistenFn: UnlistenFn | null = null; + + const setupListener = async () => { + if (unlistenFn) { + unlistenFn(); + } + unlistenFn = await addListener("verge://test-all", () => { + onDelay(); + }); + }; + + setupListener(); + + return () => { + if (unlistenFn) { + console.log(`TestItem for ${props.id} unmounting or url changed, cleaning up test-all listener.`); + unlistenFn(); + } + }; + }, [url, addListener, onDelay, props.id]); return (