feat(web): collapse older + caption-less videos in the list
Stop the un-summarized back-catalogue from burying the readable summaries
(UX review B3/B4). One feed, with a noise-collapse — not sections:
- Summarized + recent un-summarized videos lead inline as cards.
- Un-summarized videos older than the recency window collapse into a single
"Show N older videos — summarize on demand" disclosure (they will not
auto-fill; they are manual-only). Window comes from App.RecencyWindow
(= cfg.AutoSummarizeWindow); 0 disables the collapse (all inline).
- Caption-less videos collapse into one honest line ("N videos have no
captions and can't be summarized") instead of N dead terminal cards.
bucketRows is a pure classifier (cutoff-driven; undated rows never age out);
App gains RecencyWindow + an injectable clock for the cutoff.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -104,7 +104,7 @@ templ flashBanner(code string) {
|
||||
// #summary-list region; a non-HTMX request renders the whole page. flash carries
|
||||
// a one-shot notification (e.g. "connected", "registered") surfaced on arrival
|
||||
// after a POST→redirect.
|
||||
templ ListPage(rows []store.SummaryRow, f Filter, stats PipelineStats, flash string, hasConnected bool) {
|
||||
templ ListPage(b listBuckets, f Filter, stats PipelineStats, flash string, hasConnected bool) {
|
||||
@Layout("Tapir — Summaries") {
|
||||
@flashBanner(flash)
|
||||
@filterForm(f)
|
||||
@@ -118,7 +118,7 @@ templ ListPage(rows []store.SummaryRow, f Filter, stats PipelineStats, flash str
|
||||
</p>
|
||||
}
|
||||
<div id="summary-list">
|
||||
@summaryList(rows, hasConnected)
|
||||
@summaryList(b, hasConnected)
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -163,11 +163,14 @@ templ filterForm(f Filter) {
|
||||
</form>
|
||||
}
|
||||
|
||||
// summaryList is the swappable list fragment: one card per video (summarized or
|
||||
// not). Cards reflow to a single column on mobile; an empty list shows a friendly
|
||||
// first-run state instead of a blank table.
|
||||
templ summaryList(rows []store.SummaryRow, hasConnected bool) {
|
||||
if len(rows) == 0 {
|
||||
// summaryList is the swappable list fragment. It leads with readable summaries +
|
||||
// recent un-summarized cards (b.Main), then collapses the noise so it does not
|
||||
// bury the payload (UX review B3/B4): a one-line count of caption-less videos,
|
||||
// and a single disclosure holding the older un-summarized back-catalogue. Cards
|
||||
// reflow to a single column on mobile; an empty list shows a friendly first-run
|
||||
// state instead of a blank table.
|
||||
templ summaryList(b listBuckets, hasConnected bool) {
|
||||
if b.empty() {
|
||||
if hasConnected {
|
||||
<div class="empty empty-connected">
|
||||
<strong>Your account is connected</strong>
|
||||
@@ -182,10 +185,23 @@ templ summaryList(rows []store.SummaryRow, hasConnected bool) {
|
||||
}
|
||||
} else {
|
||||
<ul class="cards">
|
||||
for _, r := range rows {
|
||||
for _, r := range b.Main {
|
||||
@VideoCard(r)
|
||||
}
|
||||
</ul>
|
||||
if b.NoCaption > 0 {
|
||||
<p class="list-note muted">{ fmt.Sprintf("%d video(s) have no captions and can't be summarized.", b.NoCaption) }</p>
|
||||
}
|
||||
if len(b.Older) > 0 {
|
||||
<details class="older-videos">
|
||||
<summary>{ fmt.Sprintf("Show %d older videos — summarize on demand", len(b.Older)) }</summary>
|
||||
<ul class="cards">
|
||||
for _, r := range b.Older {
|
||||
@VideoCard(r)
|
||||
}
|
||||
</ul>
|
||||
</details>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user