fix(webui): close EventSource and clear timers on component unmount

Prevent memory leaks by ensuring the search EventSource connection is
closed when the modal unmounts and setTimeout handles are cleared in
copy-to-clipboard flows across modal components.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Estrella Pan
2026-02-24 19:44:49 +01:00
parent ead16ba4cf
commit fe1858f0e6
4 changed files with 30 additions and 3 deletions

View File

@@ -147,17 +147,24 @@ function goBack() {
step.value = 'input';
}
let copyTimer: ReturnType<typeof setTimeout> | undefined;
async function copyRssLink() {
const rssLink = rule.value.rss_link?.[0] || rss.value.url || '';
if (rssLink) {
await navigator.clipboard.writeText(rssLink);
copied.value = true;
setTimeout(() => {
clearTimeout(copyTimer);
copyTimer = setTimeout(() => {
copied.value = false;
}, 2000);
}
}
onBeforeUnmount(() => {
clearTimeout(copyTimer);
});
async function autoDetectOffset() {
if (!rule.value.id) return;
offsetLoading.value = true;

View File

@@ -82,17 +82,24 @@ const infoTags = computed(() => {
});
// Copy RSS link
let copyTimer: ReturnType<typeof setTimeout> | undefined;
async function copyRssLink() {
const rssLink = localRule.value.rss_link?.[0] || '';
if (rssLink) {
await navigator.clipboard.writeText(rssLink);
copied.value = true;
setTimeout(() => {
clearTimeout(copyTimer);
copyTimer = setTimeout(() => {
copied.value = false;
}, 2000);
}
}
onBeforeUnmount(() => {
clearTimeout(copyTimer);
});
// Auto detect offset using the new detectOffset API
async function autoDetectOffset() {
if (!localRule.value.official_title || !localRule.value.season) return;

View File

@@ -103,17 +103,24 @@ const infoTags = computed(() => {
});
// Copy RSS link
let copyTimer: ReturnType<typeof setTimeout> | undefined;
async function copyRssLink() {
const rssLink = localBangumi.value.rss_link?.[0] || '';
if (rssLink) {
await navigator.clipboard.writeText(rssLink);
copied.value = true;
setTimeout(() => {
clearTimeout(copyTimer);
copyTimer = setTimeout(() => {
copied.value = false;
}, 2000);
}
}
onBeforeUnmount(() => {
clearTimeout(copyTimer);
});
// Auto detect offset
async function autoDetectOffset() {
if (!localBangumi.value.id) return;

View File

@@ -27,6 +27,7 @@ const {
getProviders,
onSearch,
clearSearch,
closeSearch,
selectResult,
clearSelectedResult,
} = useSearchStore();
@@ -61,6 +62,11 @@ const expandedCategories = ref<Set<'group' | 'resolution' | 'subtitle' | 'season
// Track which bangumi groups have expanded variants
const expandedVariants = ref<Set<string>>(new Set());
// Close EventSource on unmount (prevents leak if navigating away mid-search)
onBeforeUnmount(() => {
closeSearch();
});
// Close on Escape
onKeyStroke('Escape', () => {
if (selectedResult.value) {