diff --git a/dreader/library.py b/dreader/library.py index 5a7c2e1..be4c951 100644 --- a/dreader/library.py +++ b/dreader/library.py @@ -46,7 +46,7 @@ class LibraryManager: library_path: str, cache_dir: Optional[str] = None, page_size: Tuple[int, int] = (800, 1200), - books_per_page: int = 10 + books_per_page: int = 6 ): """ Initialize library manager. @@ -55,7 +55,7 @@ class LibraryManager: library_path: Path to directory containing EPUB files cache_dir: Optional cache directory for covers. If None, uses default. page_size: Page size for library view rendering - books_per_page: Number of books to display per page (must be even for 2-column layout) + books_per_page: Number of books to display per page (must be even for 2-column layout, default: 6) """ self.library_path = Path(library_path) self.page_size = page_size diff --git a/dreader/main.py b/dreader/main.py index efc3470..84b8e23 100644 --- a/dreader/main.py +++ b/dreader/main.py @@ -326,6 +326,11 @@ class DReaderApplication: """ Handle touch events in library mode. + Supports: + - TAP: Select a book to read + - SWIPE_LEFT: Next page + - SWIPE_RIGHT: Previous page + Args: event: Touch event """ @@ -341,6 +346,26 @@ class DReaderApplication: else: logger.debug("Tap did not hit a book") + elif event.gesture == GestureType.SWIPE_LEFT: + logger.debug("Library: swipe left (next page)") + if self.library.next_page(): + logger.info(f"Library: moved to page {self.library.current_page + 1}/{self.library.get_total_pages()}") + # Re-render library with new page + self.library.create_library_table() + self.current_image = self.library.render_library() + else: + logger.debug("Library: already on last page") + + elif event.gesture == GestureType.SWIPE_RIGHT: + logger.debug("Library: swipe right (previous page)") + if self.library.previous_page(): + logger.info(f"Library: moved to page {self.library.current_page + 1}/{self.library.get_total_pages()}") + # Re-render library with new page + self.library.create_library_table() + self.current_image = self.library.render_library() + else: + logger.debug("Library: already on first page") + async def _handle_reading_touch(self, event: TouchEvent): """ Handle touch events in reading mode. diff --git a/test_pagination_visual.py b/test_pagination_visual.py new file mode 100644 index 0000000..56de105 --- /dev/null +++ b/test_pagination_visual.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +""" +Test script to visualize library pagination. +""" + +from pathlib import Path +from dreader import LibraryManager + +def test_pagination(): + """Test pagination with actual library""" + library_path = Path(__file__).parent / 'tests' / 'data' / 'library-epub' + + # Create library manager (default books_per_page=6) + library = LibraryManager( + library_path=str(library_path), + page_size=(800, 1200) + ) + + # Scan library + books = library.scan_library() + print(f"\nFound {len(books)} books") + print(f"Books per page: {library.books_per_page}") + print(f"Total pages: {library.get_total_pages()}") + + # Render all pages + for page_num in range(library.get_total_pages()): + library.set_page(page_num) + print(f"\n=== Rendering Page {page_num + 1}/{library.get_total_pages()} ===") + + library.create_library_table() + img = library.render_library() + + output_path = f'/tmp/library_pagination_page{page_num + 1}.png' + img.save(output_path) + print(f"Saved to {output_path}") + + # Show which books are on this page + start_idx = page_num * library.books_per_page + end_idx = min(start_idx + library.books_per_page, len(books)) + page_books = books[start_idx:end_idx] + print(f"Books on this page ({len(page_books)}):") + for book in page_books: + print(f" - {book['title']} by {book['author']}") + + # Cleanup + library.cleanup() + print("\nPagination test complete!") + +if __name__ == '__main__': + test_pagination() diff --git a/tests/data/library-epub/pg34901-images-3.epub b/tests/data/library-epub/pg34901-images-3.epub new file mode 100644 index 0000000..b1cbdfa Binary files /dev/null and b/tests/data/library-epub/pg34901-images-3.epub differ diff --git a/tests/data/library-epub/pg43-images-3.epub b/tests/data/library-epub/pg43-images-3.epub new file mode 100644 index 0000000..28c95ac Binary files /dev/null and b/tests/data/library-epub/pg43-images-3.epub differ diff --git a/tests/test_library_interaction.py b/tests/test_library_interaction.py index e7badee..9ab2154 100644 --- a/tests/test_library_interaction.py +++ b/tests/test_library_interaction.py @@ -40,7 +40,7 @@ class TestLibraryInteraction(unittest.TestCase): self.assertIn('filename', book) def test_library_table_creation(self): - """Test that library table can be created""" + """Test that library table can be created with pagination""" books = self.library.scan_library() table = self.library.create_library_table() @@ -48,10 +48,12 @@ class TestLibraryInteraction(unittest.TestCase): self.assertIsNotNone(table) # Table should have body rows for 2-column grid layout + # With pagination, we only show books_per_page books, not all books + # Calculate expected rows based on current page's books + books_on_page = min(self.library.books_per_page, len(books) - (self.library.current_page * self.library.books_per_page)) # Each pair of books gets 2 rows (cover row + detail row) - # So N books = ceil(N/2) * 2 rows + expected_rows = ((books_on_page + 1) // 2) * 2 body_rows = list(table.body_rows()) - expected_rows = ((len(books) + 1) // 2) * 2 # Round up to nearest even number, then double self.assertEqual(len(body_rows), expected_rows) def test_library_rendering(self):