@@ -157,6 +157,12 @@ uses librespot:
157157 - ` ensure_track_available() ` uses librespot's ` AudioItem ` availability to fail
158158 a single unplayable track at resolve time, so ` resolve_url_with_startup `
159159 surfaces the "track unavailable" modal instead of playing silence
160+ - ` src/spotify/search.rs ` — catalog search via the public Web API (` /v1/search ` ),
161+ authorized with a bearer token minted from the librespot session
162+ (` session.token_provider().get_token(...) ` — comma-separated scopes string).
163+ Returns ` SearchResults { tracks, albums, playlists } ` of ` SearchItem ` s whose
164+ ` uri ` is a valid ` resolve() ` target. Playlist ` items ` can contain literal
165+ ` null ` s (post-2024 API changes) — the parser filters them.
160166- ` src/spotify/sink.rs ` — the bridge. librespot's ` Player ` pushes decoded PCM
161167 into a custom ` Sink ` ; a bounded channel carries it to a rodio ` Source ` . The
162168 sink blocks under backpressure (throttling the decoder to real time); the
@@ -200,6 +206,13 @@ There are now two major UI modes:
200206- "track unavailable" modal (` draw_replay_error ` ) — non-fatal overlay shown when
201207 a replay target can't be resolved; ` d ` prunes the dead row, any other key
202208 returns to the history browser.
209+ - Spotify search overlay (` / ` from playback or the history browser;
210+ ` draw_search_overlay ` ). Query focus: type, Enter searches (one blocking Web
211+ API call; a "searching…" frame is drawn first), Esc closes. Results focus:
212+ ` j ` /` k ` move (headers are skipped), ` gg ` /` G ` jump, ` / ` re-edits the query,
213+ Enter plays the selection through the normal replay rail
214+ (` LoopAction::ReplayTarget ` in playback; ` play_file_session ` in the history
215+ browser). While open the overlay captures all keys; only Ctrl-C quits.
203216
204217### Playlist behavior
205218
0 commit comments