fix(playlists): an Undo puts a row back after its old neighbour, not at a stale index

A raw index recorded at removal drifted once anything changed before the Undo.
Both lists now read the list fresh and re-insert each row after the row that
preceded it (lib/reinsert). A failed watched toggle in a Plex playlist also
puts the row's state back: its local copy was never re-seeded.
This commit is contained in:
2026-09-27 14:02:15 +02:00
parent b456232d00
commit de62035889
9 changed files with 225 additions and 32 deletions
+39
View File
@@ -0,0 +1,39 @@
/** Where removed rows go back when their Undo comes LATER than the removal.
*
* A raw index recorded at removal time drifts: an add or a reorder landing in between (another tab,
* the rail, the player) shifts everything after it, and the row came back one or more places off
* (E28 review C4). So each removed row goes back right after the row that preceded it in the list
* it was removed from — its neighbour, looked up in the list as it stands NOW — or at the start when
* it was first or no earlier neighbour is left. Rows already back in the list are skipped (the
* server's add is idempotent and would leave them where they are).
*
* @param before the list's ids when the rows were removed, in stored order
* @param removed the ids taken out
* @param now the list's ids at Undo time, in stored order
* @returns the ids to add back and, paired one to one, the index each lands at — ascending, the
* shape the server's insert takes (each index counts the rows put back before it). */
export function reinsertAt(
before: readonly string[],
removed: readonly string[],
now: readonly string[],
): { keys: string[]; positions: number[] } {
const out = new Set(removed);
const list = [...now];
const placed: string[] = [];
for (let i = 0; i < before.length; i++) {
const id = before[i]!;
if (!out.has(id) || now.includes(id)) continue;
let at = 0;
for (let j = i - 1; j >= 0; j--) {
const k = list.indexOf(before[j]!);
if (k >= 0) {
at = k + 1;
break;
}
}
list.splice(at, 0, id);
placed.push(id);
}
const keys = placed.map((id) => ({ id, at: list.indexOf(id) })).sort((a, b) => a.at - b.at);
return { keys: keys.map((k) => k.id), positions: keys.map((k) => k.at) };
}