Fix: Respect Page-Order in Loading & Memory Eviction (#61, #63, #68)

This commit is contained in:
Youwes09
2026-05-10 02:17:25 -05:00
parent 7b2ae74c02
commit e09ae9d2e7
6 changed files with 320 additions and 110 deletions
+11 -5
View File
@@ -1,7 +1,9 @@
import { store, openReader } from "@store/state.svelte";
import { readerState } from "../store/readerState.svelte";
import { fetchPages } from "./pageLoader";
import { trackingState } from "@features/tracking/store/trackingState.svelte";
import { store } from "@store/state.svelte";
import { readerState } from "../store/readerState.svelte";
import { fetchPages } from "./pageLoader";
import { trackingState } from "@features/tracking/store/trackingState.svelte";
import { cancelQueuedFetches } from "@core/cache/imageCache";
import { clearResolvedUrlCache } from "@core/cache/pageCache";
export function scheduleResumeDismiss() {
setTimeout(() => { readerState.resumeFading = true; }, 1500);
@@ -19,6 +21,10 @@ export async function loadChapter(
abortCtrl.current?.abort();
const ctrl = new AbortController();
abortCtrl.current = ctrl;
cancelQueuedFetches();
if (useBlob) clearResolvedUrlCache();
startAtLastPage.current = false;
markedRead.clear();
readerState.resetForChapter();
@@ -43,7 +49,7 @@ export async function loadChapter(
else if (resumeTo > 1) store.pageNumber = Math.min(resumeTo, urls.length || resumeTo);
readerState.pageReady = true;
readerState.loading = false;
if (adjacent.next) fetchPages(adjacent.next.id, useBlob).catch(() => {});
if (adjacent.next) fetchPages(adjacent.next.id, useBlob, ctrl.signal).catch(() => {});
} catch (e: any) {
if (ctrl.signal.aborted) return;
readerState.error = e instanceof Error ? e.message : String(e);
+30 -29
View File
@@ -25,57 +25,58 @@ export function setupScrollTracking(
onAppend, getStripChapters, getPageUrls, shouldAutoMark,
} = callbacks;
function onScroll() {
let rafId: number | null = null;
function tick() {
rafId = null;
const imgs = containerEl.querySelectorAll<HTMLElement>("img[data-local-page]");
if (!imgs.length) return;
const containerTop = containerEl.getBoundingClientRect().top;
const readLineY = containerTop + containerEl.clientHeight * READ_LINE_PCT;
let activePage: number | null = null;
let activeChId: number | null = null;
for (const img of imgs) {
if (img.getBoundingClientRect().top <= readLineY) {
activePage = Number(img.dataset.localPage);
activeChId = Number(img.dataset.chapter);
} else break;
let lo = 0, hi = imgs.length - 1, best = 0;
while (lo <= hi) {
const mid = (lo + hi) >>> 1;
if (imgs[mid].getBoundingClientRect().top <= readLineY) { best = mid; lo = mid + 1; }
else hi = mid - 1;
}
if (activePage === null) {
activePage = Number(imgs[0].dataset.localPage);
activeChId = Number(imgs[0].dataset.chapter);
}
const active = imgs[best];
const activePage = Number(active.dataset.localPage);
const activeChId = Number(active.dataset.chapter);
if (activePage !== null) onPageChange(activePage);
if (activeChId) onChapterChange(activeChId);
onPageChange(activePage);
if (activeChId) onChapterChange(activeChId);
if (shouldAutoMark() && activePage !== null && activeChId) {
if (shouldAutoMark() && activeChId) {
const chunks = getStripChapters();
const chunk = chunks.find(c => c.chapterId === activeChId);
const total = chunk ? chunk.urls.length : getPageUrls().length;
if (total > 0 && activePage >= total) onMarkRead(activeChId);
const atBottom = containerEl.scrollTop + containerEl.clientHeight >= containerEl.scrollHeight - 40;
if (atBottom) {
const last = chunks[chunks.length - 1];
if (last) onMarkRead(last.chapterId);
}
}
const atBottom = containerEl.scrollTop + containerEl.clientHeight >= containerEl.scrollHeight - 40;
if (atBottom && shouldAutoMark()) {
const chunks = getStripChapters();
const last = chunks[chunks.length - 1];
if (last) onMarkRead(last.chapterId);
}
}
function onScrollAppend() {
const pct = (containerEl.scrollTop + containerEl.clientHeight) / containerEl.scrollHeight;
if (pct >= 0.80) onAppend();
}
containerEl.addEventListener("scroll", onScroll, { passive: true });
containerEl.addEventListener("scroll", onScrollAppend, { passive: true });
function onScroll() {
if (rafId !== null) return;
rafId = requestAnimationFrame(tick);
}
containerEl.addEventListener("scroll", onScroll, { passive: true });
return () => {
containerEl.removeEventListener("scroll", onScroll);
containerEl.removeEventListener("scroll", onScrollAppend);
if (rafId !== null) cancelAnimationFrame(rafId);
};
}
@@ -107,4 +108,4 @@ export function appendNextChapter(
onDone();
})
.catch(() => onDone());
}
}