From 2389fb05a5bc70da27090743d22ce17a7f5fb16d Mon Sep 17 00:00:00 2001 From: iamdoubz <> Date: Sun, 12 Jul 2026 09:28:21 -0500 Subject: [PATCH] feat(playback): seek audio on transcript click, push position on timeupdate (FR-REC-5) --- src/lib/views/SummaryPanel.svelte | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/lib/views/SummaryPanel.svelte b/src/lib/views/SummaryPanel.svelte index 6cfdd00..99feecc 100644 --- a/src/lib/views/SummaryPanel.svelte +++ b/src/lib/views/SummaryPanel.svelte @@ -4,6 +4,7 @@ import { meetings } from "../stores/meetings.svelte"; import { calendar } from "../stores/calendar.svelte"; import { settings } from "../stores/settings.svelte"; + import { player } from "../stores/player.svelte"; import { api, errorMessage, @@ -39,10 +40,12 @@ // ---- Recording playback (FR-REC-5) ---- let audioSrc = $state(null); let audioError = $state(null); + let audioEl = $state(null); $effect(() => { const m = meetings.selected; audioSrc = null; audioError = null; + player.reset(); if (m?.recorded) { const id = m.id; api @@ -56,6 +59,17 @@ } }); + // Seek + play when a transcript segment is clicked (player.seek bumps the + // nonce so re-clicking the same segment still jumps). Reading seekNonce is + // what makes this effect re-run. + $effect(() => { + player.seekNonce; + const ms = player.seekMs; + if (ms == null || !audioEl) return; + audioEl.currentTime = ms / 1000; + void audioEl.play().catch(() => {}); + }); + // ---- Summary + action items (T5.4/T5.5/T5.6, FR-LLM-2/3/4) ---- let llmStatus = $state(null); async function refreshLlmStatus() { @@ -490,6 +504,8 @@ controls controlsList="nodownload noplaybackrate" oncontextmenu={(e) => e.preventDefault()} + bind:this={audioEl} + ontimeupdate={() => audioEl && (player.currentMs = audioEl.currentTime * 1000)} src={audioSrc} > {:else if audioError}