# ePub Reader — Design Document ## Overview A lightweight ePub reader desktop application built with Rust + egui, compiled as a single Windows executable (x86_64-pc-windows-gnu / MSYS2+MinGW). No console window. Built-in Chinese font support. Kindle-like reading experience with medium feature set. ## Tech Stack | Layer | Choice | |---|---| | GUI Framework | `eframe` (egui official framework) | | Rendering Backend | `wgpu` | | ePub Parsing | `epub-rs` | | Font | Bundled Noto Sans SC (or similar open-source Chinese font) | | Build Target | `x86_64-pc-windows-gnu` | | Binary | Single `.exe`, `#![windows_subsystem = "windows"]` | ## Core Data Model ```rust struct AppState { book: Option, current_section: usize, current_page: usize, settings: Settings, bookmarks: Vec, sidebar_open: bool, } struct Book { title: String, author: String, cover: Option>, sections: Vec
, toc: Vec, } struct Section { title: String, content: String, // plain text (HTML tags stripped) pages: Vec, // character offsets for page boundaries } struct Settings { font_size: f32, // default 20.0 theme: Theme, } enum Theme { Light, Dark } struct Bookmark { section: usize, page: usize, label: String, timestamp: i64, } struct TocEntry { label: String, section: usize, children: Vec, } ``` ## Architecture ``` ┌──────────────────────────────────────────┐ │ eframe::App │ │ ┌──────────┐ ┌───────────────────────┐ │ │ │ WelcomePg │ │ ReadingView │ │ │ │ (no book) │ │ ├─ TopToolbar │ │ │ │ ──────── │ │ ├─ Sidebar (TOC) │ │ │ │ open btn │ │ ├─ TextArea │ │ │ │ recents │ │ └─ BottomProgressBar │ │ │ └──────────┘ └───────────────────────┘ │ │ ┌──────────────────────────────────────┐ │ │ │ AppState │ │ │ └──────────────────────────────────────┘ │ └──────────────────────────────────────────┘ ``` ## UI Layout ### Welcome Screen (no book open) - Centered "Open ePub File" button - Recently opened books list (read from settings file) ### Reading Screen (Kindle-like) - **Top toolbar**: back button, book title, font size controls, menu, bookmark toggle, theme toggle - **Left sidebar** (collapsible): table of contents tree - **Center**: text content area with pagination - Click left 30% → prev page, right 30% → next page, center 40% → toggle toolbar visibility - Keyboard: ← → for prev/next page - **Bottom bar**: current chapter name, progress slider, page number indicator ## Features (Medium Scope) ### Core 1. Open `.epub` file via native file dialog 2. Parse ePub (OPF manifest, NCX/TOC, Spine) 3. Render chapter content with pagination 4. Next/previous page navigation (click & keyboard) 5. Table of contents sidebar with chapter navigation 6. Remember last reading position (bookmark per file) ### Settings & Display 7. Font size adjustment (A⁺/A⁻) 8. Light/Dark theme toggle 9. Chinese font support (bundled Noto Sans SC) ### Bookmarks 10. Add/remove bookmarks at current page 11. Bookmark list view ### Persistence 12. `settings.json` saves: font_size, theme, recent files, reading positions, bookmarks ## Data Flow 1. User clicks "Open" → native file dialog → select `.epub` 2. `EpubLoader` reads zip, extracts OPF metadata, reads spine order, parses NCX for TOC 3. For each spine item: extract HTML content, strip tags → plain text stored in `Section.content` 4. On section load: calculate pagination based on current font_size + panel width → store page offsets 5. On page change: slice `Section.content[pages[current_page]..pages[current_page+1]]` → render to egui `Label` 6. On font_size change: recalculate all pagination for current section 7. On theme toggle: switch `egui::Style` between light/dark visuals ## Pagination Algorithm ``` fn paginate(text: &str, font_size: f32, panel_width: f32) -> Vec chars_per_line = floor(panel_width / (font_size * 0.6)) lines_per_page = floor(panel_height / (font_size * 1.5)) chars_per_page = chars_per_line * lines_per_page Iterate text, split at chars_per_page boundaries (prefer word/char boundaries) ``` ## File Storage - `settings.json` (next to exe OR in standard config dir) - font_size, theme - recent_files: Vec<{path, title}> - reading_positions: HashMap - bookmarks: HashMap> - Last window size/position ## Error Handling - ePub parsing failure → show error dialog with message - File not found (recent list) → remove from list silently - Font loading failure → fall back to system monospace - Settings file corruption → reset to defaults, log warning ## Out of Scope (v1) - Text search within book - Highlighting / annotations - Notes/export - TTS - Epub with complex CSS styling / reflowable layout math - DRM-protected ePubs