""" HTML generation functions for dreader UI. Generates HTML strings programmatically for library view, reader view, and various overlays (settings, TOC, etc.) that can be passed to a HAL for rendering. """ from pathlib import Path from typing import List, Dict, Optional import base64 from io import BytesIO def generate_library_html(books: List[Dict[str, str]], save_covers_to_disk: bool = False) -> str: """ Generate HTML for the library view showing all books in a simple table. Args: books: List of book dictionaries with keys: - title: Book title - author: Book author - filename: EPUB filename - cover_data: Optional base64 encoded cover image - cover_path: Optional path to saved cover image (if save_covers_to_disk=True) save_covers_to_disk: If True, expect cover_path instead of cover_data Returns: Complete HTML string for library view """ # Build table rows rows = [] for book in books: # Add cover image cell if available if save_covers_to_disk and book.get('cover_path'): cover_cell = f'
{len(books)} books
Adjust reading preferences
Font Size: {font_percent}%
Line Spacing: {line_spacing}px
Paragraph Spacing: {inter_block_spacing}px
Word Spacing: {word_spacing}px
Changes apply in real-time • Tap outside to close
''' return html def generate_toc_overlay( chapters: List[Dict], page_size: tuple = (800, 1200), toc_page: int = 0, toc_items_per_page: int = 10 ) -> str: """ Generate HTML for the table of contents overlay. Args: chapters: List of chapter dictionaries with keys: - index: Chapter index - title: Chapter title page_size: Page dimensions (width, height) for sizing the overlay toc_page: Current page number (0-indexed) toc_items_per_page: Number of items to show per page Returns: HTML string for TOC overlay (60% popup with transparent background) """ # Calculate pagination toc_total_pages = (len(chapters) + toc_items_per_page - 1) // toc_items_per_page if chapters else 1 toc_start = toc_page * toc_items_per_page toc_end = min(toc_start + toc_items_per_page, len(chapters)) toc_paginated = chapters[toc_start:toc_end] # Build chapter list items with clickable links for pyWebLayout query chapter_items = [] for i, chapter in enumerate(toc_paginated): title = chapter["title"] # Use original chapter number (not the paginated index) chapter_num = toc_start + i + 1 # Wrap each row in a paragraph with an inline link # For very short titles (I, II), pad the link text to ensure it's clickable link_text = f'{chapter_num}. {title}' if len(title) <= 2: # Add extra padding spaces inside the link to make it easier to click link_text = f'{chapter_num}. {title} ' # Extra spaces for padding chapter_items.append( f'' f'' f'{link_text}
' ) # Generate pagination controls toc_pagination = "" if toc_total_pages > 1: prev_disabled = 'opacity: 0.3; pointer-events: none;' if toc_page == 0 else '' next_disabled = 'opacity: 0.3; pointer-events: none;' if toc_page >= toc_total_pages - 1 else '' toc_pagination = f''' ''' # Render simple white panel - compositing will be done by OverlayManager html = f'''{len(chapters)} chapters
Tap a chapter to navigate • Tap outside to close
''' return html def generate_bookmarks_overlay(bookmarks: List[Dict]) -> str: """ Generate HTML for the bookmarks overlay. Args: bookmarks: List of bookmark dictionaries with keys: - name: Bookmark name - position: Position info Returns: HTML string for bookmarks overlay """ bookmark_rows = [] for bookmark in bookmarks: bookmark_rows.append(f'''' f'' f'{link_text}
' ) # Calculate pagination for bookmarks bookmarks_total_pages = (len(bookmarks) + toc_items_per_page - 1) // toc_items_per_page if bookmarks else 1 bookmarks_start = bookmarks_page * toc_items_per_page bookmarks_end = min(bookmarks_start + toc_items_per_page, len(bookmarks)) bookmarks_paginated = bookmarks[bookmarks_start:bookmarks_end] # Build bookmark list items with clickable links bookmark_items = [] for bookmark in bookmarks_paginated: name = bookmark['name'] position_text = bookmark.get('position', 'Saved position') bookmark_items.append( f'' f'' f'{name}' f'{position_text}' f'
' ) # Determine which content to show contents_display = "block" if active_tab == "contents" else "none" bookmarks_display = "block" if active_tab == "bookmarks" else "none" # Style active tab contents_tab_style = "background-color: #000; color: #fff;" if active_tab == "contents" else "background-color: #f0f0f0; color: #000;" bookmarks_tab_style = "background-color: #000; color: #fff;" if active_tab == "bookmarks" else "background-color: #f0f0f0; color: #000;" chapters_html = ''.join(chapter_items) if chapter_items else 'No chapters available
' bookmarks_html = ''.join(bookmark_items) if bookmark_items else 'No bookmarks yet
' # Generate pagination controls for TOC toc_pagination = "" if toc_total_pages > 1: prev_disabled = 'opacity: 0.3; pointer-events: none;' if toc_page == 0 else '' next_disabled = 'opacity: 0.3; pointer-events: none;' if toc_page >= toc_total_pages - 1 else '' toc_pagination = f''' ''' # Generate pagination controls for Bookmarks bookmarks_pagination = "" if bookmarks_total_pages > 1: prev_disabled = 'opacity: 0.3; pointer-events: none;' if bookmarks_page == 0 else '' next_disabled = 'opacity: 0.3; pointer-events: none;' if bookmarks_page >= bookmarks_total_pages - 1 else '' bookmarks_pagination = f''' ''' html = f'''{len(chapters)} chapters
{len(bookmarks)} saved