# Develop Changelog This file tracks changes on the `develop` line. `changelog.md` can later be used for release summaries. ## 2026-03-22 - Added blueprint/technical documentation structure in `docs/`. - Completed router split and bootstrap structure (`main.py`, routers, migrations, DB pool). - Expanded media support to EPUB/PDF/CBR/CBZ in import and scan flows. - Expanded Home UI with: - import dropzone for EPUB/PDF/CBR/CBZ - search functionality - alignment matching Library (search top-right, dropzone below) - Updated Library import texts and drag/drop filtering for multi-format support. - Expanded Library `New` view with: - `Grid`/`List` toggle - column visibility filter in `List` - multi-select + bulk `Remove from New` - selection only in `List` mode - `Shift+click` range selection on checkboxes - Added route: `POST /library/new/mark-reviewed` (bulk set `needs_review=false`). - Improved library performance: - `/api/library` fast-path (no full rescan on every page load) - optional `rescan=true` / `include_file_info=true` - SQL optimizations in `list_library_json()` - additional DB indexes for scale - Restored `/api/home` full dataset output: - `continue_reading` - `shorts_unread` - `novels_unread` - `shorts_read` - `novels_read` - Explicitly filtered series books out of Home sections. - Corrected Home read ordering: `shorts_read` and `novels_read` now show oldest first (`ORDER BY MAX(read_at) ASC`). - Restored Statistics page by returning the full `/api/stats` payload required for charts, favorites, top books, and reading history. - Improved backup implementation: - Dropbox token stored encrypted in DB - Dropbox backup root configurable via web UI and stored encrypted in DB - versioned snapshots + object-store deduplication in Dropbox (`library_snapshots` / `library_objects`) - configurable snapshot retention (`snapshots to keep`) via backup settings - object pruning based on retained snapshots - scheduled backup (enable + interval in hours) - backup runs as a background process, so page navigation does not block execution - stale running state recovery after restart/crash (old running logs marked interrupted/error) - dry-run support in the new flow - Updated Docker image with `postgresql-client` for `pg_dump`. - Multiple test builds pushed to `gitea.oskamp.info/ivooskamp/novela:dev`. ## 2026-03-25 (4) - Added {publisher} directory to PDF and CBR/CBZ paths: `pdf/{publisher}/{author}/{title}.pdf`, `comics/{publisher}/{author}/{title}.cbr/cbz` — consistent with EPUB structure ## 2026-03-25 (3) - Fixed CBZ extension in import: `common.make_rel_path` always generated `.cbr` for CBZ files; now accepts `ext` parameter; `library.py` passes actual suffix so CBZ files land at `comics/{author}/{title}.cbz` - Added missing `GET /download/{filename}` endpoint (referenced in book.html but was 404) - TECHNICAL.md fully rewritten: added File Storage Paths section, complete endpoint lists for all routers including settings.py, corrected path documentation ## 2026-03-25 (2) - Fixed PDF metadata editing (PATCH /library/book): - `_sync_epub_metadata` is now only called for `.epub` files; PDFs update DB only - `_make_rel_path` now includes the format prefix matching import: EPUB → `epub/{publisher}/{author}/…`, PDF → `pdf/{author}/{title}.pdf`, CBR/CBZ → `comics/{author}/{title}{ext}`; previously files were moved outside their format directory on metadata save - Fixed PDF reader (infinite loading screen): - `reader_page` now passes `format` (epub/pdf/cbr/cbz) to `reader.html` - Added `GET /api/pdf/info/{filename}` endpoint returning `{"page_count": N}` - `reader.html` branches on `FORMAT`: PDFs render page images from `/library/pdf/{filename}?page=N`, EPUB flow unchanged - PDF progress tracked per page; keyboard and button navigation work identically to EPUB - `Edit EPUB` button in Book Detail hidden for non-EPUB files ## 2026-03-23 - Added `All books` Grid/List toggle in Library: - same columns as `New` view (Publisher, Author, Series, Volume, Title, Has cover, Updated, Genres, Sub-genres, Tags, Status) - column visibility filter in `List` mode - no selection checkboxes or bulk actions - view mode and column visibility persisted separately in `localStorage` (`novela.all.viewMode`, `novela.all.visibleColumns`) - Added 1–5 star rating for books: - stored in the database (`rating SMALLINT DEFAULT 0`) - written to EPUB OPF as `` on rating change - written to CBZ `ComicInfo.xml` as `N` on rating change - CBR and PDF are DB-only (file format constraints) - rating is recovered from file metadata during rescan/DB rebuild (`upsert_book` preserves file rating over default 0) - stars displayed under the cover (outside `.book-info`) in all grid views (Library, Home) - stars in grid cards are display-only (no click) to prevent accidental taps while scrolling - stars in Book Detail are interactive (larger, 1.1rem), clicking same star removes rating - star color: amber (`#c8a03a`) for filled, `rgba(200, 160, 58, 0.25)` for unfilled — consistent across Library, Home, and Book Detail - Added text colour setting to reader hamburger menu: - 5 warm-tone presets from bright (`#e8e2d9`) to dim (`#938d86`) - active preset shown with accent-coloured ring - choice persisted in `localStorage` (`reader-text-colour`) and restored on next open - Increased spacing between hamburger button and back link in reader header (`margin-left: 1rem`) to prevent accidental taps - Removed `Cover Missing` auto-tag: - tag is no longer added on import, rescan, or grabber download - `ensure_cover_missing_tag()` removed from `common.py`, `library.py`, and `grabber.py` - startup migration removes all existing `Cover Missing` tags from the database - Fixed Tags/Genres/Sub-Genres not saving in book edit panel on desktop: - `,` (comma) now acts as a confirmation key alongside Enter in `PillInput` - `flush()` added to `PillInput`: any text still in the input field is auto-confirmed when Save is clicked - Fixed tag/genre search and tag-pill navigation being broken: - `renderGenreView` was filtering on `b.genres` (non-existent field); now uses `bookGenres()`, `bookSubgenres()`, `bookPlainTags()` - `renderSearchResults` had the same bug; search now covers title, author, genres, sub-genres, and tags