fix(cbz): attach resize observer via callback ref + drop vh from scroll-mode geometry deps — fixes constant per-page gaps and refetch storm on mobile
This commit is contained in:
@@ -38,6 +38,9 @@ The format loosely follows Keep a Changelog and can be adapted to the team's hab
|
||||
|
||||
### Fixed / 修复
|
||||
|
||||
- Comic continuous-scroll mode is contiguous again on phones: the size observer used to miss the scroll container (it was attached while the reader still showed "loading", so the box didn't exist), leaving page geometry computed from a stale 480px default width while pages rendered at the real (e.g. 390px) width — every page gained a constant dead gap. The observer now attaches when the box actually mounts; additionally, mobile address-bar show/hide no longer rebuilds the scroll geometry in continuous/whole-page modes, which used to wipe measured page heights and re-trigger a burst of image requests.
|
||||
- 手机端漫画「连读」模式页面不再上下脱节:尺寸监听器此前在阅读器还在「加载中」时就尝试挂载(滚动容器尚不存在),导致监听从未生效,页高按过时的 480px 默认宽计算而实际按手机真实宽度(如 390px)渲染,每页之间出现恒定空白断层;现改为容器真正挂载时再接管。另外,手机地址栏收展在连读/整页模式下不再重建滚动几何——此前会清空全部实测页高并引发一波图片重复请求。
|
||||
|
||||
- Dragging the comic scrollbar (or the page slider) is no longer gritty: scroll handling is coalesced to one update per frame instead of per event, prefetching waits until scrolling settles instead of firing mid-drag, height corrections are batched per frame, the virtual list re-estimates unseen pages from the first measured page size (scrollbar geometry stops morphing under your finger), and slider seeks land instantly instead of restarting a smooth-scroll animation per notch.
|
||||
- 漫画拖动滚动条(及页码滑条)不再发涩:滚动改为每帧合并处理而非逐事件响应,预取等滚动停稳再发(不再拖拽途中抢带宽),量高补偿按帧合并,虚拟列表用首个实测页高重估所有未加载页(滚动条几何不再拖拽中变形),滑条寻址即时落位(不再每格重启一段平滑动画)。
|
||||
- .txt/.md files encoded in GBK/GB2312/GB18030 or UTF-16 (typical web-novel exports) no longer render as mojibake: the reader strictly tries UTF-8 first and falls back to GB18030, recognizing UTF-16 by BOM.
|
||||
|
||||
@@ -106,22 +106,26 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
||||
const [mode, setMode] = useStoredMode();
|
||||
const fitH = mode === "fit";
|
||||
|
||||
// vh 只在适高模式参与几何;滚动模式里地址栏收展改 vh 不得重建(会丢全部实测页高→页间错位+重挂图请求风暴)
|
||||
const ph = useMemo(
|
||||
() => new PageHeights(count, fitH ? vh : width * ratio.current),
|
||||
[count, width, vh, fitH],
|
||||
[count, width, fitH ? vh : 0],
|
||||
);
|
||||
|
||||
// 容器尺寸自适应(尺寸变化后重建 PageHeights,阅读位置以当前滚动值为准)
|
||||
useEffect(() => {
|
||||
const el = boxRef.current;
|
||||
// 容器尺寸自适应:回调 ref 在滚动盒真正挂载时才观测(等页数请求期间的早退渲染里没有这个节点)
|
||||
const roRef = useRef<ResizeObserver | null>(null);
|
||||
function attachBox(el: HTMLDivElement | null) {
|
||||
boxRef.current = el;
|
||||
roRef.current?.disconnect();
|
||||
roRef.current = null;
|
||||
if (!el) return;
|
||||
const ro = new ResizeObserver(() => {
|
||||
setWidth(Math.min(el.clientWidth, MAX_W));
|
||||
setVh(el.clientHeight);
|
||||
});
|
||||
ro.observe(el);
|
||||
return () => ro.disconnect();
|
||||
}, []);
|
||||
roRef.current = ro;
|
||||
}
|
||||
|
||||
// 首次拿到 count 后恢复进度页
|
||||
useEffect(() => {
|
||||
@@ -222,7 +226,7 @@ export default function CbzReader({ book, initialLocator, initialPercent, chrome
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={boxRef}
|
||||
ref={attachBox}
|
||||
onScroll={onScroll}
|
||||
onClick={onZoneClick}
|
||||
className={"h-full overflow-y-auto" + (mode !== "scroll" ? " snap-y snap-proximity" : "")}
|
||||
|
||||
Reference in New Issue
Block a user