diff --git a/web/src/reader/reader.ts b/web/src/reader/reader.ts index 71598df..805e99b 100644 --- a/web/src/reader/reader.ts +++ b/web/src/reader/reader.ts @@ -826,7 +826,13 @@ document.addEventListener("alpine:init", () => { }); this.view.addEventListener("show-annotation", (e: any) => { const { value, index, range } = e.detail; - const h = this.highlightItems.find((x) => x.cfi === value); + // Device-synced highlights are painted with a synthesized range + // CFI (renderCfi) while the stored locator stays a point CFI, so a + // click reports the render value — match either or editing + // device highlights is impossible. + const h = this.highlightItems.find( + (x) => x.cfi === value || x.renderCfi === value, + ); if (!h) return; const doc = this.renderer ?.getContents?.() @@ -1343,7 +1349,23 @@ document.addEventListener("alpine:init", () => { if (!resp.ok) return; const row = await resp.json(); const idx = this.highlightItems.findIndex((h) => h.id === p.id); + // The overlay is keyed by the value it was added with; an edit can + // change it (note/text edits change the synthesized range), so + // remove the old paint before re-adding or it ghosts. + const oldValue = + idx !== -1 + ? this.highlightItems[idx].renderCfi || + this.highlightItems[idx].cfi + : ""; if (idx !== -1) this.highlightItems[idx] = this.mapHighlightRow(row); + const newValue = + idx !== -1 + ? this.highlightItems[idx].renderCfi || + this.highlightItems[idx].cfi + : ""; + if (p.pdfPage < 0 && oldValue && oldValue !== newValue) { + this.view?.deleteAnnotation({ value: oldValue }); + } // Re-add so the overlay redraws with the new color. if (p.pdfPage >= 0) { this.renderer?.addRectAnnotation?.({ @@ -1379,7 +1401,11 @@ document.addEventListener("alpine:init", () => { if (hl?.pdfPage >= 0) { this.renderer?.removeRectAnnotation?.(id); } else if (hl?.cfi) { - this.view?.deleteAnnotation({ value: hl.cfi }); + // Delete with the value the overlay was added by: device-synced + // highlights paint a synthesized range, not the stored point CFI. + this.view?.deleteAnnotation({ + value: hl.renderCfi || hl.cfi, + }); } this.hideSelectionPopover(); } catch (_e) {