perf(frontend): fix resource leaks and disable deep reactivity on media index
- useMediaWebSocket: shallowRef mediaIndex/tasks/loading/error/connected
to eliminate Proxy overhead on the entire library data structure.
- useMediaWebSocket: replace per-task setTimeout leak with single 3s
sweep interval for completed task cleanup.
- App.vue: remove {deep:true} watcher on mediaIndex; shallow ref change
is sufficient to trigger search worker sync.
- useGamepadNavigation: rAF only when gamepads are connected; idle
fallback to 500ms setTimeout to stop permanent 60fps CPU drain.
- useKeyboardNavigation: deduplicate synced scroll rAF requests to
prevent overlapping animation frames.
- MediaDetail/SeriesFullView/CollageHero: pause, clear src, and load()
video elements on unmount and before ref replacement to release
decoder/memory resources.
- MediaDetail/SeriesFullView: clear all volume fade intervals on
unmount to stop interval timer leaks.
This commit is contained in:
@@ -468,6 +468,13 @@ const videoRefs = ref<Map<string, HTMLVideoElement>>(new Map())
|
||||
let videoIndex = 0
|
||||
const safariAutoplay = isSafariBrowser()
|
||||
|
||||
function cleanupVideo(video: HTMLVideoElement | null | undefined) {
|
||||
if (!video) return
|
||||
video.pause()
|
||||
video.src = ""
|
||||
video.load()
|
||||
}
|
||||
|
||||
// Set video ref with staggered playback
|
||||
function setVideoRef(el: HTMLVideoElement | null, key: string) {
|
||||
if (el) {
|
||||
@@ -484,6 +491,10 @@ function setVideoRef(el: HTMLVideoElement | null, key: string) {
|
||||
safariAutoplay ? 0 : index * 200,
|
||||
)
|
||||
} else {
|
||||
const old = videoRefs.value.get(key)
|
||||
if (old) {
|
||||
cleanupVideo(old)
|
||||
}
|
||||
videoRefs.value.delete(key)
|
||||
}
|
||||
}
|
||||
@@ -649,6 +660,16 @@ onMounted(() => {
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("mediahive:gamepad-action", handleGamepadAction as EventListener)
|
||||
// Clear all volume fade intervals
|
||||
for (const interval of volumeFadeIntervals.values()) {
|
||||
clearInterval(interval)
|
||||
}
|
||||
volumeFadeIntervals.clear()
|
||||
// Pause and unload all video elements
|
||||
for (const video of videoRefs.value.values()) {
|
||||
cleanupVideo(video)
|
||||
}
|
||||
videoRefs.value.clear()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user