fix(reader): popover dismiss on PDF taps; notes save on create; colors don't close editor

- The in-book pointerdown dismiss listener lived in the reflowable-only
  block, so PDF taps never closed the selection popover — hoist it so
  every content doc (EPUB, PDF, comics) dismisses on tap.
- createHighlight hardcoded note_text: '' — 'Highlight with note' saved
  the highlight but silently dropped the note. Send p.note (and pass it
  to the EPUB overlayer).
- saveHighlightChanges collapsed the note editor on every save; color
  dots in create mode created a highlight outright. With the editor
  open, color dots now just recolor (create) or recolor-and-save with
  the editor kept open (edit).
This commit is contained in:
John O'Keefe
2026-09-17 10:55:21 -04:00
parent 960305dfa9
commit d8179bb066
3 changed files with 39 additions and 29 deletions
+23 -19
View File
@@ -730,6 +730,20 @@ document.addEventListener("alpine:init", () => {
this.scheduleSelectionPopover(doc, index);
});
}
// Clicks in the book dismiss the popover in ANY mode and for ANY
// content doc (EPUB sections and fixed-layout pages alike): iframe
// events never bubble to the host document (so the host
// outside-click dismiss never sees them). Clicking a painted
// highlight still works: this hides, then foliate's
// show-annotation re-opens it in edit mode.
doc.addEventListener(
"pointerdown",
() => {
if (this.selectionPopover.open)
this.hideSelectionPopover();
},
{ passive: true },
);
// Text selection → highlight popover (reflowable EPUB only;
// fixed-layout highlight overlays are a later milestone).
if (!this.isFixedLayout) {
@@ -759,21 +773,6 @@ document.addEventListener("alpine:init", () => {
(e: PointerEvent) => setTimeout(() => checkSelection(e), 0),
{ passive: true },
);
// Clicks in the book dismiss the popover in ANY mode: iframe
// events never bubble to the host document (so the host
// outside-click dismiss never sees them), and the collapsed
// check above only covers create mode — edit mode had no
// outside-click path at all, leaving Esc as the only way out.
// Clicking a painted highlight still works: this hides, then
// foliate's show-annotation re-opens it in edit mode.
doc.addEventListener(
"pointerdown",
() => {
if (this.selectionPopover.open)
this.hideSelectionPopover();
},
{ passive: true },
);
doc.addEventListener(
"keyup",
(ev: KeyboardEvent) => {
@@ -1627,6 +1626,9 @@ document.addEventListener("alpine:init", () => {
const p = this.selectionPopover;
const token = getToken();
if (!token || !this.mediaItemId || (!p.cfi && p.pdfPage < 0)) return;
// The note editor writes into p.note live; "Highlight with note"
// creates the highlight AND its note in one POST.
const note = p.note.trim();
const pdfAnchor =
p.pdfPage >= 0
? JSON.stringify({ v: 1, page: p.pdfPage, rects: p.pdfRects })
@@ -1647,7 +1649,7 @@ document.addEventListener("alpine:init", () => {
epubcfi_start: p.pdfPage >= 0 ? pdfAnchor : p.cfi,
epubcfi_end: p.pdfPage >= 0 ? pdfAnchor : p.cfiEnd,
color,
note_text: "",
note_text: note,
percentage_start: this.lastRelocateDetail?.fraction ?? 0,
}),
},
@@ -1676,7 +1678,7 @@ document.addEventListener("alpine:init", () => {
? ""
: this.toRangeCfi(p.cfi, p.cfiEnd, p.text) || p.cfi,
color,
note: "",
note,
id: row.id,
});
// Clear the DOM selection: the gesture is consumed, and it is
@@ -1692,7 +1694,7 @@ document.addEventListener("alpine:init", () => {
/* ignore highlight errors */
}
},
async saveHighlightChanges() {
async saveHighlightChanges(keepNoteOpen = false) {
const p = this.selectionPopover;
const token = getToken();
if (!token || !this.mediaItemId || !p.id) return;
@@ -1756,7 +1758,9 @@ document.addEventListener("alpine:init", () => {
id: p.id,
});
}
p.noteOpen = false;
// Color tweaks made while the note editor is open keep the
// editor open — only the explicit save/close paths collapse it.
if (!keepNoteOpen) p.noteOpen = false;
} catch (_e) {
/* ignore highlight errors */
}