From 0191d36dc992914ba8ecfcaaea38eeb3bef0a481 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Fri, 3 Apr 2026 22:29:11 -0400 Subject: [PATCH] Add TypeScript type definitions for reader feature Define comprehensive TypeScript interfaces for reader functionality: - Common Intermediate Format (CIF) for universal ebook representation - Parser capabilities and format detection types - Reader metadata and chapter structure interfaces - Panel layout and dock system types - Reading progress and settings interfaces - Dictionary and search functionality types These types provide the foundation for type-safe reader implementation across all media types (ebook, comic, manga, pdf). --- web/src/types/reader.d.ts | 203 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 web/src/types/reader.d.ts diff --git a/web/src/types/reader.d.ts b/web/src/types/reader.d.ts new file mode 100644 index 0000000..ecf273d --- /dev/null +++ b/web/src/types/reader.d.ts @@ -0,0 +1,203 @@ +// ============================================================ +// Common Intermediate Format (CIF) Types +// Universal format for all reflowable ebooks after parsing +// ============================================================ + +interface EbookCIF { + // Universal metadata (all formats) + metadata: { + title: string; + author: string; + language: string; + publisher?: string; + isbn?: string; + coverImage?: Blob; + }; + + // Unified navigation structure + toc: TOCNode[]; + + // Content spine (reading order) + spine: SpineItem[]; + + // Resources (CSS, fonts, images) + resources: Map; + + // Progress tracking (minimal - backend handles detailed tracking) + locations: { + totalCharacters: number; + estimatedPages: number; + }; +} + +interface SpineItem { + id: string; + type: "html" | "image"; + content: string; + properties?: string[]; + + // Minimal position info for UI + index: number; +} + +interface TOCNode { + id: string; + title: string; + href: string; + children: TOCNode[]; +} + +// ============================================================ +// Parser Types (Procedural, not OOP) +// ============================================================ + +type ParserFormat = + | "epub" + | "fb2" + | "txt" + | "html" + | "mobi" + | "azw3" + | "docx" + | "rtf"; + +interface ParserCapabilities { + canParse(mimeType: string, extension: string): boolean; + parse(file: Blob): Promise; + extractMetadata(file: Blob): Promise>; +} + +// ============================================================ +// Reader Metadata (from API) +// ============================================================ + +interface ReaderMetadata { + media_item_id: string; + title: string; + author: string; + cover_image_path: string; + library_type: "ebook" | "comic" | "manga" | "pdf"; + mime_type: string; + file_path: string; + chapter_metadata?: ChapterMetadata; + total_pages?: number; +} + +// ============================================================ +// Other Shared Types +// ============================================================ + +interface ChapterMetadata { + chapters: Chapter[]; +} + +interface Chapter { + id: string; + title: string; + start_page: number; + page_count: number; +} + +interface PanelData { + media_item_id: string; + page_number: number; + detection_method: "grid" | "ml" | "manual"; + panels: Panel[]; + updated_at: string; +} + +interface Panel { + id: string; + x: number; + y: number; + width: number; + height: number; + reading_order: number; +} + +interface ReadingSpeed { + words_per_minute: number; + pages_per_minute: number; + pages_read: number; + total_reading_minutes: number; + last_read_at: string; +} + +interface DictionaryEntry { + word: string; + definition: string; + part_of_speech?: string; + example?: string; + etymology?: string; +} + +interface ReaderSettings { + chrome_behavior: "auto-hide" | "always-visible" | "hide-on-scroll"; + progress_mode: "pages" | "chapter" | "percentage" | "time-left"; + + chrome_theme: string; + reading_theme: "light" | "sepia" | "dark" | "night" | "high-contrast"; + + reading_font: + | "literata" + | "crimson" + | "source-serif" + | "eb-garamond" + | "libertinus" + | "noto-serif" + | "charis-sil" + | "ibm-plex"; + font_size: number; + line_height: number; + margin_width: number; + + tap_zone_size: number; + auto_scroll: boolean; + panel_zoom_enabled: boolean; + + double_page_spread: boolean; + reading_direction: "ltr" | "rtl" | "vertical"; + + pdf_fit_mode: "fit-width" | "fit-page" | "fit-height" | "none"; + pdf_zoom_level: number; + pdf_text_layer_enabled: boolean; + pdf_dual_page_mode: "auto" | "single" | "dual"; + pdf_dual_page_threshold: number; + pdf_minimap_enabled: boolean; + pdf_outline_visible: boolean; + media_bookmarks_visible: boolean; + + hardware_acceleration: boolean; + + // Dockable panel layout configuration (per-user, media-type-aware) + panel_layout: PanelLayoutSettings; +} + +interface PanelLayoutSettings { + // Per panel state: which side, visible, collapsed (window-shade), width + toc: PanelState; + settings: PanelState; + navigator: PanelState; + bookmarks: PanelState; + + // Mobile override + mobile_nav_visible: boolean; +} + +interface PanelState { + side: "left" | "right" | "hidden"; + visible: boolean; + collapsed: boolean; // Window-shade: true = collapsed to title bar + width_px: number; // Panel width in pixels + order: number; // Order within the side + locked: boolean; // Lock toggle: prevents accidental drag/move + last_valid_side: "left" | "right" | "hidden"; // Snap-back target if dropped in invalid area +} + +interface ProgressDisplay { + mode: "pages" | "chapter" | "percentage" | "time-left"; + current: number; + total: number; + label?: string; + time_left?: string; +}