Merge branch 'main' into exp/orbit (pre-PR sync)

Conflicts resolved in:
- src/pages/SearchResults.tsx
- src/pages/AdvancedSearch.tsx

Both pages were rewritten on main (PR #303) to use the shared
<SongRow> component with click-to-enqueueAndPlay semantics. Orbit's
playSong helper that branched on orbit-active is no longer needed
at the page level — instead, orbit awareness moved INTO SongRow and
SongCard themselves: in an active orbit session both buttons collapse
into addTrackToOrbit (suggest for guests, host-enqueue for the host)
so we don't ship a queue replacement to every guest.

Also kept main's IntersectionObserver-based pagination on both pages.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Psychotoxical
2026-04-25 16:34:38 +02:00
28 changed files with 1760 additions and 215 deletions
+17
View File
@@ -926,6 +926,23 @@ export async function search(query: string, options?: { albumCount?: number; art
return { artists: r.artist ?? [], albums: r.album ?? [], songs: r.song ?? [] };
}
/**
* Song-only paginated search3. Tolerates empty query — Navidrome returns all songs
* ordered by title in that case; strict Subsonic implementations may return nothing.
* Caller handles empty results gracefully (Tracks page falls back to its random pool).
*/
export async function searchSongsPaged(query: string, songCount: number, songOffset: number): Promise<SubsonicSong[]> {
const data = await api<{ searchResult3: { song?: SubsonicSong[] } }>('search3.view', {
query,
artistCount: 0,
albumCount: 0,
songCount,
songOffset,
...libraryFilterParams(),
});
return data.searchResult3?.song ?? [];
}
export async function setRating(id: string, rating: number): Promise<void> {
await api('setRating.view', { id, rating });
}