fix(cbz): clamp locked cur at chapter end, hide 连读 on flat packs, silent restore, tighten prefetch storage
This commit is contained in:
@@ -22,7 +22,7 @@ function useStoredBool(key: string, def: boolean) {
|
|||||||
function useStoredPrefetch() {
|
function useStoredPrefetch() {
|
||||||
const [n, setN] = useState(() => {
|
const [n, setN] = useState(() => {
|
||||||
const s = localStorage.getItem("cbz-prefetch");
|
const s = localStorage.getItem("cbz-prefetch");
|
||||||
if (s === null) return 2; // 键缺失 ≠ 0:新用户默认 2
|
if (s === null || s === "") return 2; // 键缺失/空串 ≠ 0:新用户默认 2
|
||||||
const v = Number(s);
|
const v = Number(s);
|
||||||
return Number.isInteger(v) && v >= 0 && v <= 3 ? v : 2;
|
return Number.isInteger(v) && v >= 0 && v <= 3 ? v : 2;
|
||||||
});
|
});
|
||||||
@@ -130,7 +130,7 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
|||||||
if (restored.current || !count || !boxRef.current) return;
|
if (restored.current || !count || !boxRef.current) return;
|
||||||
restored.current = true;
|
restored.current = true;
|
||||||
const p = Number(initialLocator?.page);
|
const p = Number(initialLocator?.page);
|
||||||
if (Number.isInteger(p) && p > 0 && p < count) goPage(p, false);
|
if (Number.isInteger(p) && p > 0 && p < count) goPage(p, false, false);
|
||||||
}, [count, initialLocator, ph]);
|
}, [count, initialLocator, ph]);
|
||||||
|
|
||||||
// 跨章跳页:新窗口几何渲染后才能真正滚动(旧窗口 contentH 会把 scrollTop 夹断),故挂 pending 等 [ci] 生效
|
// 跨章跳页:新窗口几何渲染后才能真正滚动(旧窗口 contentH 会把 scrollTop 夹断),故挂 pending 等 [ci] 生效
|
||||||
@@ -154,6 +154,7 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
|||||||
setTop(t);
|
setTop(t);
|
||||||
if (count) {
|
if (count) {
|
||||||
curRef.current = ph.pageAt(t + anchor + vh / 2);
|
curRef.current = ph.pageAt(t + anchor + vh / 2);
|
||||||
|
if (locked) curRef.current = Math.min(curRef.current, w.end - 1); // 末屏中心落在章末卡片/他章 → 钉在本章末页
|
||||||
if (!locked) setCi(chapterIndexAt(chapters, curRef.current)); // 连读/扁平:当前章随滚动走(目录计数高亮)
|
if (!locked) setCi(chapterIndexAt(chapters, curRef.current)); // 连读/扁平:当前章随滚动走(目录计数高亮)
|
||||||
saver.report({ page: curRef.current }, (curRef.current + 1) / count);
|
saver.report({ page: curRef.current }, (curRef.current + 1) / count);
|
||||||
}
|
}
|
||||||
@@ -185,7 +186,8 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const cur = ph.pageAt(top + anchor + vh / 2);
|
const curRaw = ph.pageAt(top + anchor + vh / 2);
|
||||||
|
const cur = locked ? Math.min(curRaw, w.end - 1) : curRaw; // 锁章:视口落在章末卡片上时读数不越章(HUD/滑条/进度)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (toc) activeRow.current?.scrollIntoView({ block: "center" });
|
if (toc) activeRow.current?.scrollIntoView({ block: "center" });
|
||||||
@@ -200,10 +202,10 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 统一定位入口:锁章下目标页在窗外 = 显式切章(滑条/书签/目录/章末卡片/恢复进度皆此一路径)
|
// 统一定位入口:锁章下目标页在窗外 = 显式切章(滑条/书签/目录/章末卡片皆此一路径);恢复进度走 show=false 静默落位
|
||||||
function goPage(i: number, smooth = true) {
|
function goPage(i: number, smooth = true, show = true) {
|
||||||
const t = Math.max(0, Math.min(count - 1, i));
|
const t = Math.max(0, Math.min(count - 1, i));
|
||||||
chrome.show();
|
if (show) chrome.show();
|
||||||
if (locked && (t < w.start || t >= w.end)) {
|
if (locked && (t < w.start || t >= w.end)) {
|
||||||
setCi(chapterIndexAt(chapters, t));
|
setCi(chapterIndexAt(chapters, t));
|
||||||
pending.current = t;
|
pending.current = t;
|
||||||
@@ -253,9 +255,10 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
|||||||
if (el && d !== 0 && topOfI < topY) applyShift(d); // 视口上方页高变化 → 补偿滚动
|
if (el && d !== 0 && topOfI < topY) applyShift(d); // 视口上方页高变化 → 补偿滚动
|
||||||
// 让未量高页的估高收敛到实测页高:同开本漫画量一页后 d≈0,拖拽滚动条不再逐帧打架
|
// 让未量高页的估高收敛到实测页高:同开本漫画量一页后 d≈0,拖拽滚动条不再逐帧打架
|
||||||
if (width > 0 && Math.abs(h - oldEst) / oldEst > 0.03) {
|
if (width > 0 && Math.abs(h - oldEst) / oldEst > 0.03) {
|
||||||
|
const a0 = ph.offset(w.start); // 基线取当前实际 anchor:连续 measure 交错时闭包 anchor 可能过期,防前缀份额双扣
|
||||||
const n = ph.setEst(h, topY);
|
const n = ph.setEst(h, topY);
|
||||||
// n×Δest 是全局位移;锁章下 anchor 同步变了(前缀窗外页),那部分不影响窗口相对几何,须扣减
|
// n×Δest 是全局位移;锁章下窗外前缀页的那部分不影响窗口相对几何,须扣减
|
||||||
const corr = n * (h - oldEst) - (ph.offset(w.start) - anchor);
|
const corr = n * (h - oldEst) - (ph.offset(w.start) - a0);
|
||||||
if (el && corr) applyShift(corr);
|
if (el && corr) applyShift(corr);
|
||||||
ratio.current = h / width;
|
ratio.current = h / width;
|
||||||
}
|
}
|
||||||
@@ -337,6 +340,7 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-1 flex items-center gap-2 pb-1 text-sm">
|
<div className="mt-1 flex items-center gap-2 pb-1 text-sm">
|
||||||
|
{chapters && chapters.length >= 2 && (
|
||||||
<button
|
<button
|
||||||
className={"rd-btn" + (continuous ? " rd-btn-on" : "")}
|
className={"rd-btn" + (continuous ? " rd-btn-on" : "")}
|
||||||
aria-pressed={continuous}
|
aria-pressed={continuous}
|
||||||
@@ -344,6 +348,7 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
|||||||
>
|
>
|
||||||
连读{continuous ? "·开" : "·关"}
|
连读{continuous ? "·开" : "·关"}
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
{locked && (
|
{locked && (
|
||||||
<button
|
<button
|
||||||
className="rd-btn"
|
className="rd-btn"
|
||||||
|
|||||||
Reference in New Issue
Block a user