feat(plex): a Surprise reshuffle deals the previous draw last

The rail draws three unseen titles per kind under the sidebar filters; on a
small filtered pool every reshuffle dealt the same few again. The redraw now
sends the draw on screen (exclude=), the server deals the rest of the pool
first and tops up from the excluded titles only when the pool is short, so a
small pool still fills the rail. (The two discover.py baseline entries went
with the rewritten draw.)
This commit is contained in:
2026-10-09 00:06:11 +02:00
parent 6dd82ef5e2
commit 5f42ff61c8
6 changed files with 82 additions and 51 deletions
@@ -218,6 +218,9 @@ describe("PlexDiscover", () => {
fireEvent.click(screen.getByRole("button", { name: "plex.discover.reshuffle" }));
await waitFor(() => expect(plexSurprise).toHaveBeenCalledTimes(2));
expect(plexDiscover).toHaveBeenCalledTimes(1); // the whole surface was NOT refetched
// The first draw asks for anything; the redraw hands over the one on screen to deal it last.
expect(plexSurprise.mock.calls[0]?.[4]).toEqual([]);
expect(plexSurprise.mock.calls[1]?.[4]).toEqual(["sp1"]);
});
it("shows the empty message when every rail is empty", async () => {
+13 -2
View File
@@ -119,9 +119,20 @@ export default function PlexDiscover({
queryFn: () => api.plexDiscover(scope, lang, filters),
});
// Surprise-me is its own query so the ↻ button can redraw it without refetching the whole surface.
// A redraw hands over the draw on screen, so a small filtered pool deals its other titles first.
const surpriseKey = qk.plexSurprise(scope, lang, filters);
const surpriseQ = useQuery({
queryKey: qk.plexSurprise(scope, lang, filters),
queryFn: () => api.plexSurprise(scope, undefined, filters, lang),
queryKey: surpriseKey,
queryFn: () => {
const shown = qc.getQueryData<{ items: PlexCard[] }>(surpriseKey)?.items ?? [];
return api.plexSurprise(
scope,
undefined,
filters,
lang,
shown.map((c) => c.id),
);
},
staleTime: 0,
});