Skip to content

Commit fe1858f

Browse files
EstrellaXDclaude
andcommitted
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>
1 parent ead16ba commit fe1858f

4 files changed

Lines changed: 30 additions & 3 deletions

File tree

webui/src/components/ab-add-rss.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,24 @@ function goBack() {
147147
step.value = 'input';
148148
}
149149
150+
let copyTimer: ReturnType<typeof setTimeout> | undefined;
151+
150152
async function copyRssLink() {
151153
const rssLink = rule.value.rss_link?.[0] || rss.value.url || '';
152154
if (rssLink) {
153155
await navigator.clipboard.writeText(rssLink);
154156
copied.value = true;
155-
setTimeout(() => {
157+
clearTimeout(copyTimer);
158+
copyTimer = setTimeout(() => {
156159
copied.value = false;
157160
}, 2000);
158161
}
159162
}
160163
164+
onBeforeUnmount(() => {
165+
clearTimeout(copyTimer);
166+
});
167+
161168
async function autoDetectOffset() {
162169
if (!rule.value.id) return;
163170
offsetLoading.value = true;

webui/src/components/ab-edit-rule.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,24 @@ const infoTags = computed(() => {
8282
});
8383
8484
// Copy RSS link
85+
let copyTimer: ReturnType<typeof setTimeout> | undefined;
86+
8587
async function copyRssLink() {
8688
const rssLink = localRule.value.rss_link?.[0] || '';
8789
if (rssLink) {
8890
await navigator.clipboard.writeText(rssLink);
8991
copied.value = true;
90-
setTimeout(() => {
92+
clearTimeout(copyTimer);
93+
copyTimer = setTimeout(() => {
9194
copied.value = false;
9295
}, 2000);
9396
}
9497
}
9598
99+
onBeforeUnmount(() => {
100+
clearTimeout(copyTimer);
101+
});
102+
96103
// Auto detect offset using the new detectOffset API
97104
async function autoDetectOffset() {
98105
if (!localRule.value.official_title || !localRule.value.season) return;

webui/src/components/search/ab-search-confirm.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,24 @@ const infoTags = computed(() => {
103103
});
104104
105105
// Copy RSS link
106+
let copyTimer: ReturnType<typeof setTimeout> | undefined;
107+
106108
async function copyRssLink() {
107109
const rssLink = localBangumi.value.rss_link?.[0] || '';
108110
if (rssLink) {
109111
await navigator.clipboard.writeText(rssLink);
110112
copied.value = true;
111-
setTimeout(() => {
113+
clearTimeout(copyTimer);
114+
copyTimer = setTimeout(() => {
112115
copied.value = false;
113116
}, 2000);
114117
}
115118
}
116119
120+
onBeforeUnmount(() => {
121+
clearTimeout(copyTimer);
122+
});
123+
117124
// Auto detect offset
118125
async function autoDetectOffset() {
119126
if (!localBangumi.value.id) return;

webui/src/components/search/ab-search-modal.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const {
2727
getProviders,
2828
onSearch,
2929
clearSearch,
30+
closeSearch,
3031
selectResult,
3132
clearSelectedResult,
3233
} = useSearchStore();
@@ -61,6 +62,11 @@ const expandedCategories = ref<Set<'group' | 'resolution' | 'subtitle' | 'season
6162
// Track which bangumi groups have expanded variants
6263
const expandedVariants = ref<Set<string>>(new Set());
6364
65+
// Close EventSource on unmount (prevents leak if navigating away mid-search)
66+
onBeforeUnmount(() => {
67+
closeSearch();
68+
});
69+
6470
// Close on Escape
6571
onKeyStroke('Escape', () => {
6672
if (selectedResult.value) {

0 commit comments

Comments
 (0)