fix(electrobun): replace $effect scroll with MutationObserver in onMount

The $effect reading messages.length + requestAnimationFrame was a secondary
cause of effect_update_depth_exceeded. MutationObserver is non-reactive —
observes DOM changes directly without Svelte dependency tracking.
This commit is contained in:
Hibryda 2026-03-23 22:07:16 +01:00
parent 02560e341d
commit 9d45caa8df

View file

@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte';
import ChatInput from "./ChatInput.svelte"; import ChatInput from "./ChatInput.svelte";
import type { AgentMessage, AgentStatus } from "./agent-store.svelte.ts"; import type { AgentMessage, AgentStatus } from "./agent-store.svelte.ts";
import { t } from "./i18n.svelte.ts"; import { t } from "./i18n.svelte.ts";
@ -37,12 +38,14 @@
let agentPaneEl: HTMLDivElement; let agentPaneEl: HTMLDivElement;
let isDragging = $state(false); let isDragging = $state(false);
$effect(() => { // Auto-scroll on message change — done via onMount observer, NOT $effect
void messages.length; // ($effect + messages.length + DOM mutation = infinite loop in Svelte 5)
// Use requestAnimationFrame instead of tick() to avoid effect re-entry cycle onMount(() => {
requestAnimationFrame(() => { const observer = new MutationObserver(() => {
if (scrollEl) scrollEl.scrollTop = scrollEl.scrollHeight; if (scrollEl) scrollEl.scrollTop = scrollEl.scrollHeight;
}); });
if (scrollEl) observer.observe(scrollEl, { childList: true, subtree: true });
return () => observer.disconnect();
}); });
function handleSend() { function handleSend() {