new_design #1

Merged
mota merged 10 commits from new_design into main 2026-10-29 11:34:20 +00:00
Owner
No description provided.
A pane listing unseen releases from followed podcasts and artists,
behaving like an inbox: items persist until dismissed or played, and the
pane opens from a cache that a background scan refills.

The design is shaped by what the API actually permits. Probing against a
live token found Spotify's own new-releases feed returns a bare 403 to
development-mode apps, so a personalised feed has to be aggregated one
source at a time — which is what makes a scan expensive and forces the
caching and persisted seen-state at the centre of the design.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QH1aUMDE7PbRcG2tYjphAn
`S` lists the podcasts you follow and enter drills into one, mirroring
how the playlist pane behaves: opening a show lists its episodes without
committing you to hearing one.

Reading followed shows needs the user-library-read scope, which older
logins never requested. Rather than refuse to start, the pane fails with
ErrMissingScope and routes to the login screen — the only thing that can
fix it, since a refresh cannot widen a token's scopes.

Episodes reuse the track list, so a show's episodes render and play with
no new code. Two details make that read correctly: an all-podcast list
relabels its columns SHOW and RELEASED, since "artist" and "album" are
not what those hold, and the ᴾ marker is dropped there because the
headings already say so — it earns its place only in a mixed list.

ShowEpisodes takes the whole Show rather than an id: Spotify omits the
show from its own episodes, and passing it avoids a lookup purely to
recover a name the caller already has.

Also fixes a status message that blamed playlists for any missing
permission, and moves the key hints above now-playing so what is
playing is the last thing on screen.

Verified against the live API: 25 episodes requested returns 25 across
three pages, newest first, with the show stamped on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QH1aUMDE7PbRcG2tYjphAn
These tests asserted that the view contained half-block characters, but
built the model with New, which detects the protocol from the
environment. Run from Ghostty, kitty or WezTerm the model drew covers
with the kitty protocol instead — an escape sequence and blank padding
cells, containing no blocks at all — so the assertion could never hold
and the suite failed on a developer's machine while passing in a bare
CI environment.

Pinning half blocks makes the tests deterministic wherever they run.
The real protocols are already covered directly in graphics_test.go,
which builds its input rather than inheriting it.

Verified passing under Ghostty, iTerm, kitty and a bare environment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QH1aUMDE7PbRcG2tYjphAn
mota merged commit 8305ebc829 into main 2026-10-29 11:34:20 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
mota/upnext!1
No description provided.