diff --git a/ui/src/lib/components/AudioPlayer.svelte b/ui/src/lib/components/AudioPlayer.svelte index 3316bbf..c5f7ee8 100644 --- a/ui/src/lib/components/AudioPlayer.svelte +++ b/ui/src/lib/components/AudioPlayer.svelte @@ -50,6 +50,7 @@ import { audioStore } from '$lib/audio.svelte'; import { goto } from '$app/navigation'; + import { untrack } from 'svelte'; import { Button } from '$lib/components/ui/button'; import { cn } from '$lib/utils'; import type { Voice } from '$lib/types'; @@ -1010,11 +1011,14 @@ try { (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); } catch { /* ignore */ } } - // Clamp saved position to viewport on mount and on resize + // Clamp saved position to viewport on mount and on resize. + // Use untrack() when reading floatPos to avoid a reactive loop + // (reading + writing the same state inside $effect would re-trigger forever). $effect(() => { if (typeof window === 'undefined') return; const clamp = () => { - audioStore.floatPos = clampFloatPos(audioStore.floatPos.x, audioStore.floatPos.y); + const { x, y } = untrack(() => audioStore.floatPos); + audioStore.floatPos = clampFloatPos(x, y); }; clamp(); window.addEventListener('resize', clamp);