feat(web): honest, state-aware summarize status with charm spinner (ADR-025)
Clicking Summarize polled /status, which knew only "spinning" or "done". The web ProcessVideo recorded an outcome only on success, so a 429'd or caption-less click left transcript_status unset and the poll silently reverted to the Summarize button — the rate limit was invisible and the click felt broken. - ProcessVideo now records rate_limited / none / fetched (mirrors the runner); a rate-limited video keeps its requested flag so the background sweep retries it. - /status is state-aware: summary card (done), working spinner (in-flight), a calm "waiting on rate limit, will retry" card that keeps polling so the summary lands on its own (no re-click), and a terminal "no captions" card. - Charm status text (Claude-Code / Crush inspired): the spinner cycles playful tapir-themed gerunds via CSS only (no JS), decorative + an sr-only stable status line for a11y. Pillar A (foreground fetch priority lane) is a separate follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -495,11 +495,22 @@ func (a *App) handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if row.Summarized || !a.Processing.Has(processingKey(userID, videoID)) {
|
||||
// Honest, state-aware status (ADR-025). Order matters: a finished summary wins;
|
||||
// an in-flight goroutine shows the working spinner; a recorded rate-limit shows
|
||||
// the calm "waiting, will retry" card that keeps polling; a recorded "none" is
|
||||
// terminal; anything else falls back to the normal card.
|
||||
switch {
|
||||
case row.Summarized:
|
||||
a.render(w, r, VideoCard(*row))
|
||||
case a.Processing.Has(processingKey(userID, videoID)):
|
||||
a.render(w, r, processingCard(*row))
|
||||
case row.TranscriptStatus == "rate_limited":
|
||||
a.render(w, r, waitingCard(*row))
|
||||
case row.TranscriptStatus == "none":
|
||||
a.render(w, r, noCaptionsCard(*row))
|
||||
default:
|
||||
a.render(w, r, VideoCard(*row))
|
||||
return
|
||||
}
|
||||
a.render(w, r, processingCard(*row))
|
||||
}
|
||||
|
||||
// handleSummarizeMode toggles the user's auto/manual summarization mode. The form
|
||||
|
||||
Reference in New Issue
Block a user