Preload the next page in page mode
This commit is contained in:
+2
-1
@@ -45,7 +45,8 @@ mobile draft at 390px.
|
||||
number / total / Next, persists the page in localStorage, and scrolls to the next page one at
|
||||
a time with a 2 s cooldown after each load. Same filter + page is stable while the archive is
|
||||
unchanged. Infinite mode keeps the stream buffer; prefetch, buffer fill, and the buffer are
|
||||
disabled in page mode.
|
||||
disabled in page mode. Page mode pre-loads the next page's JSON and preview images, so
|
||||
jumping one page renders instantly.
|
||||
- [x] C56 Recovery completed. First run after the C55 fix recovered 1,117 of 1,240 Discord-CDN
|
||||
previews (90%); the last 123 were confirmed genuinely gone (refresh + direct fetch and `/stream`
|
||||
both fail) and are marked `unavailable after recovery` so later runs skip them. The recovery
|
||||
|
||||
+50
-10
@@ -36,6 +36,7 @@
|
||||
pageMode: localStorage.getItem("vk-media-page-mode") === "page" ? "page" : "infinite",
|
||||
page: Math.max(1, Number(localStorage.getItem("vk-media-page")) || 1),
|
||||
pageCooldownUntil: 0,
|
||||
pagePrefetch: null,
|
||||
draft: null,
|
||||
prefetched: null,
|
||||
prefetchPromise: null,
|
||||
@@ -414,9 +415,17 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const items = await window.VK.api.get(
|
||||
const prefetched =
|
||||
reset && state.pageMode === "page" && state.pagePrefetch?.page === state.page
|
||||
? state.pagePrefetch
|
||||
: null;
|
||||
if (prefetched) state.pagePrefetch = null;
|
||||
|
||||
const items =
|
||||
prefetched?.items ??
|
||||
(await window.VK.api.get(
|
||||
`/api/media?limit=${state.pageSize}&offset=${state.offset}&${filterQuery()}`
|
||||
);
|
||||
));
|
||||
|
||||
if (reset) {
|
||||
for (const item of items) state.itemKeys.add(`${item.scrapeId}:${item.itemId}`);
|
||||
@@ -442,13 +451,44 @@
|
||||
} else {
|
||||
state.pageCooldownUntil = Date.now() + 2000;
|
||||
renderToolbar();
|
||||
void prefetchNext();
|
||||
}
|
||||
}
|
||||
|
||||
/** Warm the next page's JSON and preview images before the user reaches them. */
|
||||
function warmImages(items) {
|
||||
for (const item of items) {
|
||||
const src = item.thumbUrl || item.localUrl;
|
||||
if (!src) continue;
|
||||
const image = new Image();
|
||||
image.src = src;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Warm the next slice in both modes. Infinite appends it when the user reaches the bottom;
|
||||
* page mode keeps it ready so jumping one page renders instantly with its previews cached.
|
||||
*/
|
||||
async function prefetchNext() {
|
||||
if (state.pageMode !== "infinite") return;
|
||||
if (!state.loaded || !state.more || state.prefetched || state.prefetchPromise || state.loading) return;
|
||||
if (!state.loaded || state.loading) return;
|
||||
|
||||
if (state.pageMode === "page") {
|
||||
const page = state.page + 1;
|
||||
if (!hasNextPage() || state.pagePrefetch?.page === page) return;
|
||||
|
||||
try {
|
||||
const items = await window.VK.api.get(
|
||||
`/api/media?limit=${state.pageSize}&offset=${(page - 1) * state.pageSize}&${filterQuery()}`
|
||||
);
|
||||
state.pagePrefetch = { page, items };
|
||||
warmImages(items);
|
||||
} catch {
|
||||
// best effort
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.more || state.prefetched || state.prefetchPromise) return;
|
||||
|
||||
state.prefetchPromise = window.VK.api
|
||||
.get(`/api/media?limit=${state.pageSize}&offset=${state.offset}&${filterQuery()}`)
|
||||
@@ -459,12 +499,7 @@
|
||||
}
|
||||
|
||||
state.prefetched = items;
|
||||
for (const item of items) {
|
||||
const src = item.thumbUrl || item.localUrl;
|
||||
if (!src) continue;
|
||||
const image = new Image();
|
||||
image.src = src;
|
||||
}
|
||||
warmImages(items);
|
||||
})
|
||||
.catch(() => {
|
||||
// Preloading is best effort; the scroll handler falls back to a request.
|
||||
@@ -564,6 +599,7 @@
|
||||
function setPageMode(mode) {
|
||||
if (state.pageMode === mode) return;
|
||||
state.pageMode = mode;
|
||||
state.pagePrefetch = null;
|
||||
localStorage.setItem("vk-media-page-mode", mode);
|
||||
state.prefetched = null;
|
||||
state.page = 1;
|
||||
@@ -573,6 +609,7 @@
|
||||
}
|
||||
|
||||
function gotoPage(page) {
|
||||
state.pagePrefetch = null;
|
||||
const count = pageCount();
|
||||
const wanted = Math.max(1, Math.round(Number(page) || 1));
|
||||
state.page = count ? Math.min(count, wanted) : wanted;
|
||||
@@ -1476,6 +1513,7 @@
|
||||
|
||||
function applyDraft() {
|
||||
state.page = 1;
|
||||
state.pagePrefetch = null;
|
||||
savePage();
|
||||
state.kind = state.draft.kind;
|
||||
state.filters = {
|
||||
@@ -1996,6 +2034,7 @@
|
||||
state.more = false;
|
||||
state.page = 1;
|
||||
state.pageCooldownUntil = 0;
|
||||
state.pagePrefetch = null;
|
||||
savePage();
|
||||
state.prefetched = null;
|
||||
state.items = [];
|
||||
@@ -2042,6 +2081,7 @@
|
||||
overlay.querySelector("#media-close").addEventListener("click", hide);
|
||||
overlay.querySelector("#media-refresh").addEventListener("click", () => {
|
||||
state.completed.clear();
|
||||
state.pagePrefetch = null;
|
||||
void loadScrapes();
|
||||
if (state.view === "media") void loadMedia(true);
|
||||
if (state.view === "bot") {
|
||||
|
||||
Reference in New Issue
Block a user