From 6eb29902b1715f879fd2090f059c26a41ef0524e Mon Sep 17 00:00:00 2001 From: Sulthan Zaki Date: Mon, 27 Jul 2026 17:13:58 +0700 Subject: [PATCH] feat(userscript): keep pending writes over a refreshed list --- userscript/manga-bookmark.user.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/userscript/manga-bookmark.user.js b/userscript/manga-bookmark.user.js index fb0c8dd..fc5c498 100644 --- a/userscript/manga-bookmark.user.js +++ b/userscript/manga-bookmark.user.js @@ -465,6 +465,27 @@ render(); } + // Keys the server has not heard about yet must survive a fetched list, or the + // card the user just changed silently flaps back — the exact bug this queue + // exists to fix. Reads state.byKey, so it must run *before* setList replaces + // it. + function overlayPending(list) { + if (queue.length === 0) return list; + const out = list.filter((b) => { + const e = queueGet(b.key); + return !(e && e.op === "delete"); + }); + for (const e of queue) { + if (e.op !== "put") continue; + const local = state.byKey[e.key]; + if (!local) continue; + const i = out.findIndex((b) => b.key === e.key); + if (i >= 0) out[i] = local; + else out.push(local); + } + return out; + } + // ============================================================ // Mutations (optimistic: update UI/cache first, then sync) // ============================================================ @@ -1025,9 +1046,10 @@ // ============================================================ async function refresh() { + await drain(); // push what we owe before adopting the server's view of it try { const list = await apiGet(); - setList(list); + setList(overlayPending(list)); render(); } catch (e) { render(); // fall back to cache