From c9553f0ffeeeaafb4f340ca9ecd13397fd105f8f Mon Sep 17 00:00:00 2001 From: Abe Jellinek Date: Mon, 11 Sep 2023 13:10:22 -0400 Subject: [PATCH] Fix Find behavior in paginated mode --- src/dom/common/dom-view.tsx | 8 +++++++- src/dom/common/find.ts | 20 ++++++++++++-------- src/dom/common/lib/range.ts | 2 +- src/dom/epub/epub-view.ts | 2 +- src/dom/epub/find.ts | 4 ++-- src/dom/epub/flow.ts | 12 ++++++------ 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/dom/common/dom-view.tsx b/src/dom/common/dom-view.tsx index e1ec67d5..f1872473 100644 --- a/src/dom/common/dom-view.tsx +++ b/src/dom/common/dom-view.tsx @@ -299,8 +299,14 @@ abstract class DOMView { key: a.id, range: this.toDisplayedRange(a.position), })).filter(a => !!a.range) as DisplayedAnnotation[], - ...this._find?.getAnnotations() ?? [] ]; + let findAnnotations = this._find?.getAnnotations(); + if (findAnnotations) { + displayedAnnotations.push(...findAnnotations.map(a => ({ + ...a, + range: a.range.toRange(), + }))); + } if (this._highlightedPosition) { displayedAnnotations.push({ type: 'highlight', diff --git a/src/dom/common/find.ts b/src/dom/common/find.ts index 832beec1..066279c8 100644 --- a/src/dom/common/find.ts +++ b/src/dom/common/find.ts @@ -4,9 +4,11 @@ import { SearchContext } from "./lib/dom-text-search"; import { FindState } from "../../common/types"; +import { PersistentRange } from "./lib/range"; +import EPUBView from "../epub/epub-view"; export interface FindProcessor { - getAnnotations(): DisplayedAnnotation[]; + getAnnotations(): FindAnnotation[]; prev(): FindResult | null; @@ -47,7 +49,8 @@ class DefaultFindProcessor implements FindProcessor { entireWord: this.findState.entireWord } ); - for (let range of ranges) { + for (let originalRange of ranges) { + let range = new PersistentRange(originalRange); let findResult: FindResult = { range, highlight: { @@ -59,7 +62,7 @@ class DefaultFindProcessor implements FindProcessor { } }; if (this._initialPos === null && options.startRange) { - if (range.compareBoundaryPoints(Range.START_TO_START, options.startRange) >= 0) { + if (EPUBView.compareBoundaryPoints(Range.START_TO_START, originalRange, options.startRange) >= 0) { this._initialPos = this._buf.length; } } @@ -135,12 +138,12 @@ class DefaultFindProcessor implements FindProcessor { return this._buf; } - getAnnotations(): DisplayedAnnotation[] { + getAnnotations(): FindAnnotation[] { let selected = (this._pos !== null && this._pos >= 0 && this._pos < this._buf.length) ? this._buf[this._pos] : null; - let highlights: DisplayedAnnotation[] = []; + let highlights: FindAnnotation[] = []; if (this.findState.highlightAll) { for (let result of this._buf) { if (selected === result) { @@ -165,7 +168,6 @@ class DefaultFindProcessor implements FindProcessor { getSnippets(): string[] { return this._buf.map(({ range }) => { - range = range.cloneRange(); let snippet = range.toString(); if (range.startContainer.nodeValue && range.startOffset > 0) { let textBeforeRange = range.startContainer.nodeValue.substring(0, range.startOffset); @@ -205,9 +207,11 @@ class DefaultFindProcessor implements FindProcessor { } } +export type FindAnnotation = Omit & { range: PersistentRange }; + export type FindResult = { - range: Range; - highlight: DisplayedAnnotation; + range: PersistentRange; + highlight: FindAnnotation; } export default DefaultFindProcessor; diff --git a/src/dom/common/lib/range.ts b/src/dom/common/lib/range.ts index d1a297a4..1f28fb5c 100644 --- a/src/dom/common/lib/range.ts +++ b/src/dom/common/lib/range.ts @@ -177,7 +177,7 @@ export function caretPositionFromPoint(doc: Document, x: number, y: number): Car return null; } -export function getStartElement(range: Range): Element | null { +export function getStartElement(range: Range | PersistentRange): Element | null { let startContainer: Node | null = range.startContainer; while (startContainer && startContainer.nodeType !== Node.ELEMENT_NODE) { startContainer = startContainer.parentNode; diff --git a/src/dom/epub/epub-view.ts b/src/dom/epub/epub-view.ts index ba6c3f74..3851c492 100644 --- a/src/dom/epub/epub-view.ts +++ b/src/dom/epub/epub-view.ts @@ -950,7 +950,7 @@ class EPUBView extends DOMView { window.dispatchEvent(new Event('resize')); } - static getContainingSectionIndex(rangeOrNode: Range | Node): number | null { + static getContainingSectionIndex(rangeOrNode: Range | PersistentRange | Node): number | null { let elem; if ('nodeType' in rangeOrNode) { elem = closestElement(rangeOrNode); diff --git a/src/dom/epub/find.ts b/src/dom/epub/find.ts index 9cdea535..c24f50e9 100644 --- a/src/dom/epub/find.ts +++ b/src/dom/epub/find.ts @@ -1,8 +1,8 @@ import DefaultFindProcessor, { + FindAnnotation, FindProcessor, FindResult } from "../common/find"; -import { DisplayedAnnotation } from "../common/components/overlay/annotation-overlay"; import EPUBView from "./epub-view"; import SectionView from "./section-view"; import { FindState } from "../../common/types"; @@ -94,7 +94,7 @@ export class EPUBFindProcessor implements FindProcessor { return null; } - getAnnotations(): DisplayedAnnotation[] { + getAnnotations(): FindAnnotation[] { let highlights = []; for (let [i, processor] of this._processors.entries()) { if (!processor || !this.view.views[i]?.mounted) continue; diff --git a/src/dom/epub/flow.ts b/src/dom/epub/flow.ts index 2acfd6ff..4021f892 100644 --- a/src/dom/epub/flow.ts +++ b/src/dom/epub/flow.ts @@ -21,7 +21,7 @@ export interface Flow { readonly visibleViews: SectionView[]; - scrollIntoView(target: Range | HTMLElement, options?: CustomScrollIntoViewOptions): void; + scrollIntoView(target: Range | PersistentRange | HTMLElement, options?: CustomScrollIntoViewOptions): void; canNavigateToPreviousPage(): boolean; @@ -150,7 +150,7 @@ abstract class AbstractFlow implements Flow { return this._view.views.slice(startIdx, endIdx + 1); } - abstract scrollIntoView(target: Range | HTMLElement, options?: CustomScrollIntoViewOptions): void; + abstract scrollIntoView(target: Range | PersistentRange | HTMLElement, options?: CustomScrollIntoViewOptions): void; abstract canNavigateToNextPage(): boolean; @@ -214,8 +214,8 @@ export class ScrolledFlow extends AbstractFlow { this._iframeDocument.body.classList.remove('flow-mode-scrolled'); } - scrollIntoView(target: Range | HTMLElement, options?: CustomScrollIntoViewOptions): void { - let rect = target.getBoundingClientRect(); + scrollIntoView(target: Range | PersistentRange | HTMLElement, options?: CustomScrollIntoViewOptions): void { + let rect = (target instanceof PersistentRange ? target.toRange() : target).getBoundingClientRect(); if (options?.ifNeeded && (rect.top >= 0 && rect.bottom < this._iframe.clientHeight)) { return; @@ -402,14 +402,14 @@ export class PaginatedFlow extends AbstractFlow { this._onViewUpdate(); } - scrollIntoView(target: Range | HTMLElement, options?: CustomScrollIntoViewOptions): void { + scrollIntoView(target: Range | PersistentRange | HTMLElement, options?: CustomScrollIntoViewOptions): void { let index = EPUBView.getContainingSectionIndex(target); if (index === null) { return; } this.currentSectionIndex = index; // Otherwise, center the target horizontally - let rect = target.getBoundingClientRect(); + let rect = (target instanceof PersistentRange ? target.toRange() : target).getBoundingClientRect(); let x = rect.x + this._sectionsContainer.scrollLeft; if (options?.block === 'center') { x += rect.width / 2;