perf: optimize event listeners in update viewer and test item components with proper cleanup on unmount
(cherry picked from commit 2e4e939e0b05040c8f38248f3663978a0212cd50)
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { forwardRef, useImperativeHandle, useState, useMemo } from "react";
|
import { forwardRef, useImperativeHandle, useState, useMemo, useEffect } from "react";
|
||||||
import { useLockFn } from "ahooks";
|
import { useLockFn } from "ahooks";
|
||||||
import { Box, LinearProgress, Button } from "@mui/material";
|
import { Box, LinearProgress, Button } from "@mui/material";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -14,12 +14,11 @@ import ReactMarkdown from "react-markdown";
|
|||||||
import { useListen } from "@/hooks/use-listen";
|
import { useListen } from "@/hooks/use-listen";
|
||||||
import { showNotice } from "@/services/noticeService";
|
import { showNotice } from "@/services/noticeService";
|
||||||
|
|
||||||
let eventListener: UnlistenFn | null = null;
|
|
||||||
|
|
||||||
export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const [currentProgressListener, setCurrentProgressListener] = useState<UnlistenFn | null>(null);
|
||||||
|
|
||||||
const updateState = useUpdateState();
|
const updateState = useUpdateState();
|
||||||
const setUpdateState = useSetUpdateState();
|
const setUpdateState = useSetUpdateState();
|
||||||
@@ -66,10 +65,12 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
}
|
}
|
||||||
if (updateState) return;
|
if (updateState) return;
|
||||||
setUpdateState(true);
|
setUpdateState(true);
|
||||||
if (eventListener !== null) {
|
|
||||||
eventListener();
|
if (currentProgressListener) {
|
||||||
|
currentProgressListener();
|
||||||
}
|
}
|
||||||
eventListener = await addListener(
|
|
||||||
|
const progressListener = await addListener(
|
||||||
"tauri://update-download-progress",
|
"tauri://update-download-progress",
|
||||||
(e: Event<any>) => {
|
(e: Event<any>) => {
|
||||||
setTotal(e.payload.contentLength);
|
setTotal(e.payload.contentLength);
|
||||||
@@ -79,6 +80,8 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
setCurrentProgressListener(() => progressListener);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateInfo.downloadAndInstall();
|
await updateInfo.downloadAndInstall();
|
||||||
await relaunch();
|
await relaunch();
|
||||||
@@ -86,9 +89,22 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
showNotice('error', err?.message || err.toString());
|
showNotice('error', err?.message || err.toString());
|
||||||
} finally {
|
} finally {
|
||||||
setUpdateState(false);
|
setUpdateState(false);
|
||||||
|
if (progressListener) {
|
||||||
|
progressListener();
|
||||||
|
}
|
||||||
|
setCurrentProgressListener(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (currentProgressListener) {
|
||||||
|
console.log("UpdateViewer unmounting, cleaning up progress listener.");
|
||||||
|
currentProgressListener();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [currentProgressListener]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseDialog
|
<BaseDialog
|
||||||
open={open}
|
open={open}
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ interface Props {
|
|||||||
onDelete: (uid: string) => void;
|
onDelete: (uid: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let eventListener: UnlistenFn = () => {};
|
|
||||||
|
|
||||||
export const TestItem = (props: Props) => {
|
export const TestItem = (props: Props) => {
|
||||||
const { itemData, onEdit, onDelete: onDeleteItem } = props;
|
const { itemData, onEdit, onDelete: onDeleteItem } = props;
|
||||||
const {
|
const {
|
||||||
@@ -42,6 +40,12 @@ export const TestItem = (props: Props) => {
|
|||||||
const [iconCachePath, setIconCachePath] = useState("");
|
const [iconCachePath, setIconCachePath] = useState("");
|
||||||
const { addListener } = useListen();
|
const { addListener } = useListen();
|
||||||
|
|
||||||
|
const onDelay = async () => {
|
||||||
|
setDelay(-2);
|
||||||
|
const result = await cmdTestDelay(url);
|
||||||
|
setDelay(result);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initIconCachePath();
|
initIconCachePath();
|
||||||
}, [icon]);
|
}, [icon]);
|
||||||
@@ -58,12 +62,6 @@ export const TestItem = (props: Props) => {
|
|||||||
return url.substring(url.lastIndexOf("/") + 1);
|
return url.substring(url.lastIndexOf("/") + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDelay = async () => {
|
|
||||||
setDelay(-2);
|
|
||||||
const result = await cmdTestDelay(url);
|
|
||||||
setDelay(result);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onEditTest = () => {
|
const onEditTest = () => {
|
||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
onEdit();
|
onEdit();
|
||||||
@@ -83,16 +81,27 @@ export const TestItem = (props: Props) => {
|
|||||||
{ label: "Delete", handler: onDelete },
|
{ label: "Delete", handler: onDelete },
|
||||||
];
|
];
|
||||||
|
|
||||||
const listenTsetEvent = async () => {
|
|
||||||
eventListener();
|
|
||||||
eventListener = await addListener("verge://test-all", () => {
|
|
||||||
onDelay();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
listenTsetEvent();
|
let unlistenFn: UnlistenFn | null = null;
|
||||||
}, [url]);
|
|
||||||
|
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 (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
Reference in New Issue
Block a user