Add a source picker to search and use the full window width

Search now queries YouTube and SoundCloud together by default and
interleaves the two result lists so neither buries the other; a picker
left of the input narrows it to one source (plus the local library when
configured), and a prefix typed into the query still outranks it.

The panel was capped at 1180px, which left most of a wide screen empty —
it now scales to 1680px and gives the search column the extra room.

A dead link also reported "could not parse yt-dlp's response", which
described our parser rather than the problem; it now shows yt-dlp's own
error line, or says the link did not open.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Leonid Pershin
2026-09-09 00:11:29 +03:00
co-authored by Claude Opus 5
parent f84489e27e
commit 971fd65b1f
8 changed files with 96 additions and 21 deletions
+12 -2
View File
@@ -210,8 +210,18 @@ export async function startApiServer({ manager, context }: ApiServerOptions) {
const { id } = serverParams.parse(request.params);
const session = await requireServerAccess(request, reply, id);
if (!session) return reply;
const { q } = z.object({ q: z.string().min(1) }).parse(request.query);
const tracks = await manager.search(q, { id: session.userId, username: session.username });
const { q, source } = z
.object({
q: z.string().min(1),
source: z.enum(["all", "youtube", "soundcloud", "local"]).default("all"),
})
.parse(request.query);
const tracks = await manager.search(
q,
{ id: session.userId, username: session.username },
undefined,
source,
);
cacheTracks(tracks);
return reply.send({ tracks });
});