diff --git a/frontend/src/lib/components/ChatList.svelte b/frontend/src/lib/components/ChatList.svelte index f40268b..e3f1677 100644 --- a/frontend/src/lib/components/ChatList.svelte +++ b/frontend/src/lib/components/ChatList.svelte @@ -83,6 +83,11 @@ if (index === -1 || viewport === null) { return; } + const row = viewport.querySelector(".Chat.selected"); + if (row) { + row.scrollIntoView({ block: "nearest" }); + return; + } const top = index * rowHeight; if (top < viewport.scrollTop) { viewport.scrollTop = top; diff --git a/frontend/src/lib/params.ts b/frontend/src/lib/params.ts index 213d1c4..b55fb4d 100644 --- a/frontend/src/lib/params.ts +++ b/frontend/src/lib/params.ts @@ -1,17 +1,32 @@ import { goto } from "$app/navigation"; import { page } from "$app/state"; -export async function replaceParam( - key: string, - value: string | null -): Promise { +const ATTEMPTS = 2; + +function withParam(key: string, value: string | null): URL { const url = new URL(page.url.href); if (value === null) { url.searchParams.delete(key); } else { url.searchParams.set(key, value); } - if (url.href !== page.url.href) { - await goto(url, { replace: true, reset: false, state: { ...page.state } }); + return url; +} + +export async function replaceParam( + key: string, + value: string | null +): Promise { + for (let attempt = 0; attempt < ATTEMPTS; attempt += 1) { + const url = withParam(key, value); + if (url.href === page.url.href) { + return; + } + // biome-ignore lint/performance/noAwaitInLoops: a write overtaken by another navigation is retried once + await goto(url, { + replace: true, + reset: false, + state: { ...page.state }, + }).catch(() => undefined); } }