From 1e65c3b413b1bc4fc4999218dcd698c67ed12fa0 Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 9 Jun 2026 22:17:00 +0200 Subject: [PATCH] fix(web): show paste box to any connected user, not only on an empty feed hasConnected was computed only inside the buckets.empty() branch (it was added for the empty-state copy), so a connected user WITH videos got hasConnected=false and never saw the paste box (#2-regression of the v0.12.0 paste UI). Compute it on every list render. Test: connected user with a non-empty feed sees the box. Co-Authored-By: Claude Opus 4.8 (1M context) --- internal/web/handlers.go | 22 ++++++++++------------ internal/web/paste_handler_test.go | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/internal/web/handlers.go b/internal/web/handlers.go index 95c4549..5bfaee5 100644 --- a/internal/web/handlers.go +++ b/internal/web/handlers.go @@ -211,19 +211,17 @@ func (a *App) handleList(w http.ResponseWriter, r *http.Request) { rows := f.apply(allRows) buckets := bucketRows(rows, a.recencyCutoff()) - // hasConnected drives the empty state: a fresh account with a connection but - // no discovery pass yet has zero rows, and we want it to read "connected, - // summaries land gradually" rather than "nothing here". Only needed when the - // list is empty. - hasConnected := false - if buckets.empty() { - conns, err := a.Store.ConnectionsForUser(r.Context(), userID) - if err != nil { - a.serverError(w, r, "connections for user", err) - return - } - hasConnected = len(conns) > 0 + // 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"). + // Computed every render — not only when empty — so a user with videos still + // gets the paste box. + conns, err := a.Store.ConnectionsForUser(r.Context(), userID) + if err != nil { + a.serverError(w, r, "connections for user", err) + return } + hasConnected := len(conns) > 0 if isHTMX(r) { a.render(w, r, summaryList(buckets, hasConnected)) diff --git a/internal/web/paste_handler_test.go b/internal/web/paste_handler_test.go index 4702078..73f35fe 100644 --- a/internal/web/paste_handler_test.go +++ b/internal/web/paste_handler_test.go @@ -7,6 +7,7 @@ import ( "net/url" "strings" "testing" + "time" "github.com/stretchr/testify/require" @@ -111,3 +112,23 @@ func TestPasteDedupNoDuplicate(t *testing.T) { userID).Scan(&count)) require.Equal(t, 1, count, "pasting the same video twice must not duplicate the row") } + +func TestListShowsPasteFormForConnectedUserWithVideos(t *testing.T) { + app := newApp(t) + resetDB(t, rawPool(t)) + app.Fetcher = &fakeFetcher{title: "x"} + p := rawPool(t) + + // Connected user with a non-empty feed (the case the bug missed: hasConnected + // was only computed for an empty feed). + _, err := p.Exec(context.Background(), + `INSERT INTO video_connections (user_id, provider, token_ref, status) + VALUES ($1, 'youtube', 'youtube/x/refresh_token', 'active')`, userID) + require.NoError(t, err) + seedVideo(t, p, "11111111-1111-1111-1111-111111111111", "A talk", "https://youtu.be/aaaaaaaaaaa", time.Now()) + + rec := do(t, app, httptest.NewRequest(http.MethodGet, "/", nil)) + require.Equal(t, http.StatusOK, rec.Code) + require.Contains(t, body(t, rec), `action="/paste"`, + "a connected user must see the paste box even when the feed has videos") +}