|
|
|
@@ -4,8 +4,8 @@
|
|
|
|
|
// @version 1.6.0
|
|
|
|
|
// @description Track read progress on Asura, Demonic, Comix & Kagane and sync to a self-hosted backend. Bromite-compatible (no GM_* APIs).
|
|
|
|
|
// @author you
|
|
|
|
|
// @downloadURL https://manga-api.violetcrown.my.id/u/40d79969b5442f90df4fe306a092c7c50e7b4a7a98099f98cc398f4fb374b1df/manga-bookmark.user.js
|
|
|
|
|
// @updateURL https://manga-api.violetcrown.my.id/u/40d79969b5442f90df4fe306a092c7c50e7b4a7a98099f98cc398f4fb374b1df/manga-bookmark.user.js
|
|
|
|
|
// @downloadURL https://bookmark-api.violetcrown.my.id/u/40d79969b5442f90df4fe306a092c7c50e7b4a7a98099f98cc398f4fb374b1df/manga-bookmark.user.js
|
|
|
|
|
// @updateURL https://bookmark-api.violetcrown.my.id/u/40d79969b5442f90df4fe306a092c7c50e7b4a7a98099f98cc398f4fb374b1df/manga-bookmark.user.js
|
|
|
|
|
// @match https://asuracomic.net/*
|
|
|
|
|
// @match https://asurascans.com/*
|
|
|
|
|
// @match https://demonicscans.org/*
|
|
|
|
@@ -21,19 +21,34 @@
|
|
|
|
|
// ============================================================
|
|
|
|
|
// CONFIG — fill these in before installing.
|
|
|
|
|
// ============================================================
|
|
|
|
|
const API_BASE = "https://manga-api.violetcrown.my.id"; // your backend origin, no trailing slash
|
|
|
|
|
const API_BASE = "https://bookmark-api.violetcrown.my.id"; // your backend origin, no trailing slash
|
|
|
|
|
const API_TOKEN = "40d79969b5442f90df4fe306a092c7c50e7b4a7a98099f98cc398f4fb374b1df"; // must equal backend API_TOKEN
|
|
|
|
|
const WEB_BASE = "https://manga.violetcrown.my.id"; // the browser UI, for the panel's nav chips
|
|
|
|
|
const WEB_BASE = "https://bookmark.violetcrown.my.id"; // the browser UI, for the panel's nav chips
|
|
|
|
|
|
|
|
|
|
// This script owns the manga library; the novel script is a separate install
|
|
|
|
|
// with its own prefix, so the two never share a cache, a queue or a panel.
|
|
|
|
|
const STORE_PREFIX = "bmgr:manga:";
|
|
|
|
|
|
|
|
|
|
// Safe in Bromite's isolated world: the page's own JS cannot read these.
|
|
|
|
|
const CACHE_KEY = "mangabm:cache";
|
|
|
|
|
const CACHE_KEY = STORE_PREFIX + "cache";
|
|
|
|
|
|
|
|
|
|
// Per-device record of when each series was last checked for new chapters.
|
|
|
|
|
// Deliberately not synced: each device does its own checking.
|
|
|
|
|
const LASTCHECKED_KEY = "mangabm:lastchecked";
|
|
|
|
|
const LASTCHECKED_KEY = STORE_PREFIX + "lastchecked";
|
|
|
|
|
const LATEST_CHECK_THROTTLE_MS = 4 * 60 * 60 * 1000;
|
|
|
|
|
const LATEST_CHECK_BATCH = 1; // series fetched per navigation
|
|
|
|
|
|
|
|
|
|
// One-time carry-over from the pre-rebrand key names. The cache would rebuild
|
|
|
|
|
// itself from the server, but the retry queue would not: dropping it loses
|
|
|
|
|
// writes made while offline.
|
|
|
|
|
for (const name of ["cache", "lastchecked", "queue", "fabpos"]) {
|
|
|
|
|
const old = localStorage.getItem("mangabm:" + name);
|
|
|
|
|
if (old !== null && localStorage.getItem(STORE_PREFIX + name) === null) {
|
|
|
|
|
localStorage.setItem(STORE_PREFIX + name, old);
|
|
|
|
|
}
|
|
|
|
|
localStorage.removeItem("mangabm:" + name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
// Site adapters
|
|
|
|
|
//
|
|
|
|
@@ -534,13 +549,13 @@
|
|
|
|
|
// A failed write is not rolled back and not lost: the key is parked here and
|
|
|
|
|
// replayed when the backend is next reachable. Entries carry no payload — the
|
|
|
|
|
// body is read from state.byKey at send time, because state.list *is* the
|
|
|
|
|
// desired state and is already persisted in mangabm:cache. One entry per key,
|
|
|
|
|
// desired state and is already persisted under CACHE_KEY. One entry per key,
|
|
|
|
|
// so two writes to the same series cannot replay out of order, an
|
|
|
|
|
// archive-then-unarchive collapses to whatever the cache now says, and a
|
|
|
|
|
// queued DELETE replaces a queued PUT rather than racing it.
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
const QUEUE_KEY = "mangabm:queue";
|
|
|
|
|
const QUEUE_KEY = STORE_PREFIX + "queue";
|
|
|
|
|
const QUEUE_MAX = 200; // ~12 KB; realistically bounded by the bookmark count
|
|
|
|
|
const QUEUE_MAX_ATTEMPTS = 10;
|
|
|
|
|
|
|
|
|
@@ -1075,7 +1090,7 @@
|
|
|
|
|
// FAB placement + dragging (snaps to nearest left/right edge)
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
const FAB_KEY = "mangabm:fabpos";
|
|
|
|
|
const FAB_KEY = STORE_PREFIX + "fabpos";
|
|
|
|
|
const FAB_MARGIN = 12; // vertical breathing room at the top and bottom
|
|
|
|
|
const FAB_EDGE = 0; // horizontal: an edge tab sits flush against the side
|
|
|
|
|
const ARM_MS = 400; // hold this long on the invisible strip to arm a drag
|
|
|
|
@@ -1580,7 +1595,7 @@
|
|
|
|
|
</g>
|
|
|
|
|
</g>
|
|
|
|
|
</svg>
|
|
|
|
|
<span>manga<em>Bookmark</em></span>
|
|
|
|
|
<span>Bookmark<em>Manager</em></span>
|
|
|
|
|
</span>
|
|
|
|
|
<button id="closeBtn" aria-label="Close">close</button>
|
|
|
|
|
</header>
|
|
|
|
|