From aae68853ef42f5f185d5a59c642ad025885a3263 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 27 Dec 2025 18:18:06 -0800 Subject: [PATCH] kill butterchurn visualizer if player is idle --- .../components/butternchurn/visualizer.tsx | 59 ++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/renderer/features/visualizer/components/butternchurn/visualizer.tsx b/src/renderer/features/visualizer/components/butternchurn/visualizer.tsx index 7a0fa0f9f..dcc201b9d 100644 --- a/src/renderer/features/visualizer/components/butternchurn/visualizer.tsx +++ b/src/renderer/features/visualizer/components/butternchurn/visualizer.tsx @@ -29,6 +29,7 @@ const VisualizerInner = () => { const resizeObserverRef = useRef(undefined); const cycleTimerRef = useRef(undefined); const cycleStartTimeRef = useRef(undefined); + const pauseTimerRef = useRef(undefined); const butterchurnSettings = useSettingsStore((store) => store.visualizer.butterchurn); const opacity = useSettingsStore((store) => store.visualizer.butterchurn.opacity); const { setSettings } = useSettingsStoreActions(); @@ -115,6 +116,48 @@ const VisualizerInner = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [webAudio, canvasRef, containerRef, visualizer, isPlaying]); + // Kill visualizer after 5 seconds of pause + useEffect(() => { + if (isPlaying) { + // Clear pause timer if player resumes + if (pauseTimerRef.current) { + clearTimeout(pauseTimerRef.current); + pauseTimerRef.current = undefined; + } + return; + } + + // Player is paused + if (!visualizer) return; + + // Start 5-second timer + pauseTimerRef.current = setTimeout(() => { + if (animationFrameRef.current) { + cancelAnimationFrame(animationFrameRef.current); + animationFrameRef.current = undefined; + } + if (cycleTimerRef.current) { + clearInterval(cycleTimerRef.current); + cycleTimerRef.current = undefined; + } + if (resizeObserverRef.current) { + resizeObserverRef.current.disconnect(); + resizeObserverRef.current = undefined; + } + + // Destroy visualizer + setVisualizer(undefined); + pauseTimerRef.current = undefined; + }, 5000); + + return () => { + if (pauseTimerRef.current) { + clearTimeout(pauseTimerRef.current); + pauseTimerRef.current = undefined; + } + }; + }, [isPlaying, visualizer]); + // Handle resize useEffect(() => { const container = containerRef.current; @@ -293,10 +336,22 @@ const VisualizerInner = () => { }; }, [visualizer, butterchurnSettings.maxFPS]); + // Render container when playing (for initialization) or when visualizer exists + // Canvas must always be rendered when container is rendered so refs are available + const shouldRenderContainer = isPlaying || visualizer; + + if (!shouldRenderContainer) { + return null; + } + return ( -
+
- {butterchurnSettings.currentPreset && ( + {visualizer && butterchurnSettings.currentPreset && ( {butterchurnSettings.currentPreset}