mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
04ec495c25
* feat(reader): add PDF highlights and annotations Persist and render PDF highlights through the same annotation system as EPUB. The annotation_positions table already supported a 'pdf' format, so this wires the web create path, response, and reader UI to it. Backend: - create-annotation DTO accepts a pdf position (page + segment rects) as an alternative to a cfi; exactly one is required - repository createPdf() persists a format='pdf' position (geometry in pos0, pageno in extras); selectWithCfi exposes the pdf geometry and status - response DTO parses the pdf position and derives positionStatus Frontend (pdf-v4 reader): - usePdfAnnotations REST store and usePdfHighlights orchestration render persisted highlights via the EmbedPDF annotation plugin (autoCommit off, DB stays source of truth) - selection popup (colour/style/note/copy/delete), note dialog, and a Highlights sidebar tab with search/colour/notes filters, navigate, delete - NoteDialog relocated to reader/shared for reuse by both readers Shared types gain AnnotationRect/AnnotationPdfPosition and an optional pdf field on AnnotationItem. * fix(reader): preserve input on failed PDF annotation save; convert mixed PDF+CFI for KOReader - usePdfHighlights: createFromSelection/restyleExisting now return success; applyHighlight and saveNote only clear the selection, dismiss the popup, and close the note dialog on success. On failure the mark, popup, and typed note are preserved so the user can retry without losing input. - koreader annotation exchange: the PDF push-down guard now skips only PDF-only annotations (no EPUB anchor). A mixed PDF+CFI annotation still converts its CFI to xpointer instead of being dropped. - Tests for both paths. * fix(reader): label PDF selection buttons and dedupe multi-page highlight retries - PdfSelectionPopup: add aria-labels to the copy, highlight, note, and delete icon-only buttons so screen readers can identify them. - usePdfHighlights: createFromSelection keeps only the pages that failed, so a retry after a partial multi-page failure never duplicates already-saved pages. - Test for the multi-page partial-failure retry path. * fix(reader): harden PDF annotation store, validation, and create logging - usePdfAnnotations: catch rejected api() calls (session expiry / network) so load() sets loadError and mutations return null/false instead of rejecting. - create-annotation DTO: require positive rect width/height so degenerate PDF geometry is rejected; tests for zero/negative dimensions. - annotation.service: add [annotation.create] start/end/fail lifecycle logs with IDs, durationMs, and sanitized error for the multi-step create. * test(reader): cover PDF annotations in the hub and add missing docstrings Adds a real-DB e2e proving a PDF highlight persists as a pdf position and surfaces in the library-wide Annotations hub with the exact fields the page deep link needs (jumpFileFormat=pdf, cfi=null, pageno). Adds a hub-service unit test for the pdf row mapping. Documents the PDF render helpers, the annotation deep-link builder, and the createPdf repository method. * fix(annotations): make PDF highlights reliable across reloads Reconcile persisted highlights after EmbedPDF finishes loading its annotation state. Keep file-scoped pagination bounded and prevent PDF-only positions from starving device sync. Ref #1195 * fix(annotations): keep pdf annotations stable during reload Use authenticated native pagination fetches and discard responses that overlap successful mutations. Align shared dialog styling and annotation tests with project conventions. Ref #1195 --------- Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>