paginate long tocs
Python CI / test (3.12) (push) Successful in 8m37s
Python CI / test (3.13) (push) Has been cancelled

This commit is contained in:
2025-11-09 20:02:55 +01:00
parent 01e79dfa4b
commit a552eb0951
4 changed files with 513 additions and 24 deletions
+115 -14
View File
@@ -294,7 +294,12 @@ def generate_settings_overlay(
return html
def generate_toc_overlay(chapters: List[Dict], page_size: tuple = (800, 1200)) -> str:
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.
@@ -303,21 +308,32 @@ def generate_toc_overlay(chapters: List[Dict], page_size: tuple = (800, 1200)) -
- 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(chapters):
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'{i+1}. {title}'
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'{i+1}. {title} ' # Extra spaces for padding
link_text = f'{chapter_num}. {title} ' # Extra spaces for padding
chapter_items.append(
f'<p style="padding: 12px; margin: 5px 0; background-color: #f0f0f0; '
@@ -326,6 +342,26 @@ def generate_toc_overlay(chapters: List[Dict], page_size: tuple = (800, 1200)) -
f'{link_text}</a></p>'
)
# 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'''
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 15px; padding-top: 12px; border-top: 2px solid #ccc;">
<a href="page:prev" style="text-decoration: none; color: #000; display: block; padding: 10px 20px; background-color: #e0e0e0; border-radius: 4px; font-weight: bold; {prev_disabled}">
← Prev
</a>
<span style="color: #666; font-size: 13px;">
Page {toc_page + 1} of {toc_total_pages}
</span>
<a href="page:next" style="text-decoration: none; color: #000; display: block; padding: 10px 20px; background-color: #e0e0e0; border-radius: 4px; font-weight: bold; {next_disabled}">
Next →
</a>
</div>
'''
# Render simple white panel - compositing will be done by OverlayManager
html = f'''
<!DOCTYPE html>
@@ -345,10 +381,12 @@ def generate_toc_overlay(chapters: List[Dict], page_size: tuple = (800, 1200)) -
{len(chapters)} chapters
</p>
<div style="max-height: 600px; overflow-y: auto;">
<div style="min-height: 400px;">
{"".join(chapter_items)}
</div>
{toc_pagination}
<p style="text-align: center; margin: 15px 0 0 0; padding-top: 12px;
border-top: 2px solid #ccc; color: #888; font-size: 11px;">
Tap a chapter to navigate • Tap outside to close
@@ -508,13 +546,17 @@ def generate_navigation_overlay(
chapters: List[Dict],
bookmarks: List[Dict],
active_tab: str = "contents",
page_size: tuple = (800, 1200)
page_size: tuple = (800, 1200),
toc_page: int = 0,
toc_items_per_page: int = 10,
bookmarks_page: int = 0
) -> str:
"""
Generate HTML for the unified navigation overlay with Contents and Bookmarks tabs.
This combines TOC and Bookmarks into a single overlay with tab switching.
This combines TOC and Bookmarks into a single overlay with tab switching and pagination.
Tabs are clickable links that switch between contents (tab:contents) and bookmarks (tab:bookmarks).
Pagination buttons (page:next, page:prev) allow navigating through large lists.
Args:
chapters: List of chapter dictionaries with keys:
@@ -525,17 +567,28 @@ def generate_navigation_overlay(
- position: Position info (optional)
active_tab: Which tab to show ("contents" or "bookmarks")
page_size: Page dimensions (width, height) for sizing the overlay
toc_page: Current page number for TOC (0-indexed)
toc_items_per_page: Number of items to show per page
bookmarks_page: Current page number for bookmarks (0-indexed)
Returns:
HTML string for navigation overlay with tab switching
HTML string for navigation overlay with tab switching and pagination
"""
# Calculate pagination for chapters
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
chapter_items = []
for i, chapter in enumerate(chapters):
for i, chapter in enumerate(toc_paginated):
title = chapter["title"]
link_text = f'{i+1}. {title}'
# Use original chapter number (not the paginated index)
chapter_num = toc_start + i + 1
link_text = f'{chapter_num}. {title}'
if len(title) <= 2:
link_text = f'{i+1}. {title} ' # Extra spaces for padding
link_text = f'{chapter_num}. {title} ' # Extra spaces for padding
chapter_items.append(
f'<p style="margin: 5px 0; background-color: #f0f0f0; border-left: 3px solid #000;">'
@@ -543,9 +596,15 @@ def generate_navigation_overlay(
f'{link_text}</a></p>'
)
# 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:
for bookmark in bookmarks_paginated:
name = bookmark['name']
position_text = bookmark.get('position', 'Saved position')
@@ -568,6 +627,46 @@ def generate_navigation_overlay(
chapters_html = ''.join(chapter_items) if chapter_items else '<p style="padding: 20px; text-align: center; color: #999;">No chapters available</p>'
bookmarks_html = ''.join(bookmark_items) if bookmark_items else '<p style="padding: 20px; text-align: center; color: #999;">No bookmarks yet</p>'
# 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'''
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 15px; padding-top: 12px; border-top: 2px solid #ccc;">
<a href="page:prev" style="text-decoration: none; color: #000; display: block; padding: 10px 20px; background-color: #e0e0e0; border-radius: 4px; font-weight: bold; {prev_disabled}">
← Prev
</a>
<span style="color: #666; font-size: 13px;">
Page {toc_page + 1} of {toc_total_pages}
</span>
<a href="page:next" style="text-decoration: none; color: #000; display: block; padding: 10px 20px; background-color: #e0e0e0; border-radius: 4px; font-weight: bold; {next_disabled}">
Next →
</a>
</div>
'''
# 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'''
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 15px; padding-top: 12px; border-top: 2px solid #ccc;">
<a href="page:prev" style="text-decoration: none; color: #000; display: block; padding: 10px 20px; background-color: #e0e0e0; border-radius: 4px; font-weight: bold; {prev_disabled}">
← Prev
</a>
<span style="color: #666; font-size: 13px;">
Page {bookmarks_page + 1} of {bookmarks_total_pages}
</span>
<a href="page:next" style="text-decoration: none; color: #000; display: block; padding: 10px 20px; background-color: #e0e0e0; border-radius: 4px; font-weight: bold; {next_disabled}">
Next →
</a>
</div>
'''
html = f'''
<!DOCTYPE html>
<html>
@@ -600,9 +699,10 @@ def generate_navigation_overlay(
border-bottom: 2px solid #ccc; font-size: 13px;">
{len(chapters)} chapters
</p>
<div style="overflow-y: auto; max-height: calc(100vh - 200px);">
<div style="min-height: 400px;">
{chapters_html}
</div>
{toc_pagination}
</div>
<!-- Bookmarks Tab Content -->
@@ -614,9 +714,10 @@ def generate_navigation_overlay(
border-bottom: 2px solid #ccc; font-size: 13px;">
{len(bookmarks)} saved
</p>
<div style="overflow-y: auto; max-height: calc(100vh - 200px);">
<div style="min-height: 400px;">
{bookmarks_html}
</div>
{bookmarks_pagination}
</div>
<!-- Close Button (bottom right) -->