fix: Reject stale dictionary lookups

The dictionary used a lookup only when the selected words still belonged
to the visible page. If the selection or sentence disappeared while
the page answered, the reader reported the result as unavailable
instead of guessing its language.
This commit is contained in:
Chmouel Boudjnah 2026-10-13 20:32:25 +02:00
parent cc219fb8e2
commit 5bf98ec353
3 changed files with 11 additions and 3 deletions

View file

@ -340,10 +340,10 @@ internal object PageSwaps {
selectionIntersectsAppliedSwap(url, s) {
if (!here(url)) return null;
const selection = window.getSelection();
if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return false;
if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return null;
let at = null;
try { at = locate(s.selector, s.before, s.text); } catch (e) {}
if (!at) return false;
if (!at) return null;
const bounds = new Map();
for (let i = at.start; i <= at.end; i++) {
const node = at.nodes[i];

View file

@ -69,6 +69,8 @@ internal object TranslatedPages {
/** The selected words as the translated page currently shows them. */
@OptIn(ExperimentalReadiumApi::class)
suspend fun selectedText(nav: EpubNavigatorFragment): String? {
val web = visibleWebView(nav.publicationView) ?: return null
val url = web.url ?: return null
val result = try {
withTimeoutOrNull(ANSWER_MS) {
nav.evaluateJavascript(SELECTION_TEXT_SCRIPT)
@ -78,7 +80,7 @@ internal object TranslatedPages {
} catch (_: Exception) {
null
} ?: return null
return decodeSelectionText(result)
return decodeSelectionText(result)?.takeIf { stillShows(nav, web, url) }
}
@OptIn(ExperimentalReadiumApi::class)

View file

@ -78,6 +78,12 @@ class PageSwapsTest {
assertTrue(js.contains("edits.get(node)"))
assertTrue(js.contains("range.compareBoundaryPoints(Range.END_TO_START, changed)"))
assertTrue(js.contains("range.compareBoundaryPoints(Range.START_TO_END, changed)"))
val body = js.substringAfter("selectionIntersectsAppliedSwap(url, s) {")
.substringBefore("markedAt(url, s, fx, fy) {")
assertTrue(
body.contains("if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return null;"),
)
assertTrue(body.contains("if (!at) return null;"))
}
@Test