Archived
- Backend: Chapter, ReadingProgress, ReadingSettings models - Backend: Chapter API (TOC + content), progress tracking, settings CRUD - Frontend: ReadingPage with chapter navigation - Frontend: TableOfContents drawer - Frontend: ReadingSettingsPanel (theme, font, size, orientation) - Frontend: Custom hooks for settings, chapters, progress tracking - CSS: Mobile-first reading view with sepia/dark/light/paper themes - Route: /reader/:bookId reading view from book detail page - Docs: 001-customizable-mobile-reading-experience.md
246 lines
8.5 KiB
Markdown
246 lines
8.5 KiB
Markdown
# 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 |