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).
This commit is contained in:
2026-04-03 22:29:11 -04:00
parent fa2d4c0fd8
commit 0191d36dc9
+203
View File
@@ -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<string, Blob>;
// 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<EbookCIF>;
extractMetadata(file: Blob): Promise<Partial<EbookCIF["metadata"]>>;
}
// ============================================================
// 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;
}