refactor(playlists): #411 R2 — generic registry-driven system endpoints
Replaces the per-kind refresh/shuffle handlers with one generic
pair driven off the kind registry, in lockstep across both clients.
Server:
- systemPlaylistKind gains Singleton; RefreshableSystemKind(key)
exported. for_you/discover singleton; songs_like_artist not.
- New generic POST /api/playlists/system/{kind}/refresh and
GET /api/playlists/system/{kind}/shuffle ({kind} = raw
system_variant). Non-singleton/unknown kind → 404. Deleted
playlists_{foryou,discover}_refresh.go and the per-kind shuffle
wrappers; serveSystemPlaylistShuffle core kept.
- playlistRowView.refreshable: server-derived flag so clients show
the refresh affordance generically without hardcoding kinds.
Web (not drift-cached → uses the server flag):
- refreshSystem(variant) replaces refreshForYou/refreshDiscover;
systemShuffle drops the for_you→for-you mapping (raw variant).
- PlaylistCard + detail page gate the kebab/Refresh button on
playlist.refreshable; label is "Refresh {name}". Tests reworked;
obsolete refresh-foryou/discover api tests deleted.
Flutter (list tiles are drift-cache-sourced → derive, no migration):
- Playlist.refreshable getter = isSystem && variant !=
songs_like_artist (holds for all current + planned kinds).
- refreshSystem/systemShuffle use the raw variant; PlaylistCard +
detail screen gate kebab/Regenerate/source-tagging on refreshable
so songs_like_artist plays via get() (no by-kind endpoint).
Pure-plumbing refactor; CI verifies parity. Next (R3): the five
discovery mixes — each a candidate query + one registry entry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,7 +32,12 @@ type playlistRowView struct {
|
||||
IsPublic bool `json:"is_public"`
|
||||
Kind string `json:"kind"`
|
||||
SystemVariant *string `json:"system_variant,omitempty"`
|
||||
SeedArtistID *string `json:"seed_artist_id,omitempty"`
|
||||
// Refreshable: a singleton system kind addressable by the generic
|
||||
// /system/{kind}/{refresh,shuffle} endpoints. Lets clients show
|
||||
// the per-tile refresh affordance generically without hardcoding
|
||||
// which kinds support it (false for user + songs_like_artist).
|
||||
Refreshable bool `json:"refreshable"`
|
||||
SeedArtistID *string `json:"seed_artist_id,omitempty"`
|
||||
CoverURL string `json:"cover_url,omitempty"`
|
||||
TrackCount int32 `json:"track_count"`
|
||||
DurationSec int32 `json:"duration_sec"`
|
||||
@@ -435,6 +440,7 @@ func playlistRowToView(r *playlists.PlaylistRow) playlistRowView {
|
||||
IsPublic: r.IsPublic,
|
||||
Kind: r.Kind,
|
||||
SystemVariant: r.SystemVariant,
|
||||
Refreshable: r.SystemVariant != nil && playlists.RefreshableSystemKind(*r.SystemVariant),
|
||||
TrackCount: r.TrackCount,
|
||||
DurationSec: r.DurationSec,
|
||||
CreatedAt: formatTimestamp(r.CreatedAt),
|
||||
|
||||
Reference in New Issue
Block a user