Archived
- add uv configuration for the backend - update frontend to make auth work - add new auth endpoints - add bookmars feat - add reader feat
84 lines
3.0 KiB
Markdown
84 lines
3.0 KiB
Markdown
# 015 — EPUB bookmarks and notes (physical-book UX)
|
|
|
|
**Status:** Implemented
|
|
**Created:** 2026-06-04
|
|
|
|
## Objective
|
|
|
|
Let users select passage text while reading an EPUB, save a bookmark (with optional thought), list markers in chapter order, and jump back to the exact location. Global view groups markers by book in a Reddit-style thread layout.
|
|
|
|
## Fix: AnnotationsProvider
|
|
|
|
`AnnotationsProvider` wraps all routes in [`App.tsx`](frontend/src/App.tsx) so `/bookmarks-notes` and the reader can use `useAnnotations()`.
|
|
|
|
## Data model
|
|
|
|
`Bookmark` (annotations app) references **`books.EBook`**, not catalog `Book`:
|
|
|
|
| Field | Purpose |
|
|
|-------|---------|
|
|
| `ebook` | FK to uploaded ebook |
|
|
| `epub_cfi` | EPUB CFI anchor |
|
|
| `chapter_index` | Spine index for sort order |
|
|
| `chapter_title` | Display label |
|
|
| `location_text` | Selected passage quote |
|
|
| `content` | Optional user thought (empty = bookmark only) |
|
|
| `page` | Legacy display field (`chapter_index + 1`) |
|
|
|
|
Unique: `(user, ebook, epub_cfi)`.
|
|
|
|
Default API ordering: `chapter_index`, `epub_cfi`.
|
|
|
|
Legacy `Note` model remains for old API; new UX uses `Bookmark.content` only.
|
|
|
|
## Reader flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant User
|
|
participant EpubView
|
|
participant Popover
|
|
participant API
|
|
User->>EpubView: Select text
|
|
EpubView->>Popover: Show near selection
|
|
User->>Popover: Save optional thought
|
|
Popover->>API: POST /annotations/bookmarks/
|
|
```
|
|
|
|
1. Text selection via epub.js `selected` event and content `mouseup` hook.
|
|
2. [`SelectionPopover`](frontend/src/components/reader/SelectionPopover.tsx) — floating UI, optional textarea.
|
|
3. Toolbar bookmark icon opens [`BookMarkersPanel`](frontend/src/components/reader/BookMarkersPanel.tsx) (current ebook only).
|
|
4. “Go to passage” sets reader `location` to stored CFI (`/read/:id` with router state).
|
|
|
|
## Global page (`/bookmarks-notes`)
|
|
|
|
[`MarkerThreadsView`](frontend/src/components/annotations/MarkerThreadsView.tsx):
|
|
|
|
- Groups markers by ebook (collapsible book rows).
|
|
- Within each book: chapter order, passage as blockquote, thought indented below (Reddit-style).
|
|
- Optional filter: `/bookmarks-notes/:ebookId`.
|
|
|
|
## API
|
|
|
|
- `GET /api/annotations/bookmarks/?ebook={id}`
|
|
- `POST /api/annotations/bookmarks/` — body: `ebook`, `epub_cfi`, `chapter_index`, `chapter_title`, `location_text`, `content`
|
|
|
|
## i18n
|
|
|
|
New keys under `annotations.*` (EN/ES): `saveMarker`, `thoughtPlaceholder`, `bookmarkOnly`, `selectTextHint`, `goToPassage`, `inBookPanel`, `markerCount`, etc.
|
|
|
|
## Verification
|
|
|
|
1. `/bookmarks-notes` loads without provider error.
|
|
2. Select text in reader → popover → save with/without thought.
|
|
3. Markers appear in reader panel and global page under correct book, in chapter order.
|
|
4. “Go to passage” opens the correct location.
|
|
|
|
See also [016 — Bookmark reading anchor](016-bookmark-reading-anchor.md) for preserving reading position while peeking at bookmarks.
|
|
|
|
## Out of scope
|
|
|
|
- PDF selection
|
|
- Multiple replies per passage
|
|
- Migrating legacy `Note` rows into `Bookmark`
|