From 43278686f7f6abd0ce8d9cedb6600cea54da3ac0 Mon Sep 17 00:00:00 2001 From: Aaron Nelson Date: Wed, 29 Apr 2026 18:00:53 +0000 Subject: [PATCH] capture: optimistic list update + SSE refresh on transcription complete --- app/capture/page.tsx | 19 ++++++++++++++++++- proxy.ts | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/capture/page.tsx b/app/capture/page.tsx index 5a8ab25..0686cd8 100644 --- a/app/capture/page.tsx +++ b/app/capture/page.tsx @@ -111,9 +111,25 @@ export default function CapturePage() { checkPending(); window.addEventListener('focus', retryQueue); window.addEventListener('online', retryQueue); + + // Listen for capture_saved SSE — refresh list when transcription completes + let es: EventSource | null = null; + function connectSSE() { + es = new EventSource(`${API_URL}/api/captures/events`); + es.onmessage = (e) => { + try { + const data = JSON.parse(e.data); + if (data.type === 'capture_saved') loadRecentCaptures(); + } catch {} + }; + es.onerror = () => { es?.close(); setTimeout(connectSSE, 10000); }; + } + connectSSE(); + return () => { window.removeEventListener('focus', retryQueue); window.removeEventListener('online', retryQueue); + es?.close(); }; }, []); @@ -217,7 +233,8 @@ export default function CapturePage() { setImagePreview(null); setImageBlob(null); imageBlobRef.current = null; - await loadRecentCaptures(); + // Optimistic update — show immediately as processing + setRecentCaptures(prev => [{ name: `${new Date().toISOString().slice(0,16).replace('T','-').replace(':','-')}-voice ⏳` }, ...prev].slice(0, 4)); setTimeout(() => setMode('idle'), 3000); return; } diff --git a/proxy.ts b/proxy.ts index e2307ac..ace385c 100644 --- a/proxy.ts +++ b/proxy.ts @@ -6,6 +6,7 @@ export function proxy(request: NextRequest) { // Always allow these through if ( + pathname.startsWith('/api/captures') || pathname.startsWith('/api/') || pathname.startsWith('/login') || pathname.startsWith('/_next') ||