fix(plex): a Plex reorder the server accepted is the order the cache holds

The YouTube list got this rule in round 5 — one accepted write, one cache entry
that matches it — and the Plex list got only the rollback half of that fix. Its
success path invalidated `qk.plexPlaylists()`, a disjoint key root, and never
touched `qk.plexPlaylist(id)`: the key `putBack` rolls back to, and the one a
re-entry renders from without refetching.

So after an accepted drag the detail cache still held the pre-reorder order.
Leaving the playlist and coming back inside the 30 s staleTime showed the
reorder undone, and the next drag from there persisted that — silently undoing
an order the server had taken. Measured in jsdom: server 2,1,3, cache 1,2,3, no
refetch.

1 test, mutation-checked.
This commit is contained in:
2026-09-12 05:50:40 +02:00
parent a0114deff1
commit 3eb0f41962
2 changed files with 102 additions and 1 deletions
+12 -1
View File
@@ -427,7 +427,18 @@ export default function PlexPlaylistView({
playlistId,
next.map((i) => i.id),
)
.then(() => qc.invalidateQueries({ queryKey: qk.plexPlaylists() }))
.then(() => {
// Write the accepted order into the DETAIL cache, not just the list. That cache is what
// `putBack` rolls back to and what a re-entry inside the 30 s staleTime renders without
// refetching — so after an accepted reorder it showed the pre-reorder order again, and the
// next drag from there persisted it, silently undoing the one the server took. The
// YouTube sibling (`Playlists.tsx`) got this in round 5; this half was left behind (round
// 6). One accepted write, one cache entry that matches it.
qc.setQueryData<{ items: PlexCard[] }>(qk.plexPlaylist(playlistId), (old) =>
old ? { ...old, items: next } : old,
);
qc.invalidateQueries({ queryKey: qk.plexPlaylists() });
})
.catch((e: unknown) => {
notifyActionError(e, t("plex.playlist.reorderFailed"));
putBack();