# DReader Application Architecture

## Overview

DReader is a full-featured ebook reader application built on top of [pyWebLayout](https://gitea.tourolle.paris/dtourolle/pyWebLayout). It provides a complete reading experience with navigation, bookmarks, highlights, and customizable display settings.

## System Architecture

### High-Level Component Structure

```
dreader/
├── application.py          # Main EbookReader class (coordinator)
├── managers/              # Specialized management modules
│   ├── document.py        # Document loading (EPUB/HTML)
│   ├── settings.py        # Font and spacing controls
│   └── highlight_coordinator.py  # Text highlighting
├── handlers/
│   └── gestures.py        # Touch event routing
├── overlays/              # UI overlay system
│   ├── base.py           # Base overlay functionality
│   ├── navigation.py     # TOC and bookmarks overlay
│   └── settings.py       # Settings overlay
├── library.py            # Library browsing and book selection
├── state.py              # Application state persistence
├── html_generator.py     # HTML generation for overlays
└── gesture.py            # Gesture definitions and responses
```

### Relationship to pyWebLayout

**pyWebLayout** provides low-level rendering primitives:
- Text layout and rendering algorithms
- Document structure and pagination
- Query systems for interactive content
- Core rendering infrastructure

**DReader** is an application framework that:
- Combines pyWebLayout components into a complete reader
- Provides high-level APIs for common ereader tasks
- Manages application state (bookmarks, highlights, positions)
- Handles business logic for gestures and interactions

Think of it as:
- **pyWebLayout** = React (library)
- **DReader** = Next.js (framework)

## Core Components

### 1. EbookReader (Main Coordinator)

**Location**: [application.py](../dreader/application.py)

The central orchestrator that coordinates all subsystems:

```python
class EbookReader:
    """Main ebook reader application"""

    # Core dependencies
    manager: EreaderLayoutManager      # pyWebLayout layout engine
    doc_manager: DocumentManager       # Document loading
    settings_manager: SettingsManager  # Display settings
    highlight_coordinator: HighlightCoordinator  # Text highlighting
    gesture_router: GestureRouter      # Gesture handling
    overlay_manager: OverlayManager    # Overlay rendering
```

**Key Responsibilities**:
- Document lifecycle (load, close)
- Page navigation (next, previous, chapters)
- Bookmark management
- Position persistence
- Settings coordination
- Gesture event routing

### 2. Document Manager

**Location**: [managers/document.py](../dreader/managers/document.py)

Handles document loading and metadata extraction.

**Responsibilities**:
- Load EPUB files via pyWebLayout
- Extract book metadata (title, author, etc.)
- Provide document info to other components

### 3. Settings Manager

**Location**: [managers/settings.py](../dreader/managers/settings.py)

Manages all display settings with persistence.

**Settings**:
- Font scale (adjustable font size)
- Line spacing
- Inter-block spacing (paragraph spacing)
- Word spacing

**Features**:
- Real-time preview in settings overlay
- Persistent across sessions
- Position preservation when settings change

### 4. Gesture Router

**Location**: [handlers/gestures.py](../dreader/handlers/gestures.py)

Routes touch events to appropriate handlers based on application state.

**Gesture Types**:
- `TAP` - Word selection, link following, overlay interaction
- `SWIPE_LEFT` - Next page
- `SWIPE_RIGHT` - Previous page
- `SWIPE_UP` - Open navigation overlay (from bottom 20%)
- `SWIPE_DOWN` - Open settings overlay (from top) or close overlay
- `PINCH_IN/OUT` - Font size adjustment
- `DRAG` - Text selection (start, move, end)

**Routing Logic**:
```
Touch Event → GestureRouter
    ├─ Is overlay open?
    │  ├─ Yes → Route to overlay handler
    │  └─ No → Route to reading mode handler
    └─ Return GestureResponse
```

### 5. Overlay System

**Location**: [overlays/](../dreader/overlays/)

The overlay system provides modal UI panels over the reading content.

#### Overlay Manager

**Location**: [overlays/base.py](../dreader/overlays/base.py)

Core overlay rendering and compositing infrastructure.

**Responsibilities**:
- Render overlay HTML to images
- Composite overlays over base page
- Darken background for modal effect
- Handle coordinate translation for interaction
- Cache for performance

#### Navigation Overlay

**Location**: [overlays/navigation.py](../dreader/overlays/navigation.py)

Unified overlay with tabbed interface for:
- **Contents Tab**: Chapter navigation (TOC)
- **Bookmarks Tab**: Saved position management

**Features**:
- Tab switching without closing overlay
- Chapter selection with jump
- Bookmark selection with jump
- Add/delete bookmarks

#### Settings Overlay

**Location**: [overlays/settings.py](../dreader/overlays/settings.py)

Interactive settings panel with real-time preview.

**Controls**:
- Font size: A- / A+ buttons
- Line spacing: +/- buttons
- Block spacing: +/- buttons
- Word spacing: +/- buttons

**Interaction**: Changes apply immediately, overlay refreshes to show updated values.

### 6. Library Manager

**Location**: [library.py](../dreader/library.py)

Manages the library browsing experience.

**Features**:
- Scan directory for EPUB files
- Extract and cache metadata
- Render library grid view
- Handle book selection via tap
- Cache cover images for performance

**Display**: Renders books in a grid with cover thumbnails and metadata.

### 7. State Manager

**Location**: [state.py](../dreader/state.py)

Persistent application state across sessions.

**State Structure**:
```python
class AppState:
    mode: EreaderMode              # LIBRARY or READING
    overlay: OverlayState          # Current overlay type
    current_book: BookState        # Currently open book
    library: LibraryState          # Library scan cache
    settings: SettingsState        # Display settings
```

**Persistence**:
- Location: `~/.config/dreader/state.json`
- Auto-save every 60 seconds
- Immediate save on mode change, settings change, shutdown
- Atomic writes for safety

**Boot Behavior**:
- Resume last book at last position
- Restore all settings
- Fall back to library if book missing

## Data Flow Diagrams

### Opening an Overlay

```
User Action
    ↓
EbookReader.open_navigation_overlay()
    ├─ Get current page (base layer)
    ├─ Get chapters and bookmarks
    ↓
OverlayManager.open_navigation_overlay()
    ├─ Generate HTML
    ├─ Render to image (using temp reader)
    ├─ Composite over base page
    │  ├─ Darken background
    │  ├─ Add border
    │  └─ Paste panel at center
    └─ Cache base page, overlay, offset
    ↓
Return composited image
```

### Overlay Interaction

```
User Touch (x, y)
    ↓
GestureRouter.handle_touch()
    ├─ Overlay open? YES
    ↓
EbookReader._handle_overlay_tap(x, y)
    ↓
OverlayManager.query_overlay_pixel(x, y)
    ├─ Translate screen coords to overlay coords
    ├─ Query pyWebLayout for link at position
    └─ Return link_target (e.g., "chapter:5")
    ↓
Parse link_target and execute action:
    ├─ "chapter:N" → jump_to_chapter(N), close overlay
    ├─ "bookmark:name" → load_position(name), close overlay
    ├─ "setting:action" → apply setting, refresh overlay
    └─ "tab:name" → switch tab, keep overlay open
    ↓
Return GestureResponse
```

### State Persistence

```
Application Running
    ↓
StateManager auto-save timer (every 60s)
    ├─ Gather current state
    ├─ Serialize to JSON
    └─ Atomic write to disk

OR

User performs action (page turn, setting change)
    ├─ StateManager.save_state()
    └─ Immediate write

Application Shutdown
    ├─ Save position: reader.save_position("__auto_resume__")
    ├─ Stop auto-save
    └─ Final state.json write
```

### Boot Sequence

```
Application Start
    ↓
StateManager.load_state()
    ├─ Read state.json
    ├─ Validate and parse
    └─ Create AppState object
    ↓
Check previous mode:
    ├─ READING mode?
    │  ├─ Load last book
    │  ├─ Apply saved settings
    │  └─ Restore position ("__auto_resume__")
    │
    └─ LIBRARY mode?
       └─ Show library grid
```

## File Organization

### Application State Files

```
~/.config/dreader/
├── state.json                 # Application state
├── covers/                    # Cached book covers
│   └── {book_id}.png
├── bookmarks/                 # Per-book bookmarks
│   └── {document_id}_{bookmark_name}.json
└── highlights/                # Per-book highlights
    └── {document_id}_highlights.json
```

### Bookmark Format

Each book's position is stored separately using document ID:
```json
{
  "document_id": "book123",
  "bookmark_name": "__auto_resume__",
  "position": {
    "offset": 1234,
    "chapter": 5
  },
  "timestamp": "2025-11-09T10:30:00Z"
}
```

## Gesture Handling

### Gesture Priority and Routing

```
Touch Event
    ↓
Is overlay open?
├─ YES → Overlay Mode
│   ├─ TAP → Handle overlay interaction
│   ├─ SWIPE_DOWN → Close overlay
│   └─ Other → Ignore (modal behavior)
│
└─ NO → Reading Mode
    ├─ TAP
    │   ├─ On link → Follow link
    │   ├─ On word → Select word
    │   ├─ Left edge → Previous page
    │   └─ Right edge → Next page
    │
    ├─ SWIPE
    │   ├─ LEFT → Next page
    │   ├─ RIGHT → Previous page
    │   ├─ UP (from bottom 20%) → Open navigation
    │   └─ DOWN (from top 20%) → Open settings
    │
    ├─ PINCH
    │   ├─ IN → Decrease font size
    │   └─ OUT → Increase font size
    │
    └─ DRAG
        ├─ START → Begin text selection
        ├─ MOVE → Extend selection
        └─ END → Complete selection
```

### Response Types

```python
class ActionType(Enum):
    NONE = "none"
    PAGE_TURN = "page_turn"
    WORD_SELECTED = "word_selected"
    LINK_FOLLOWED = "link_followed"
    CHAPTER_SELECTED = "chapter_selected"
    BOOKMARK_SELECTED = "bookmark_selected"
    SETTING_CHANGED = "setting_changed"
    OVERLAY_OPENED = "overlay_opened"
    OVERLAY_CLOSED = "overlay_closed"
    TAB_SWITCHED = "tab_switched"
```

## Performance Characteristics

### Rendering Performance

- **Page Turn**: ~50-100ms (depends on page complexity)
- **Overlay Open**: ~200-250ms (includes HTML generation and rendering)
- **Tab Switch**: ~125ms (uses cached base page)
- **Setting Change**: ~150ms (re-render with new settings)
- **Tap Interaction**: ~5-10ms (coordinate query)

### Memory Usage

- **Base Application**: ~20-30MB
- **Per Book**: ~10-50MB (depends on images)
- **Overlay Cache**: ~5-10MB

### Optimization Strategies

1. **Caching**:
   - Base page cached during overlay display
   - Overlay panel cached for tab switching
   - Cover images cached to disk
   - Metadata cached between sessions

2. **Lazy Loading**:
   - Library covers loaded on-demand
   - Book content loaded only when opened
   - Overlays rendered only when needed

3. **Efficient Updates**:
   - Tab switching reuses base page
   - Setting changes use incremental rendering
   - Position saves are debounced

## Extension Points

### Adding New Overlays

To add a new overlay type:

1. Define new `OverlayState` enum value in [state.py](../dreader/state.py#L27-L33)
2. Create HTML generator in [html_generator.py](../dreader/html_generator.py)
3. Add overlay class in `overlays/` directory
4. Implement open/close methods in [overlay manager](../dreader/overlays/base.py)
5. Add gesture handling in [application.py](../dreader/application.py)

### Custom Gesture Handlers

To add custom gestures:

1. Define gesture type in [gesture.py](../dreader/gesture.py)
2. Add handler in [gestures.py](../dreader/handlers/gestures.py)
3. Define action type for response
4. Update gesture router logic

### HAL Integration

To integrate with hardware:

Create a display abstraction layer implementing:
```python
class DisplayHAL(ABC):
    @abstractmethod
    def show_image(self, image: Image.Image):
        """Display image on hardware"""

    @abstractmethod
    def get_touch_events(self) -> Iterator[TouchEvent]:
        """Get touch input from hardware"""

    @abstractmethod
    def set_brightness(self, level: int):
        """Control display brightness"""
```

Examples:
- **E-ink**: IT8951, Remarkable device SDK
- **Desktop**: pygame, tkinter
- **Web**: Flask + HTML canvas
- **Qt**: QPixmap + QTouchEvent

## Testing Strategy

### Unit Tests

- State serialization and persistence
- Gesture routing logic
- Coordinate translation
- HTML generation

### Integration Tests

- Mode transitions (LIBRARY ↔ READING)
- Overlay lifecycle (open → interact → close)
- Boot recovery and resume
- Settings persistence

### Example-Based Testing

Working examples demonstrate full integration:
- [simple_ereader_example.py](../examples/simple_ereader_example.py)
- [library_reading_integration.py](../examples/library_reading_integration.py)
- [navigation_overlay_example.py](../examples/navigation_overlay_example.py)
- [demo_settings_overlay.py](../examples/demo_settings_overlay.py)

## Design Patterns

### Component-Based Architecture

- **Managers**: Single-responsibility modules for specific tasks
- **Handlers**: Event routing and processing
- **Overlays**: Self-contained UI components

### Delegation Over Inheritance

- EbookReader delegates to specialized managers
- No deep inheritance hierarchies
- Composition for flexibility

### State Machine Pattern

- Clear state transitions (modes, overlays)
- State persistence for resume
- Predictable behavior

### Event-Driven Architecture

- Touch events drive all interactions
- Response objects communicate results
- Decoupled components

## Future Architecture Considerations

### Sub-Application Pattern

Current overlay handling uses a monolithic approach. Future refactoring could extract overlays into sub-applications:

```python
class OverlaySubApplication(ABC):
    def open(self, context: OverlayContext) -> Image.Image: ...
    def handle_tap(self, x: int, y: int) -> GestureResponse: ...
    def close(self) -> Image.Image: ...
```

Benefits:
- Self-contained overlay logic
- Easier testing
- Plugin support
- Composable overlays

### Plugin System

Enable third-party extensions:
- Custom overlay types
- Additional gestures
- Export formats
- Cloud sync providers

## References

- [pyWebLayout Documentation](https://gitea.tourolle.paris/dtourolle/pyWebLayout)
- [REQUIREMENTS.md](REQUIREMENTS.md) - Detailed feature specifications
- [README.md](../README.md) - User-facing documentation
- [examples/](../examples/) - Working code examples
