diff --git a/src/_test/electron/reader-features.integration.js b/src/_test/electron/reader-features.integration.js index 4cc1d30..c7be371 100644 --- a/src/_test/electron/reader-features.integration.js +++ b/src/_test/electron/reader-features.integration.js @@ -1373,7 +1373,7 @@ app.whenReady().then(async () => { return progress && progress.locator && progress.locator.kind === 'epub'; }, 5000); const epubProgress = readerStore.getState(entry.id).progress; - const focalOffsetAfter = await js(epubWin, `(() => { + const focalAfter = await js(epubWin, `(() => { const frame = document.querySelector('.host-epub iframe'); const doc = frame.contentDocument; const outerRect = document.querySelector('.epub-scroll').getBoundingClientRect(); @@ -1387,18 +1387,31 @@ app.whenReady().then(async () => { const range = doc.caretRangeFromPoint(x, y); if (range) caret = { offsetNode: range.startContainer, offset: range.startOffset }; } - if (!caret) return -1; + if (!caret) return { offset: -1, charsPerLine: 0 }; + // 容差要按"一行有多少字"算:字体不同,同样的一行在不同平台字数不同, + // 写死字符数的话换个字体集就会假失败 + let charsPerLine = 0; + const host = caret.offsetNode.parentElement; + if (host && host.textContent) { + const range = doc.createRange(); + range.selectNodeContents(host); + const lines = range.getClientRects().length; + if (lines > 0) charsPerLine = host.textContent.length / lines; + } const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT); let offset = 0; for (let node = walker.nextNode(); node; node = walker.nextNode()) { - if (node === caret.offsetNode) return offset + caret.offset; + if (node === caret.offsetNode) return { offset: offset + caret.offset, charsPerLine }; offset += node.data.length; } - return -1; + return { offset: -1, charsPerLine }; })()`); + const focalOffsetAfter = focalAfter.offset; + // 焦点锚定的语义是"停在原来那行附近",超过一行就说明锚点真的漂了 + const focalTolerance = Math.max(12, Math.ceil(focalAfter.charsPerLine)); check('EPUB 双指缩放保持焦点附近字符偏移', - Math.abs(focalOffsetAfter - pinchResult.anchorOffset) <= 12, - `${pinchResult.anchorOffset} -> ${focalOffsetAfter}; 顶部=${epubProgress.locator.offset}`); + Math.abs(focalOffsetAfter - pinchResult.anchorOffset) <= focalTolerance, + `${pinchResult.anchorOffset} -> ${focalOffsetAfter}; 容差=${focalTolerance}; 顶部=${epubProgress.locator.offset}`); const epubSelection = await selectEpubText(epubWin); await waitForJs(epubWin, `!document.getElementById('selBar').classList.contains('hidden')`);