# US: Customizable Mobile Reading Experience **Issue:** https://gitea-dev.codescripters.org/HermesFactory/cloud-reader/issues (TBD) ## Overview Add a full-screen reading view for ebooks with customizable typography, themes, table of contents navigation, and orientation support. Mobile-first, responsive design that adapts to any screen size. --- ## Backend Specification ### New Models #### `apps.books.models.Chapter` | Field | Type | Notes | |-------------|--------------------|--------------------------------| | id | AutoField (PK) | | | book | FK -> Book | related_name="chapters" | | title | CharField(512) | Chapter title | | number | PositiveIntegerField | Chapter ordering / TOC index | | content | TextField | Chapter text/markdown content | | created_at | DateTimeField | auto_now_add | | updated_at | DateTimeField | auto_now | **Constraints:** UniqueConstraint(book, chapter_number) **Ordering:** [book, number] **Index:** FK to book with db_index #### `apps.books.models.ReadingProgress` | Field | Type | Notes | |------------------|--------------------|--------------------------------| | id | AutoField (PK) | | | user | FK -> User | related_name="reading_progress"| | book | FK -> Book | related_name="reading_progress"| | current_chapter | PositiveIntegerField | Last chapter number | | current_position | PositiveIntegerField | Position within chapter (paragraph) | | percentage | FloatField | 0.0 - 100.0 overall progress | | updated_at | DateTimeField | auto_now | **Constraints:** UniqueConstraint(user, book) **Indexes:** (user, book) composite, (user) filter for list queries #### `apps.reader.models.ReadingSettings` New app `apps/reader/` for reading preferences, isolated from book data model. | Field | Type | Notes | |-------------------|--------------------|-------------------------------| | id | AutoField (PK) | | | user | OneToOneField -> User | related_name="reading_settings" | | font_family | CharField(32) | "sans-serif", "serif", "monospace" | | font_size | PositiveSmallIntegerField | 12-32, default 18 | | line_height | FloatField | 1.2 - 2.0, default 1.6 | | margin_width | PositiveSmallIntegerField | 8-48, default 16 (px) | | background_color | CharField(7) | Hex color, default "#f5f0eb" | | text_color | CharField(7) | Hex color, default "#1a1a1a" | | brightness | PositiveSmallIntegerField | 0-100, default 100 | | orientation_lock | CharField(16) | "auto", "portrait", "landscape" | | theme | CharField(32) | "sepia", "dark", "light", "paper" | | created_at | DateTimeField | auto_now_add | | updated_at | DateTimeField | auto_now | ### New API Endpoints All under `/api/` prefix, authenticated with JWT. #### Reader Settings (`/api/reader/settings/`) | Method | URL | Action | |--------|------------------------------|---------------------------| | GET | /api/reader/settings/ | Get current user settings | | PUT | /api/reader/settings/ | Create/update settings | | PATCH | /api/reader/settings/ | Partial update settings | - Single-object endpoint (one settings record per user, auto-created on first GET) - Validation: font_size 12-32, line_height 1.2-2.0, margin_width 8-48 #### Reading Progress (`/api/books/{id}/progress/`) | Method | URL | Action | |--------|----------------------------------------|------------------------------| | GET | /api/books/{id}/progress/ | Get reading progress for book| | PUT | /api/books/{id}/progress/ | Create/update reading progress| - Nested under book detail - Auto-creates progress record on first PUT #### Chapters (`/api/books/{id}/chapters/`) | Method | URL | Action | |--------|----------------------------------------|------------------------------| | GET | /api/books/{id}/chapters/ | List chapters for book (TOC) | | GET | /api/books/{id}/chapters/{number}/ | Get specific chapter content | - Ordering by `number` - Used by frontend TOC sidebar and content loading --- ## Frontend Specification ### New Pages #### `/reader/:bookId` — ReadingPage Full-screen reading view with: - Chapter content display (left/right swiping or scroll) - Bottom toolbar: TOC toggle, Settings toggle, Progress indicator - Top bar: Back button, Book title, Chapter title - Swipe/tap/page navigation between chapters ### New Components #### `ReaderToolbar` - Fixed bottom toolbar - TOC button (opens TOC drawer) - Settings/theme button (opens settings panel) - Progress bar showing overall reading progress #### `TableOfContents` - Slide-in drawer from left - Lists all chapters with current chapter highlighted - Tap on chapter to navigate - Shows reading progress per chapter #### `ReadingSettingsPanel` - Slide-in drawer from right (or bottom sheet on mobile) - Controls: - Theme presets: Sepia, Dark, Light, Paper - Font family: Sans-serif, Serif, Monospace - Font size slider (12-32) - Line height slider (1.2-2.0) - Margin/padding control - Orientation lock toggle (Auto / Portrait / Landscape) - All changes persist immediately via API - LocalStorage fallback when offline ### New Hooks #### `useReadingSettings(bookId)` - Fetches user reading settings from API - Returns current settings + update function - Applies CSS custom properties to document root - Falls back to defaults if API unavailable #### `useChapters(bookId)` - Fetches chapter list for TOC - Returns chapters array, current chapter, navigate function - Prefetches next/prev chapter content #### `useReadingProgress(bookId)` - Fetches/updates reading progress - Auto-saves position on chapter change and periodic interval ### New Types ```typescript interface Chapter { id: number; book: number; title: string; number: number; content?: string; // Only present when fetching individual chapter } interface ChapterSummary { id: number; book: number; title: string; number: number; } interface ReadingSettings { font_family: "sans-serif" | "serif" | "monospace"; font_size: number; line_height: number; margin_width: number; background_color: string; text_color: string; brightness: number; orientation_lock: "auto" | "portrait" | "landscape"; theme: "sepia" | "dark" | "light" | "paper"; } interface ReadingProgress { current_chapter: number; current_position: number; percentage: number; updated_at: string; } ``` ### CSS / Theming Reading view uses CSS custom properties driven by reading settings: ```css :root { --reader-bg: var(--bg-color, #f5f0eb); --reader-text: var(--text-color, #1a1a1a); --reader-font-family: var(--font-family, "Georgia", serif); --reader-font-size: var(--font-size, 18px); --reader-line-height: var(--line-height, 1.6); --reader-margin: var(--margin-width, 16px); } ``` Three theme presets: - **Sepia**: `bg:#f5f0eb`, `text:#1a1a1a` — warm, easy on eyes - **Dark**: `bg:#1a1a2e`, `text:#e0e0e0` — for low-light reading - **Light**: `bg:#ffffff`, `text:#1a1a1a` — crisp and clean - **Paper**: `bg:#e8e0d4`, `text:#2c2c2c` — book-like feel ### Orientation Support - CSS `@media (orientation: portrait)` and `@media (orientation: landscape)` breakpoints - Reading settings panel includes orientation lock toggle - On mobile, landscape mode expands content horizontally with wider margins - Portrait mode stacks controls vertically for thumb-reachable UI ### Routing Add to App.tsx: ``` / → LibraryPage /books/:bookId → BookDetailPage /reader/:bookId → ReadingPage ``` --- ## Implementation Order 1. Backend models + migrations (Chapter, ReadingProgress, ReadingSettings) 2. Backend serializers + views + URLs 3. Frontend types + API client 4. Frontend hooks (useReadingSettings, useChapters, useReadingProgress) 5. Frontend components (ReadingSettingsPanel, TableOfContents, ReaderToolbar) 6. Frontend page (ReadingPage) 7. Routing updates 8. CSS / theming