# 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 │ ├────────────────────────────────────────────────────┤ │ │ │