# Agent 7 - Thumbnail Generation Architecture
## System Overview
```
┌─────────────────────────────────────────────────────────────────┐
│ THUMBNAIL GENERATION SYSTEM │
└─────────────────────────────────────────────────────────────────┘
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Template │────────▶│ getThumbnail │────────▶│ Cache │
│ (Vue View) │ │ (pageNum) │ │ Check First │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
│
┌───────────────────────────┼───────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌─────────┐
│ Cached │ │ Loading? │ │Generate │
│ Return │ │ Wait │ │ New │
└──────────┘ └──────────┘ └────┬────┘
│
▼
┌─────────────────┐
│ PDF.js API │
│ getPage(num) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ getViewport() │
│ scale: 0.2 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Create Canvas │
│ 80x100px (≈) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ page.render() │
│ to Canvas │
└────────┬────────┘
│
▼
┌─────────────────┐
│ toDataURL() │
│ PNG @ 0.8 qual │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Store in Cache │
│ Return Data URL│
└─────────────────┘
```
## Component Interaction Flow
```
USER SEARCHES
│
▼
┌────────────────────────────────────────────────────┐
│ performSearch() → highlightSearchTerms() │
│ Creates hitList with page numbers and snippets │
└────────────────┬───────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────┐
│ Template renders search results │
│ For each hit in hitList: │
│ - Show thumbnail (getThumbnail(hit.page)) │
│ - Show snippet │
│ - Show page number │
└────────────────┬───────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────┐
│ getThumbnail(pageNum) │
│ ├─▶ Check thumbnailCache Map │
│ ├─▶ Check thumbnailLoading Set │
│ └─▶ Call generateThumbnail(pageNum) │
└────────────────┬───────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────┐
│ generateThumbnail(pageNum) │
│ 1. Mark as loading │
│ 2. Get page from PDF │
│ 3. Create viewport at 0.2 scale │
│ 4. Render to off-screen canvas │
│ 5. Convert to PNG data URL │
│ 6. Cache result │
│ 7. Unmark loading │
└────────────────┬───────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────┐
│ Template receives data URL │
│
│
└────────────────────────────────────────────────────┘
```
## State Management
```
┌─────────────────────────────────────────────────────┐
│ STATE VARIABLES │
├─────────────────────────────────────────────────────┤
│ │
│ thumbnailCache (Map) │
│ ├─ Key: Page Number (integer) │
│ └─ Value: Data URL (string) │
│ │
│ Example: │
│ Map { │
│ 1 => "data:image/png;base64,iVBORw0KG...", │
│ 3 => "data:image/png;base64,iVBORw0KG...", │
│ 5 => "data:image/png;base64,iVBORw0KG..." │
│ } │
│ │
│ thumbnailLoading (Set) │
│ └─ Contains page numbers currently generating │
│ │
│ Example: │
│ Set { 2, 4, 7 } │
│ │
└─────────────────────────────────────────────────────┘
```
## Cache Lifecycle
```
Document Load
│
▼
┌─────────────────┐
│ Cache: Empty │
│ Loading: Empty │
└────────┬────────┘
│
▼
Search Performed
│
▼
┌─────────────────────────────────────┐
│ User sees results with thumbnails │
└────────┬────────────────────────────┘
│
▼
First thumbnail request (page 5)
│
▼
┌─────────────────┐
│ Cache: Empty │──▶ Generate thumbnail
│ Loading: {5} │
└────────┬────────┘
│
▼ (thumbnail rendered)
┌─────────────────┐
│ Cache: {5} │
│ Loading: Empty │
└────────┬────────┘
│
▼
Second request for same page (page 5)
│
▼
┌─────────────────┐
│ Cache: {5} ✓ │──▶ Return immediately
│ Loading: Empty │ (no regeneration)
└────────┬────────┘
│
▼
Document change
│
▼
clearThumbnailCache()
│
▼
┌─────────────────┐
│ Cache: Empty │
│ Loading: Empty │
└─────────────────┘
```
## Performance Characteristics
```
┌────────────────────────────────────────────────────┐
│ PERFORMANCE METRICS │
├────────────────────────────────────────────────────┤
│ │
│ Thumbnail Size (typical): │
│ ├─ Dimensions: 80x100px (approx) │
│ ├─ File size: 5-10 KB per thumbnail │
│ └─ Format: PNG (0.8 quality) │
│ │
│ Generation Time: │
│ ├─ First generation: 50-150ms │
│ └─ Cached retrieval: <1ms │
│ │
│ Memory Usage: │
│ ├─ Per thumbnail: ~10 KB │
│ ├─ 50 pages cached: ~500 KB │
│ └─ 200 pages cached: ~2 MB │
│ │
│ Concurrent Generation: │
│ ├─ Multiple pages can generate simultaneously │
│ ├─ No race conditions (loading Set prevents) │
│ └─ Duplicates wait for first to complete │
│ │
└────────────────────────────────────────────────────┘
```
## Error Handling
```
generateThumbnail(pageNum)
│
├──▶ pdfDoc null? ──▶ Return ''
│
├──▶ getPage() fails? ──▶ Catch, log, return ''
│
├──▶ Canvas context fail? ──▶ Throw error, return ''
│
└──▶ render() fails? ──▶ Catch, log, return ''
│
▼
┌────────────────┐
│ Finally block │
│ - Unmark loading│
└────────────────┘
```
## Integration Points
```
┌────────────────────────────────────────────────────┐
│ DocumentView.vue Structure │
├────────────────────────────────────────────────────┤
│ │
│ │
│ └─ Search Results │
│ └─ Thumbnail Images ──▶ getThumbnail() │
│ │
│