diff --git a/internal/adapters/store/migrate_test.go b/internal/adapters/store/migrate_test.go
index 37f1935..822b90d 100644
--- a/internal/adapters/store/migrate_test.go
+++ b/internal/adapters/store/migrate_test.go
@@ -53,7 +53,9 @@ func TestMigration010LoginEventsUpDown(t *testing.T) {
require.True(t, loginEventsExists(t), "login_events must exist at latest migration")
m := fileMigrator(t)
- // 011, 012, 013 sit above 010; step them down first so 010 is exercised in isolation.
+ // 011, 012, 013, 014 sit above 010; step them down first so 010 is exercised in isolation.
+ require.NoError(t, m.Steps(-1), "down 014 drops channel_title, login_events intact")
+ require.True(t, loginEventsExists(t), "014 down leaves login_events intact")
require.NoError(t, m.Steps(-1), "down 013 drops channel_errors, login_events intact")
require.True(t, loginEventsExists(t), "013 down leaves login_events intact")
require.NoError(t, m.Steps(-1), "down 012 is a no-op, login_events intact")
@@ -64,7 +66,7 @@ func TestMigration010LoginEventsUpDown(t *testing.T) {
require.NoError(t, m.Steps(-1), "down 010 must drop login_events")
require.False(t, loginEventsExists(t), "login_events must be gone after the down migration")
- require.NoError(t, m.Steps(4), "up must recreate 010 then re-apply 011, 012, 013")
+ require.NoError(t, m.Steps(5), "up must recreate 010 then re-apply 011, 012, 013, 014")
require.True(t, loginEventsExists(t), "login_events must be restored after the up migration")
}
@@ -87,6 +89,7 @@ func TestMigration011AutoSummarizeDefaultUpDown(t *testing.T) {
require.Equal(t, "true", autoSummarizeDefault(t), "011 sets the default to TRUE")
m := fileMigrator(t)
+ require.NoError(t, m.Steps(-1), "down 014 drops channel_title")
require.NoError(t, m.Steps(-1), "down 013 drops channel_errors")
require.NoError(t, m.Steps(-1), "down 012 is a no-op")
require.NoError(t, m.Steps(-1), "down 011 reverts the column default")
@@ -96,6 +99,31 @@ func TestMigration011AutoSummarizeDefaultUpDown(t *testing.T) {
require.Equal(t, "true", autoSummarizeDefault(t))
require.NoError(t, m.Steps(1), "up 012 runs clean (no FORCE RLS on fresh schema)")
require.NoError(t, m.Steps(1), "up 013 creates channel_errors")
+ require.NoError(t, m.Steps(1), "up 014 recreates channel_title")
+}
+
+// channelTitleExists reports whether videos.channel_title is present.
+func channelTitleExists(t *testing.T) bool {
+ t.Helper()
+ var exists bool
+ require.NoError(t, rawPool(t).QueryRow(context.Background(),
+ `SELECT EXISTS (SELECT 1 FROM information_schema.columns
+ WHERE table_name = 'videos' AND column_name = 'channel_title')`).Scan(&exists))
+ return exists
+}
+
+// TestMigration014VideoChannelTitleUpDown proves 014 is reversible: down drops
+// videos.channel_title, up recreates it.
+func TestMigration014VideoChannelTitleUpDown(t *testing.T) {
+ newStore(t) // latest (014 applied)
+ require.True(t, channelTitleExists(t), "channel_title exists at latest migration")
+
+ m := fileMigrator(t)
+ require.NoError(t, m.Steps(-1), "down 014 must drop channel_title")
+ require.False(t, channelTitleExists(t), "channel_title must be gone after the down migration")
+
+ require.NoError(t, m.Steps(1), "up 014 must recreate channel_title")
+ require.True(t, channelTitleExists(t), "channel_title must be restored after the up migration")
}
// TestMigration012FixAutoSummarizeRLS proves 012 runs cleanly and flips any
diff --git a/internal/adapters/store/migrations/014_video_channel_title.down.sql b/internal/adapters/store/migrations/014_video_channel_title.down.sql
new file mode 100644
index 0000000..2575250
--- /dev/null
+++ b/internal/adapters/store/migrations/014_video_channel_title.down.sql
@@ -0,0 +1 @@
+ALTER TABLE videos DROP COLUMN channel_title;
diff --git a/internal/adapters/store/migrations/014_video_channel_title.up.sql b/internal/adapters/store/migrations/014_video_channel_title.up.sql
new file mode 100644
index 0000000..e917f10
--- /dev/null
+++ b/internal/adapters/store/migrations/014_video_channel_title.up.sql
@@ -0,0 +1,8 @@
+-- Store the source channel's title per video so the list can offer a real
+-- channel filter (multi-select of the user's channels) instead of the dead
+-- free-text field that only ever matched the provider string. Nullable: existing
+-- rows backfill on the next discovery pass (UpsertVideo writes it); pasted videos
+-- get it immediately from videos.list. No FK to a channels table at Stage 0 — the
+-- title is a denormalised display/filter value, consistent with the existing
+-- subscription_id-stays-NULL stance (data-model.md).
+ALTER TABLE videos ADD COLUMN channel_title TEXT;
diff --git a/internal/adapters/store/reads.go b/internal/adapters/store/reads.go
index 6db068c..c3315cf 100644
--- a/internal/adapters/store/reads.go
+++ b/internal/adapters/store/reads.go
@@ -29,6 +29,7 @@ type SummaryRow struct {
ProviderVideoID string // videos.provider_video_id; empty when no videos row
Title string // videos.title; empty when no videos row
Channel string // videos.provider for now; empty when no videos row
+ ChannelTitle string // videos.channel_title; the source channel, for display + filtering
URL string // videos.url; empty when no videos row
PublishedAt time.Time // videos.published_at; zero when absent
Summary string
@@ -137,7 +138,8 @@ const selectVideo = `
COALESCE(s.created_at, v.seen_at),
(s.id IS NOT NULL) AS summarized,
v.summarize_requested,
- COALESCE(v.transcript_status, '')
+ COALESCE(v.transcript_status, ''),
+ COALESCE(v.channel_title, '')
FROM videos v
LEFT JOIN summaries s ON s.video_id = v.id AND s.user_id = v.user_id`
@@ -254,6 +256,7 @@ func scanVideoRow(rows pgx.Row) (SummaryRow, error) {
&row.Summarized,
&row.SummarizeRequested,
&row.TranscriptStatus,
+ &row.ChannelTitle,
); err != nil {
return SummaryRow{}, fmt.Errorf("store: scan video: %w", err)
}
diff --git a/internal/adapters/store/videos.go b/internal/adapters/store/videos.go
index 1a6b448..7b28cbb 100644
--- a/internal/adapters/store/videos.go
+++ b/internal/adapters/store/videos.go
@@ -46,14 +46,15 @@ func (s *Store) UpsertVideo(ctx context.Context, v domain.Video) (string, error)
}
if err := tx.QueryRow(ctx,
- `INSERT INTO videos (user_id, provider, provider_video_id, title, url, published_at)
- VALUES ($1, $2, $3, $4, $5, $6)
+ `INSERT INTO videos (user_id, provider, provider_video_id, title, url, published_at, channel_title)
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (user_id, provider, provider_video_id) DO UPDATE SET
- title = EXCLUDED.title,
- url = EXCLUDED.url,
- published_at = EXCLUDED.published_at
+ title = EXCLUDED.title,
+ url = EXCLUDED.url,
+ published_at = EXCLUDED.published_at,
+ channel_title = COALESCE(NULLIF(EXCLUDED.channel_title, ''), videos.channel_title)
RETURNING id`,
- v.UserID, provider, v.ProviderVideoID, v.Title, v.URL, nullTime(v.PublishedAt),
+ v.UserID, provider, v.ProviderVideoID, v.Title, v.URL, nullTime(v.PublishedAt), v.ChannelTitle,
).Scan(&id); err != nil {
return fmt.Errorf("store: upsert video: %w", err)
}
@@ -110,3 +111,31 @@ func (s *Store) NewestUnsummarizedVideoIDs(ctx context.Context, userID string, l
}
return ids, nil
}
+
+// DistinctChannels returns the user's distinct, non-empty source channel titles
+// (the channels they have videos from), alphabetically — the option list for the
+// feed's channel filter. RLS-scoped via withUser.
+func (s *Store) DistinctChannels(ctx context.Context, userID string) ([]string, error) {
+ var out []string
+ if err := s.withUser(ctx, userID, func(tx pgx.Tx) error {
+ rows, err := tx.Query(ctx,
+ `SELECT DISTINCT channel_title FROM videos
+ WHERE user_id = $1 AND channel_title IS NOT NULL AND channel_title <> ''
+ ORDER BY channel_title`, userID)
+ if err != nil {
+ return fmt.Errorf("store: distinct channels: %w", err)
+ }
+ defer rows.Close()
+ for rows.Next() {
+ var c string
+ if err := rows.Scan(&c); err != nil {
+ return fmt.Errorf("store: scan channel: %w", err)
+ }
+ out = append(out, c)
+ }
+ return rows.Err()
+ }); err != nil {
+ return nil, err
+ }
+ return out, nil
+}
diff --git a/internal/adapters/store/videos_test.go b/internal/adapters/store/videos_test.go
index c5b5762..3451a8e 100644
--- a/internal/adapters/store/videos_test.go
+++ b/internal/adapters/store/videos_test.go
@@ -113,3 +113,29 @@ func TestNewestUnsummarizedVideoIDs(t *testing.T) {
require.NoError(t, err)
require.Empty(t, none, "limit 0 returns nothing")
}
+
+func TestUpsertVideoPersistsChannelAndDistinctChannels(t *testing.T) {
+ ctx := context.Background()
+ s := newStore(t)
+ resetDB(t, rawPool(t))
+
+ mk := func(pid, channel string) {
+ v := ytVideo(userA, pid, pid)
+ v.ChannelTitle = channel
+ _, err := s.UpsertVideo(ctx, v)
+ require.NoError(t, err)
+ }
+ mk("aa11111aaaa", "Acme Talks")
+ mk("bb22222bbbb", "Acme Talks") // same channel
+ mk("cc33333cccc", "Zeta Channel")
+ // userB's channel must not leak.
+ vb := ytVideo(userB, "dd44444dddd", "x")
+ vb.ChannelTitle = "Bravo Only"
+ _, err := s.UpsertVideo(ctx, vb)
+ require.NoError(t, err)
+
+ got, err := s.DistinctChannels(ctx, userA)
+ require.NoError(t, err)
+ require.Equal(t, []string{"Acme Talks", "Zeta Channel"}, got,
+ "distinct, alphabetical, user-scoped (no Bravo Only)")
+}
diff --git a/internal/adapters/youtube/videobyid_test.go b/internal/adapters/youtube/videobyid_test.go
index 31762fe..0342e1c 100644
--- a/internal/adapters/youtube/videobyid_test.go
+++ b/internal/adapters/youtube/videobyid_test.go
@@ -21,7 +21,7 @@ func TestVideoByID(t *testing.T) {
if got := r.URL.Query().Get("part"); got != "snippet" {
t.Errorf("expected part=snippet, got %q", got)
}
- _, _ = w.Write([]byte(`{"items":[{"snippet":{"title":"Never Gonna Give You Up","publishedAt":"2026-05-20T09:00:00Z"}}]}`))
+ _, _ = w.Write([]byte(`{"items":[{"snippet":{"title":"Never Gonna Give You Up","channelTitle":"Rick Astley","publishedAt":"2026-05-20T09:00:00Z"}}]}`))
})
v, err := a.VideoByID(context.Background(), "u1", id)
@@ -34,6 +34,9 @@ func TestVideoByID(t *testing.T) {
if v.ProviderVideoID != id || v.Title != "Never Gonna Give You Up" {
t.Errorf("unexpected video: %+v", v)
}
+ if v.ChannelTitle != "Rick Astley" {
+ t.Errorf("ChannelTitle = %q, want Rick Astley", v.ChannelTitle)
+ }
if v.Provider != domain.ProviderYouTube || v.URL != "https://www.youtube.com/watch?v="+id {
t.Errorf("video not wired correctly: %+v", v)
}
diff --git a/internal/adapters/youtube/youtube.go b/internal/adapters/youtube/youtube.go
index 96137f7..99fd61b 100644
--- a/internal/adapters/youtube/youtube.go
+++ b/internal/adapters/youtube/youtube.go
@@ -234,6 +234,7 @@ func (a *Adapter) NewVideos(ctx context.Context, sub domain.Subscription) ([]dom
Provider: domain.ProviderYouTube,
ProviderVideoID: vid,
Title: item.Snippet.Title,
+ ChannelTitle: sub.ChannelTitle,
URL: "https://www.youtube.com/watch?v=" + vid,
PublishedAt: item.Snippet.PublishedAt,
})
@@ -270,6 +271,7 @@ func (a *Adapter) VideoByID(ctx context.Context, userID, videoID string) (domain
Provider: domain.ProviderYouTube,
ProviderVideoID: videoID,
Title: it.Snippet.Title,
+ ChannelTitle: it.Snippet.ChannelTitle,
URL: "https://www.youtube.com/watch?v=" + videoID,
PublishedAt: it.Snippet.PublishedAt,
}, nil
@@ -376,8 +378,9 @@ type playlistItemListResponse struct {
type videoListResponse struct {
Items []struct {
Snippet struct {
- Title string `json:"title"`
- PublishedAt time.Time `json:"publishedAt"`
+ Title string `json:"title"`
+ ChannelTitle string `json:"channelTitle"`
+ PublishedAt time.Time `json:"publishedAt"`
} `json:"snippet"`
} `json:"items"`
}
diff --git a/internal/adapters/youtube/youtube_test.go b/internal/adapters/youtube/youtube_test.go
index 133de16..43e412e 100644
--- a/internal/adapters/youtube/youtube_test.go
+++ b/internal/adapters/youtube/youtube_test.go
@@ -131,7 +131,7 @@ func TestNewVideos(t *testing.T) {
}`))
})
- sub := domain.Subscription{ID: "s1", UserID: "u1", ChannelID: "UC_acme"}
+ sub := domain.Subscription{ID: "s1", UserID: "u1", ChannelID: "UC_acme", ChannelTitle: "Acme Channel"}
vids, err := a.NewVideos(context.Background(), sub)
if err != nil {
t.Fatalf("NewVideos: %v", err)
@@ -143,6 +143,9 @@ func TestNewVideos(t *testing.T) {
if v.ProviderVideoID != "vid1" || v.Title != "Designing for Attention" {
t.Errorf("unexpected video: %+v", v)
}
+ if v.ChannelTitle != "Acme Channel" {
+ t.Errorf("ChannelTitle = %q, want Acme Channel", v.ChannelTitle)
+ }
if v.Provider != domain.ProviderYouTube || v.URL != "https://www.youtube.com/watch?v=vid1" {
t.Errorf("video not wired correctly: %+v", v)
}
diff --git a/internal/domain/domain.go b/internal/domain/domain.go
index c02c626..367924a 100644
--- a/internal/domain/domain.go
+++ b/internal/domain/domain.go
@@ -73,6 +73,7 @@ type Video struct {
Provider Provider
ProviderVideoID string
Title string
+ ChannelTitle string
URL string
PublishedAt time.Time
SeenAt time.Time
diff --git a/internal/web/handlers.go b/internal/web/handlers.go
index 5bfaee5..04bd7ed 100644
--- a/internal/web/handlers.go
+++ b/internal/web/handlers.go
@@ -21,6 +21,9 @@ import (
// fake without a database.
type Store interface {
ListVideos(ctx context.Context, userID string, limit int) ([]store.SummaryRow, error)
+ // DistinctChannels lists the user's source channels — the options for the
+ // feed's channel multi-select filter.
+ DistinctChannels(ctx context.Context, userID string) ([]string, error)
GetSummaryByVideo(ctx context.Context, userID, videoID string) (*store.SummaryRow, error)
GetVideoRow(ctx context.Context, userID, videoID string) (*store.SummaryRow, error)
ActionsFor(ctx context.Context, userID string, videoIDs []string) (map[string][]string, error)
@@ -196,7 +199,7 @@ func (a *App) handleList(w http.ResponseWriter, r *http.Request) {
}
q := r.URL.Query()
f := Filter{
- Channel: q.Get("channel"),
+ Channels: nonEmptyStrings(q["channel"]),
From: q.Get("from"),
To: q.Get("to"),
OnlySummarized: q.Get("summarized") == "1",
@@ -211,6 +214,13 @@ func (a *App) handleList(w http.ResponseWriter, r *http.Request) {
rows := f.apply(allRows)
buckets := bucketRows(rows, a.recencyCutoff())
+ // Channel options for the multi-select filter (the user's source channels).
+ channels, err := a.Store.DistinctChannels(r.Context(), userID)
+ if err != nil {
+ a.serverError(w, r, "distinct channels", err)
+ return
+ }
+
// hasConnected drives both the paste box (shown to ANY connected user, #2) and
// the empty-state copy (a fresh account with a connection but no discovery pass
// yet reads "connected, summaries land gradually" rather than "nothing here").
@@ -227,7 +237,7 @@ func (a *App) handleList(w http.ResponseWriter, r *http.Request) {
a.render(w, r, summaryList(buckets, hasConnected))
return
}
- a.render(w, r, ListPage(buckets, f, stats, takeFlash(w, r), hasConnected))
+ a.render(w, r, ListPage(buckets, f, stats, takeFlash(w, r), hasConnected, channels))
}
// handleDetail renders one summary in full (highlights, takeaways, action group).
diff --git a/internal/web/handlers_test.go b/internal/web/handlers_test.go
index 9d60956..7d6dee8 100644
--- a/internal/web/handlers_test.go
+++ b/internal/web/handlers_test.go
@@ -207,13 +207,15 @@ func TestListChannelFilter(t *testing.T) {
resetDB(t, p)
require.NoError(t, deliver(ctx, app, videoX, "body x"))
seedVideo(t, p, videoX, "X Title", "https://x", time.Time{})
+ _, err := p.Exec(ctx, `UPDATE videos SET channel_title = 'Acme Channel' WHERE id = $1`, videoX)
+ require.NoError(t, err)
- // Channel is "youtube" for seeded rows; a non-matching filter hides them.
- rec := do(t, app, httptest.NewRequest(http.MethodGet, "/?channel=vimeo", nil))
+ // Selecting a different channel hides the row; selecting its channel shows it.
+ rec := do(t, app, httptest.NewRequest(http.MethodGet, "/?channel=Other+Channel", nil))
require.Equal(t, http.StatusOK, rec.Code)
require.NotContains(t, body(t, rec), "X Title")
- rec = do(t, app, httptest.NewRequest(http.MethodGet, "/?channel=youtube", nil))
+ rec = do(t, app, httptest.NewRequest(http.MethodGet, "/?channel=Acme+Channel", nil))
require.Contains(t, body(t, rec), "X Title")
}
diff --git a/internal/web/paste_test.go b/internal/web/paste_test.go
index f6d44c9..bb5d6cc 100644
--- a/internal/web/paste_test.go
+++ b/internal/web/paste_test.go
@@ -3,6 +3,7 @@ package web
import (
"bytes"
"context"
+ "gitea.d-ma.be/mathias/tapir/internal/adapters/store"
"strings"
"testing"
)
@@ -64,7 +65,7 @@ func TestParseYouTubeVideoID(t *testing.T) {
func TestListPageShowsPasteFormOnlyWhenConnected(t *testing.T) {
render := func(connected bool) string {
var buf bytes.Buffer
- if err := ListPage(listBuckets{}, Filter{}, PipelineStats{}, "", connected).Render(context.Background(), &buf); err != nil {
+ if err := ListPage(listBuckets{}, Filter{}, PipelineStats{}, "", connected, nil).Render(context.Background(), &buf); err != nil {
t.Fatalf("render: %v", err)
}
return buf.String()
@@ -78,3 +79,19 @@ func TestListPageShowsPasteFormOnlyWhenConnected(t *testing.T) {
t.Errorf("disconnected feed must not show the paste form")
}
}
+
+func TestFilterMatchesMultipleChannels(t *testing.T) {
+ f := Filter{Channels: []string{"Acme", "Zeta"}}
+ row := func(ch string) store.SummaryRow { return store.SummaryRow{ChannelTitle: ch, Summarized: true} }
+
+ rows := []store.SummaryRow{row("Acme"), row("Beta"), row("Zeta")}
+ got := f.apply(rows)
+ if len(got) != 2 || got[0].ChannelTitle != "Acme" || got[1].ChannelTitle != "Zeta" {
+ t.Fatalf("multi-channel filter = %+v, want Acme+Zeta only", got)
+ }
+
+ // Empty selection = no channel constraint (all pass).
+ if n := len(Filter{}.apply(rows)); n != 3 {
+ t.Fatalf("no channel filter should pass all rows, got %d", n)
+ }
+}
diff --git a/internal/web/view.go b/internal/web/view.go
index 40d9900..d415ebd 100644
--- a/internal/web/view.go
+++ b/internal/web/view.go
@@ -2,6 +2,7 @@ package web
import (
"regexp"
+ "slices"
"strings"
"time"
"unicode/utf8"
@@ -469,7 +470,7 @@ func (b listBuckets) empty() bool {
// Dates are kept as the raw YYYY-MM-DD strings so the form re-renders the user's
// input verbatim; parsing happens in matchFilter.
type Filter struct {
- Channel string
+ Channels []string // selected channel titles; empty = all channels
From string
To string
OnlySummarized bool // show only videos that have a summary
@@ -480,7 +481,28 @@ type Filter struct {
// filter) the bar is hidden so the connect CTA stands alone (UX review C1); a
// filter that happens to match nothing still shows the bar so it can be cleared.
func (f Filter) active() bool {
- return f.Channel != "" || f.From != "" || f.To != "" || f.OnlySummarized
+ return len(f.Channels) > 0 || f.From != "" || f.To != "" || f.OnlySummarized
+}
+
+// HasChannel reports whether a channel is currently selected (drives the
+// multi-select's selected state in the view).
+func (f Filter) HasChannel(c string) bool {
+ return slices.Contains(f.Channels, c)
+}
+
+// nonEmptyStrings drops blank entries. A channel multi-select submits real
+// channel titles; this guards against a stray empty value reaching the filter.
+func nonEmptyStrings(ss []string) []string {
+ out := ss[:0:0]
+ for _, s := range ss {
+ if strings.TrimSpace(s) != "" {
+ out = append(out, s)
+ }
+ }
+ if len(out) == 0 {
+ return nil
+ }
+ return out
}
// matches reports whether a row satisfies the filter. Channel is an exact match;
@@ -491,7 +513,7 @@ func (f Filter) matches(r store.SummaryRow) bool {
if f.OnlySummarized && !r.Summarized {
return false
}
- if f.Channel != "" && r.Channel != f.Channel {
+ if len(f.Channels) > 0 && !slices.Contains(f.Channels, r.ChannelTitle) {
return false
}
if from, ok := parseDate(f.From); ok {
@@ -521,7 +543,7 @@ func parseDate(s string) (time.Time, bool) {
// apply returns the subset of rows matching the filter, preserving order.
func (f Filter) apply(rows []store.SummaryRow) []store.SummaryRow {
- if f.Channel == "" && f.From == "" && f.To == "" && !f.OnlySummarized {
+ if len(f.Channels) == 0 && f.From == "" && f.To == "" && !f.OnlySummarized {
return rows
}
out := rows[:0:0]
diff --git a/internal/web/views.templ b/internal/web/views.templ
index 30debc7..48a989f 100644
--- a/internal/web/views.templ
+++ b/internal/web/views.templ
@@ -104,14 +104,14 @@ 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(b listBuckets, f Filter, stats PipelineStats, flash string, hasConnected bool) {
+templ ListPage(b listBuckets, f Filter, stats PipelineStats, flash string, hasConnected bool, channels []string) {
@Layout("Tapir — Summaries") {
@flashBanner(flash)
if hasConnected {
@pasteForm()
}
if !b.empty() || f.active() {
- @filterForm(f)
+ @filterForm(f, channels)
}
if stats.RateLimited > 0 || stats.Pending > 0 || stats.NoText > 0 {
@pipelineBar(stats)
@@ -168,7 +168,7 @@ templ pasteForm() {
}
-templ filterForm(f Filter) {
+templ filterForm(f Filter, channels []string) {
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -604,25 +647,25 @@ func summaryList(b listBuckets, hasConnected bool) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var21 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var21 == nil {
- templ_7745c5c3_Var21 = templ.NopComponent
+ templ_7745c5c3_Var22 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var22 == nil {
+ templ_7745c5c3_Var22 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
if b.empty() {
if hasConnected {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "Your account is connected Tapir is finding your subscriptions and fetching captions — summaries appear here gradually. Check back later.
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "Your account is connected Tapir is finding your subscriptions and fetching captions — summaries appear here gradually. Check back later.
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -632,48 +675,48 @@ func summaryList(b listBuckets, hasConnected bool) templ.Component {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if b.NoCaption > 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var22 string
- templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d video(s) have no captions and can't be summarized.", b.NoCaption))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 218, Col: 113}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if len(b.Older) > 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var23 string
- templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("Show %d older videos — summarize on demand", len(b.Older)))
+ templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d video(s) have no captions and can't be summarized.", b.NoCaption))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 222, Col: 88}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 227, Col: 113}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if len(b.Older) > 0 {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var24 string
+ templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("Show %d older videos — summarize on demand", len(b.Older)))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 231, Col: 88}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -683,7 +726,7 @@ func summaryList(b listBuckets, hasConnected bool) templ.Component {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -719,297 +762,297 @@ func VideoCard(r store.SummaryRow) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var24 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var24 == nil {
- templ_7745c5c3_Var24 = templ.NopComponent
+ templ_7745c5c3_Var25 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var25 == nil {
+ templ_7745c5c3_Var25 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- var templ_7745c5c3_Var25 = []any{"card", templ.KV("card-pending", !r.Summarized)}
- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var25...)
+ var templ_7745c5c3_Var26 = []any{"card", templ.KV("card-pending", !r.Summarized)}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var26...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "\" id=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var28 string
+ templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.ResolveAttributeValue("video-" + r.VideoID)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 252, Col: 88}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var28)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if r.Summarized {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var29 string
- templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 245, Col: 76}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 254, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var30 string
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 247, Col: 44}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 254, Col: 76}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- }
- if cardMeta(r) != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ if cardMeta(r) != "" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var32 string
+ templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(cardMeta(r))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 259, Col: 39}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
if r.Summarized {
if p := previewText(r.Summary, 160); p != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var32 string
- templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(p)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 254, Col: 33}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1038,12 +1081,12 @@ func TapirSpinner() templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var41 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var41 == nil {
- templ_7745c5c3_Var41 = templ.NopComponent
+ templ_7745c5c3_Var42 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var42 == nil {
+ templ_7745c5c3_Var42 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 89, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1051,7 +1094,7 @@ func TapirSpinner() templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1059,7 +1102,7 @@ func TapirSpinner() templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1067,33 +1110,33 @@ func TapirSpinner() templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "
Summarizing…
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var44 string
+ templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(tapirBarFill)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 327, Col: 99}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "
Summarizing…
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1122,69 +1165,69 @@ func processingCard(r store.SummaryRow) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var44 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var44 == nil {
- templ_7745c5c3_Var44 = templ.NopComponent
+ templ_7745c5c3_Var45 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var45 == nil {
+ templ_7745c5c3_Var45 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "\" hx-get=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var47 string
- templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r))
+ templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.ResolveAttributeValue(string(statusURL(r.VideoID)))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 336, Col: 43}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 341, Col: 39}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var47)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "\" hx-trigger=\"every 2s\" hx-swap=\"outerHTML\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var48 string
+ templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 345, Col: 43}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if cardMeta(r) != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1193,7 +1236,7 @@ func processingCard(r store.SummaryRow) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 101, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1219,12 +1262,12 @@ func DetailPage(r store.SummaryRow) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var49 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var49 == nil {
- templ_7745c5c3_Var49 = templ.NopComponent
+ templ_7745c5c3_Var50 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var50 == nil {
+ templ_7745c5c3_Var50 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var50 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_Var51 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
@@ -1236,99 +1279,99 @@ func DetailPage(r store.SummaryRow) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "← Summaries
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, "← Summaries
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var51 string
- templ_7745c5c3_Var51, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r))
+ var templ_7745c5c3_Var52 string
+ templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 350, Col: 24}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 359, Col: 24}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var51))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, "
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if detailMeta(r) != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var52 string
- templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(detailMeta(r))
+ var templ_7745c5c3_Var53 string
+ templ_7745c5c3_Var53, templ_7745c5c3_Err = templ.JoinStringErrs(detailMeta(r))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 353, Col: 26}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 362, Col: 26}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var53))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
if r.FallbackUsed {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "fallback ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "fallback ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if url, ok := embedURL(r.ProviderVideoID); ok {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 101, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "\" title=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var55 string
+ templ_7745c5c3_Var55, templ_7745c5c3_Err = templ.ResolveAttributeValue(displayTitle(r))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 372, Col: 29}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var55)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "\" loading=\"lazy\" referrerpolicy=\"strict-origin-when-cross-origin\" allow=\"accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
if r.URL != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, "watch on source ↗
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "\" rel=\"noopener noreferrer\">watch on source ↗")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1338,83 +1381,83 @@ func DetailPage(r store.SummaryRow) templ.Component {
return templ_7745c5c3_Err
}
if len(r.Takeaways) > 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "Takeaways ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "Takeaways ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, t := range r.Takeaways {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var56 string
- templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinStringErrs(t)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 384, Col: 14}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var56))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- if len(r.Highlights) > 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "Highlights ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, h := range r.Highlights {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 114, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var57 string
- templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(h)
+ templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(t)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 394, Col: 14}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 393, Col: 14}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var57))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 116, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 114, "Summary ")
+ if len(r.Highlights) > 0 {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "Highlights ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, h := range r.Highlights {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var58 string
+ templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(h)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 403, Col: 14}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "Summary ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var58 string
- templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(r.Summary)
+ var templ_7745c5c3_Var59 string
+ templ_7745c5c3_Var59, templ_7745c5c3_Err = templ.JoinStringErrs(r.Summary)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 401, Col: 31}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 410, Col: 31}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var59))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
- templ_7745c5c3_Err = Layout("Tapir — "+displayTitle(r)).Render(templ.WithChildren(ctx, templ_7745c5c3_Var50), templ_7745c5c3_Buffer)
+ templ_7745c5c3_Err = Layout("Tapir — "+displayTitle(r)).Render(templ.WithChildren(ctx, templ_7745c5c3_Var51), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1441,12 +1484,12 @@ func RegisterPage(email, errMsg string) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var59 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var59 == nil {
- templ_7745c5c3_Var59 = templ.NopComponent
+ templ_7745c5c3_Var60 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var60 == nil {
+ templ_7745c5c3_Var60 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var60 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_Var61 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
@@ -1458,59 +1501,59 @@ func RegisterPage(email, errMsg string) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 116, "Complete your registration ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "Complete your registration ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if email != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "Signed in as ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var61 string
- templ_7745c5c3_Var61, templ_7745c5c3_Err = templ.JoinStringErrs(email)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 415, Col: 40}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var61))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, ".
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "Choose a display name to finish setting up your Tapir account.
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if errMsg != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, "
Signed in as ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var62 string
- templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg)
+ templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.JoinStringErrs(email)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 419, Col: 42}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 424, Col: 40}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var62))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, ".")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "Display name Register ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "Choose a display name to finish setting up your Tapir account.
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if errMsg != "" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 127, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var63 string
+ templ_7745c5c3_Var63, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 428, Col: 42}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var63))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 128, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 129, "Display name Register ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
- templ_7745c5c3_Err = Layout("Tapir — Register").Render(templ.WithChildren(ctx, templ_7745c5c3_Var60), templ_7745c5c3_Buffer)
+ templ_7745c5c3_Err = Layout("Tapir — Register").Render(templ.WithChildren(ctx, templ_7745c5c3_Var61), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1538,12 +1581,12 @@ func AccountPage(displayName, email string, conns []store.Connection, autoSummar
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var63 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var63 == nil {
- templ_7745c5c3_Var63 = templ.NopComponent
+ templ_7745c5c3_Var64 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var64 == nil {
+ templ_7745c5c3_Var64 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Var64 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_Var65 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
@@ -1559,43 +1602,43 @@ func AccountPage(displayName, email string, conns []store.Connection, autoSummar
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, " Account Display name ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 130, " Account Display name ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var65 string
- templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.JoinStringErrs(displayNameOr(displayName))
+ var templ_7745c5c3_Var66 string
+ templ_7745c5c3_Var66, templ_7745c5c3_Err = templ.JoinStringErrs(displayNameOr(displayName))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 443, Col: 36}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 452, Col: 36}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var65))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var66))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 131, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if email != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "Signed in as ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 132, " Signed in as ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var66 string
- templ_7745c5c3_Var66, templ_7745c5c3_Err = templ.JoinStringErrs(email)
+ var templ_7745c5c3_Var67 string
+ templ_7745c5c3_Var67, templ_7745c5c3_Err = templ.JoinStringErrs(email)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 446, Col: 16}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 455, Col: 16}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var66))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var67))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 133, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 127, "Summarization Automatic summarizes new videos from about the last week as they are discovered. Older videos stay browsable — summarize them on demand. Manual lets you pick which videos to summarize — every new video appears in your list with a Summarize button.
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 134, "Summarization Automatic summarizes new videos from about the last week as they are discovered. Older videos stay browsable — summarize them on demand. Manual lets you pick which videos to summarize — every new video appears in your list with a Summarize button.
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1603,178 +1646,178 @@ func AccountPage(displayName, email string, conns []store.Connection, autoSummar
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 128, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 135, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(channelErrors) > 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 129, "Unavailable channels ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 136, "Unavailable channels ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var67 string
- templ_7745c5c3_Var67, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d channel(s) returned errors on the last discovery pass.", len(channelErrors)))
+ var templ_7745c5c3_Var68 string
+ templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d channel(s) returned errors on the last discovery pass.", len(channelErrors)))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 463, Col: 100}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 472, Col: 100}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var67))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var68))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 130, " These may have been deleted or made private on YouTube.
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 137, " These may have been deleted or made private on YouTube.
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, ce := range channelErrors {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 131, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var68 string
- templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.JoinStringErrs(ce.ChannelName)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 469, Col: 57}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var68))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 132, " unavailable since ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 138, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var69 string
- templ_7745c5c3_Var69, templ_7745c5c3_Err = templ.JoinStringErrs(ce.FirstSeen.Format("2006-01-02"))
+ templ_7745c5c3_Var69, templ_7745c5c3_Err = templ.JoinStringErrs(ce.ChannelName)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 471, Col: 89}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 478, Col: 57}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var69))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 133, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 134, " ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 135, "Connected accounts ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- if len(conns) == 0 {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 136, "No connected video accounts yet.
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 137, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- for _, c := range conns {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 138, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, " unavailable since ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var70 string
- templ_7745c5c3_Var70, templ_7745c5c3_Err = templ.JoinStringErrs(providerLabel(c.Provider))
+ templ_7745c5c3_Var70, templ_7745c5c3_Err = templ.JoinStringErrs(ce.FirstSeen.Format("2006-01-02"))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 486, Col: 64}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 480, Col: 89}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var70))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 140, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 141, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 142, "
Connected accounts ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if len(conns) == 0 {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 143, "No connected video accounts yet.
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 144, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, c := range conns {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 145, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var71 string
+ templ_7745c5c3_Var71, templ_7745c5c3_Err = templ.JoinStringErrs(providerLabel(c.Provider))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 495, Col: 64}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var71))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 146, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if c.ProviderAccount != "" {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 140, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 147, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var71 string
- templ_7745c5c3_Var71, templ_7745c5c3_Err = templ.JoinStringErrs(c.ProviderAccount)
+ var templ_7745c5c3_Var72 string
+ templ_7745c5c3_Var72, templ_7745c5c3_Err = templ.JoinStringErrs(c.ProviderAccount)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 488, Col: 49}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 497, Col: 49}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var71))
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var72))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 141, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 148, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 142, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var72 string
- templ_7745c5c3_Var72, templ_7745c5c3_Err = templ.JoinStringErrs(c.Status)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 490, Col: 38}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var72))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 143, "
connected ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 149, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var73 string
- templ_7745c5c3_Var73, templ_7745c5c3_Err = templ.JoinStringErrs(c.ConnectedAt.Format("2006-01-02"))
+ templ_7745c5c3_Var73, templ_7745c5c3_Err = templ.JoinStringErrs(c.Status)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 492, Col: 83}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 499, Col: 38}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var73))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 144, "
connected ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- var templ_7745c5c3_Var74 templ.SafeURL
- templ_7745c5c3_Var74, templ_7745c5c3_Err = templ.JoinURLErrs(disconnectURL(c.Provider))
+ var templ_7745c5c3_Var74 string
+ templ_7745c5c3_Var74, templ_7745c5c3_Err = templ.JoinStringErrs(c.ConnectedAt.Format("2006-01-02"))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 493, Col: 62}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 501, Col: 83}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var74))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 145, "\">Disconnect ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 151, "
Disconnect ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 146, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 153, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
if !hasYouTube(conns) {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 147, "Connect YouTube
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 154, "Connect YouTube
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 148, "Delete account Permanently remove your Tapir account and all of its data — summaries, watch/skip/save actions, and connected accounts. This cannot be undone.
Delete account… This permanently deletes your account and all data. Are you sure?
Yes, permanently delete my account ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 155, "Delete account Permanently remove your Tapir account and all of its data — summaries, watch/skip/save actions, and connected accounts. This cannot be undone.
Delete account… This permanently deletes your account and all data. Are you sure?
Yes, permanently delete my account ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
- templ_7745c5c3_Err = Layout("Tapir — Account").Render(templ.WithChildren(ctx, templ_7745c5c3_Var64), templ_7745c5c3_Buffer)
+ templ_7745c5c3_Err = Layout("Tapir — Account").Render(templ.WithChildren(ctx, templ_7745c5c3_Var65), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1802,51 +1845,51 @@ func summarizeModeControl(auto bool) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var75 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var75 == nil {
- templ_7745c5c3_Var75 = templ.NopComponent
+ templ_7745c5c3_Var76 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var76 == nil {
+ templ_7745c5c3_Var76 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 149, "Current mode: ")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var76 string
- templ_7745c5c3_Var76, templ_7745c5c3_Err = templ.JoinStringErrs(summarizeModeLabel(auto))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 530, Col: 53}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var76))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 150, "
Current mode: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var77 string
- templ_7745c5c3_Var77, templ_7745c5c3_Err = templ.ResolveAttributeValue(boolStr(!auto))
+ templ_7745c5c3_Var77, templ_7745c5c3_Err = templ.JoinStringErrs(summarizeModeLabel(auto))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 538, Col: 61}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 539, Col: 53}
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var77)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var77))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 151, "\"> ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 157, "
")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "\"> ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var79 string
+ templ_7745c5c3_Var79, templ_7745c5c3_Err = templ.JoinStringErrs(summarizeModeToggleLabel(auto))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 548, Col: 79}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var79))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1874,38 +1917,38 @@ func ActionButtons(videoID string, active map[string]bool) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var79 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var79 == nil {
- templ_7745c5c3_Var79 = templ.NopComponent
+ templ_7745c5c3_Var80 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var80 == nil {
+ templ_7745c5c3_Var80 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 153, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, "\" hx-target=\"#action-buttons\" hx-swap=\"outerHTML\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1917,7 +1960,7 @@ func ActionButtons(videoID string, active map[string]bool) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 156, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 163, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1925,7 +1968,7 @@ func ActionButtons(videoID string, active map[string]bool) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 157, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 164, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1951,81 +1994,81 @@ func actionButton(verb string, isActive bool) templ.Component {
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Var82 := templ.GetChildren(ctx)
- if templ_7745c5c3_Var82 == nil {
- templ_7745c5c3_Var82 = templ.NopComponent
+ templ_7745c5c3_Var83 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var83 == nil {
+ templ_7745c5c3_Var83 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- var templ_7745c5c3_Var83 = []any{"action", templ.KV("active", isActive)}
- templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var83...)
+ var templ_7745c5c3_Var84 = []any{"action", templ.KV("active", isActive)}
+ templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var84...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 167, "\" aria-pressed=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var87 string
+ templ_7745c5c3_Var87, templ_7745c5c3_Err = templ.ResolveAttributeValue(ariaPressed(isActive))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 586, Col: 38}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var87)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 168, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if isActive {
- var templ_7745c5c3_Var87 string
- templ_7745c5c3_Var87, templ_7745c5c3_Err = templ.JoinStringErrs("✓ " + actionLabel(verb))
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 580, Col: 31}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var87))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- } else {
var templ_7745c5c3_Var88 string
- templ_7745c5c3_Var88, templ_7745c5c3_Err = templ.JoinStringErrs(actionLabel(verb))
+ templ_7745c5c3_Var88, templ_7745c5c3_Err = templ.JoinStringErrs("✓ " + actionLabel(verb))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 582, Col: 22}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 589, Col: 31}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var88))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
+ } else {
+ var templ_7745c5c3_Var89 string
+ templ_7745c5c3_Var89, templ_7745c5c3_Err = templ.JoinStringErrs(actionLabel(verb))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 591, Col: 22}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var89))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, " ")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 169, "")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}