Commit Graph

544 Commits

Author SHA1 Message Date
dependabot[bot] 9f1563068f chore(deps): bump actions/checkout in the github-actions group (#243)
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/de0fac2e4500dabe0009e67214ff5f5447ce83dd...df4cb1c069e1874edd31b4311f1884172cec0e10)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
2026-06-05 09:42:38 -06:00
neon 913dab0ac5 feat(kobo/koreader): two way page level sync between kobo/koreader and bookorbit (#250)
* feat(kobo): support two-way progress sync

Implement two-way page-level reading progress synchronization between Kobo devices, KOReader, and BookOrbit. This ensures readers can switch between physical devices and the web app without losing their exact page-level reading position.

Closes #249

* fix(settings): restore thumbnail click preference

Restore the main branch thumbnail-click setting after the Kobo branch accidentally dropped it during the rebase. Keep the Kobo architecture allowlist aligned with the new identity service.

* fix(kobo): harden two-way progress sync fallbacks

Preserve Kobo bookmark metadata and tolerate null auth payloads/settings failures.

Cover review-reported regressions with focused tests.
2026-06-05 09:30:25 -06:00
neon cc7ab54a3b feat(settings): add option to change default thumbnail click behavior
Introduce a new display preference to control what happens when clicking
a book cover thumbnail. Users can now choose to open the book details
page instead of launching the reader directly.

Closes #240
2026-06-05 04:19:26 +00:00
neon ae8001d7ea fix(metadata): improve goodreads search relevance and ranking
Search results from Goodreads frequently surfaced study guides,
summaries, and companion books instead of the actual primary work
because they often shared similar titles.

To ensure the correct book is selected during metadata fetch, the
autocomplete ranking now heavily penalizes derivative works and boosts
items with high rating counts and strong author name overlap.
2026-06-04 16:42:26 +00:00
neon c2b956d54a feat(metadata): add genre blocklist to exclude unwanted tags
The genre blocklist allows users to define a global list of strings
that are prevented from being applied to a books genre field during
metadata fetches. Case-insensitive filtering executes directly inside
the metadata pipeline before merge strategies run, preventing unwanted
values from persisting across providers.

Closes #235
2026-06-04 16:09:00 +00:00
neon 1f94b3dac9 chore(cover): allow empty author in cover search queries
Remove the @IsNotEmpty() decorator from the author field in the
SearchCoversQueryDto so that empty strings do not trigger a validation
error on the cover search endpoint.
2026-06-03 23:44:32 +00:00
neon 6c7941c81b chore(client): update default dashboard scrollers configuration
Update DEFAULT_SCROLLERS to enable 'Recently Added', 'Discover Something
New', 'Continue Reading', and 'Continue Listening' in that specific order.
Disable 'Want to Read' and 'Up Next in Series' by default to streamline the
initial user experience.
2026-06-03 23:07:36 +00:00
neon 0257b4553e feat: add continue listening and want to read dashboard scrollers
Add dedicated dashboard scrollers for audiobooks and want-to-read lists to improve content discoverability. Previously, audiobook progress was merged with reading progress, making it difficult to find active audiobooks. Separate the queries to ensure audiobooks are handled exclusively by the new listening scroller and expose the user's want-to-read queue directly on the dashboard for easier access.
2026-06-03 22:14:04 +00:00
neon a1d0c2aef6 feat(series): add option to group books by media type
Add a "Group by media" toggle in the series detail view to separate
books, audiobooks, and comics into distinct sections. Persist the
user's selection preference to localStorage.

Closes #154
2026-06-03 21:20:27 +00:00
neon 57e2f39ec5 feat(opds): expose all content files for multi-format books
Select all acquisition content files from the database for each book
instead of only the primary file. Return multiple acquisition links
in the OPDS catalog feed for books available in multiple formats,
and update unit and E2E tests to verify catalog output and downloads.

Closes #224
2026-06-03 20:21:01 +00:00
neon 6bdb9dc7fc feat(series): implement 3d perspective fan and hero cover sorting for series stack
rearrange the fanned list of book covers so that the first book in a series sits in the center of the stack as the front-most hero, with subsequent books fanning out symmetrically on the sides. apply hardware-accelerated css 3d transforms for perspective, hover-container expansion, and hover-item lift, while keeping the scale transitions clean and subtle.
2026-06-03 18:27:05 +00:00
neon 936b907352 feat(series): add stack display mode for series thumbnails
Introduces a new 'stack' cover mode for series cards, rendering the covers
as a stacked pile. This mode has also been made the default for series card
display preferences. Settings UI is updated to allow users to toggle this
mode alongside existing mosaic and single-cover options.

Closes #223
2026-06-03 17:56:20 +00:00
neon efa300cecc fix(metadata): restore RanobeDB file metadata and links #207 #210
Preserve RanobeDB IDs through write-back, file import, and load-from-file so saved metadata survives round trips.

Expose saved RanobeDB sources in the book detail surfaces with the provider icon and database link.

Closes #207
Closes #210
2026-06-03 16:40:09 +00:00
neon 5adb046ee4 fix(series): prevent stretched background shadow on audiobooks
Square audiobook covers were using portrait dimensions for the background stack shadow, causing visual stretching. This updates the scale logic to detect square ratios and apply the correct 1:1 dimension.

Closes #221
2026-06-03 10:05:21 -06:00
neon 7e90576511 feat(books): remember show paths setting on files page
Use useLocalStorage from @vueuse/core to persist the show paths toggle state on the book details files page so the preference is remembered across visits.

Closes #212
2026-06-03 10:05:20 -06:00
neon c1bf268cc7 fix(client): deduplicate file format badges in list view
Filter out duplicate file formats in BookListRow so that audiobooks with many tracks do not flood the row with redundant tags.
2026-06-03 10:05:20 -06:00
Chris Mansell 06657a56a5 feat(books): write metadata directly to audiobook files (#219)
- Extend file write pipeline to write metadata fields directly into audiobook files.
- Map metadata fields to standard audio tag mappings and run ffmpeg to embed tags and cover art for M4B, M4A, MP3, and FLAC files.
- Update UI in edit metadata tab to show file write status and highlight written fields.

Handle edge cases in metadata extraction, file write-back status checks, and comic XML building. This ensures narrators are not incorrectly populated when they match the author/artist, preserves audibleId during chapter extraction, prevents whitespace issue numbers from breaking the XML, and improves the UI to clearly show why write-back is disabled.
2026-06-03 10:03:52 -06:00
Logan Selley 0627a34618 fix(kobo): re-deliver books removed on device while still eligible (#194)
Co-authored-by: Logan-Selley <logan@selleytech.com>
2026-06-03 09:08:30 -06:00
Daniel 0699aa9cec fix(series): prevent 404 for long series titles (#201) 2026-06-02 16:24:13 -06:00
neon 0208ba0b9e fix(reader): load correct chapter in web reader
Navigation sometimes treated stale rendered contents as successful navigation or failed silently when a section did not load properly. Ensure the target index matches the rendered content and throw on section load failure to prevent incorrect chapter display.

Closes #203
2026-06-02 21:29:29 +00:00
neon 45f252a7e6 fix(metadata): extract metadata from sidecar opf files
Ensure .opf sidecar files are processed alongside book files during
library scans and their metadata is extracted properly.

Closes #200
2026-06-02 12:53:21 -06:00
neon 73795767da fix(series): use numeric ID for routing to support long titles
Transition from title-based to ID-based routing for series to prevent
404 errors when a series has an excessively long title. This introduces
numeric IDs for series, backed by schema updates, and updates the
frontend router to use seriesId instead of seriesName.

Closes #198
2026-06-02 18:53:14 +00:00
Chris Mansell d06e65a42b feat(audio): embed cover image in audiobook files (#197)
* feat(audio): embed cover image in audiobook files

- Add audio cover embedder
- Implement format writers for M4B, M4A, MP3, and FLAC using ffmpeg
- Add library settings for audio file writes

Closes #145

* fix(library): disable audio file write by default and add ffmpeg timeout

Change the default value of file_write_audio_enabled from true to false in the database schema and migrations. Automatically disable audio writing in the UI if cover writing is toggled off. Add a 60-second timeout to the ffmpeg child process to prevent hanging when embedding covers.

---------

Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
2026-06-02 12:40:27 -06:00
neon befe6ef466 ci: upload codecov coverage for fork PRs
Allow public fork pull requests to upload coverage without repository secrets while keeping tokened uploads for trusted runs.

Use Codecov v6 so the action runs on Node 24.
2026-06-02 15:18:16 +00:00
neon 383506fc07 feat(reader): support peeking books without tracking progress
Implement a 'peek mode' that allows users to open and read books without updating their reading progress or creating reading sessions. Add a 'Peeking' banner in the reader and disable API calls in 'useReaderProgress' and 'useReadingSession' when tracking is disabled.

Closes #161
2026-06-02 05:34:05 +00:00
neon 3a29ac7679 fix(scanner): prevent nested folders from being marked missing
Virtual sibling cleanup is now deferred until the final missing pass instead of being handled eagerly during upsert. This ensures that real nested book folders are not prematurely marked as missing before their own candidates can be processed. A new validation step against the disk state guarantees only genuinely missing books are removed.

Closes #170
2026-06-02 04:52:25 +00:00
neon beb969a744 feat(reader): auto scroll table of contents to current chapter
Closes #193
2026-06-02 03:53:02 +00:00
neon 1b33a0a9c1 docs(readme): restructure layout and enhance feature presentation 2026-06-02 01:48:18 +00:00
neon 3a349c83b1 feat(book-dock): support custom container directory via BOOK_DOCK_PATH
The Book Dock directory inside the container was previously hardcoded to `/data/book-dock`. This adds support for the `BOOK_DOCK_PATH` environment variable, allowing users to customize the internal container directory where the Book Dock monitors for files. If the environment variable is not set, it defaults to the `book-dock` folder inside the configured app data path. This replaces the `BOOK_DROP_HOST_PATH` volume mapping in the compose file with a standard volume and environment variable approach.

Closes #178
2026-06-01 23:56:21 +00:00
neon f20efdeedd fix(book-dock): refine duplicate detection for books without isbn
The duplicate detection logic in BookDockFinalizeService previously identified books as duplicates if they had the same title, even if their authors differed, when ISBNs were unavailable. This has been updated to include author names in the duplicate check for books missing ISBNs to prevent incorrect duplicate identifications.

Closes #175
2026-06-01 23:20:34 +00:00
neon 9fd61d327a feat(client): support square audiobook covers and inline series cells
Refactors the virtual book table to render collapsed series as standard
inline cells (BookTableCollapsedSeriesCell) rather than full-width
rows, improving table alignment and layout consistency. Updates the
dashboard scroller and cover artwork components to support 1:1 aspect
ratios, ensuring audiobook covers are displayed correctly without
distortion.
2026-06-01 20:52:07 +00:00
neon 1baae51a32 feat(client): prevent audiobook cover cropping in series view
Closes #153
2026-06-01 18:29:52 +00:00
neon 2bdc88e2cc feat(dashboard): add up next in series to continue reading
Closes #162
2026-06-01 16:48:21 +00:00
neon 6d1cac52b3 fix(books): sync book context during lazy loading
Ensure the book context stays in sync when more books are loaded by lazy loading. Stop unregistering the loadMore handler when the list view unmounts so that metadata navigation continues working seamlessly after leaving the primary list view.

Closes #187
2026-06-01 15:54:49 +00:00
neon fe936822ba fix(smart-scope): prune deleted scopes from dashboard shelves
Remove stale smart-scope scrollers after smart scopes load so deleted shelves stop rendering and stop issuing invalid scroller requests.

Add dashboard config edge-case tests for prune, reset, and malformed storage normalization to prevent regressions.

Closes #189
2026-06-01 15:47:33 +00:00
neon af8a855b3b feat(metadata): fallback to search if lookup by id fails
Update the metadata fetch service to perform a fallback search when a provider's lookup by ID returns no result or an irrelevant candidate. This ensures that metadata retrieval can gracefully recover from incorrect or stale provider IDs.

Closes #182
2026-06-01 05:38:43 +00:00
neon 9111f84c47 fix(books): update date when metadata is auto fetched
Update the `updatedAt` field on the `books` table whenever book metadata is
automatically fetched or bulk updated. Additionally, filter codecov reports
to only include server coverage and ignore test/config files, and update
the README codecov badge to reflect this.

Closes #186
2026-06-01 05:07:59 +00:00
Chris Mansell 53a08788bc feat(metadata): add RanobeDB as metadata provider (#185)
* feat(metadata): add RanobeDB metadata provider

Introduces a new metadata provider to fetch book metadata from RanobeDB.

- Adds `ranobedb.client` to interact with the RanobeDB API.
- Implements `ranobedb.mapper` to map RanobeDB data to the internal metadata schema.
  - Maps native Japanese titles to subtitles.
  - Uses the original language as a fallback for the language field.
  - Parses specific release dates to determine the original publication year.
- Registers RanobeDB as an available provider in the preferences UI.
- Adds `ranobedb_id` to the metadata database schema.
- Removes the `bookId` override when manually performing a metadata search in the UI.

Closes #114
2026-05-31 22:56:40 -06:00
neon 7fca7af9d4 ci: upload server and client coverage reports to codecov (#183)
* ci: upload server and client coverage reports to codecov

Generate client lcov output and publish per-package coverage from CI so Codecov checks and README coverage artifacts stay up to date.

* ci: configure codecov project status and pr comments

* ci: isolate codecov coverage status by flags

* ci: add patch coverage status, per-flag badges, and client coverage scope

- Add patch coverage status in codecov.yml (server and client flags) so
  Codecov checks coverage on changed lines in PRs, not just overall trend
- Add include/exclude patterns to client vitest coverage config so test
  files and entry points are excluded from coverage stats
- Add per-flag server/client coverage badges to the README coverage section

* docs: restructure coverage map in README

Move the coverage map down to the documentation and contributing section, giving it its own heading. Remove the redundant server and client badges from the top.
2026-05-31 21:41:42 -06:00
neon 16e01f6b01 feat(settings): add option to show titles under grid cards (#181)
Add a user preference to configure the label displayed underneath book
and series cards in grid view. The option allows users to select
between hiding labels completely, showing book titles, or showing series
titles.

Closes #159
2026-05-31 19:37:28 -06:00
neon 66e3cd3954 fix(series): disable virtualization for series book grid
Virtualization can incorrectly hide books in the series detail view, showing only a small subset until the page is interacted with. This adds a static rendering mode to the book grid component and uses it for the series detail view to ensure all books remain visible.

Closes #171
2026-05-31 16:10:08 +00:00
neon 02262e3b3f fix(books): update metadata and locks atomically
When a newly filled metadata field is locked before saving, the subsequent
save causes a 409 conflict because the field was locked but not yet saved.
This introduces a new endpoint and DTO to update both metadata and locks
simultaneously, resolving the conflict.

Closes #172
2026-05-31 15:48:01 +00:00
neon 7a1b0120b8 feat(series): add selectable cover modes for collapsed series cards
Allow readers to choose which representative series cover appears in collapsed grid view so browsing can prioritize first, latest, or first unread volumes.

Closes #160
2026-05-31 15:10:00 +00:00
neon 0b3a96cbe3 fix(cover): make placeholder palettes react to theme accent
Unify accent metadata in one client module to prevent hue and tone drift across theme picker, chart palettes, and cover placeholders.

Guard placeholder theme-store access when Pinia is unavailable so non-store mounts remain stable while preserving reactive updates when a store is active.
2026-05-31 06:35:42 +00:00
neon cc7cbb13a1 fix(library): increase reading threshold constraint max to 100
The database check constraint for the library reading threshold was previously enforcing a maximum value of 1, causing an internal server error when configuring a threshold greater than 1% via the UI. The constraint max has been increased to 100 to support percentage-based values and align with the mark_as_finished constraint.

Closes #142
2026-05-31 01:22:11 +00:00
Chris Mansell 26b3c8ba18 feat(settings): add adaptive cover display preferences (#169)
Allow users to choose how cover artwork is fitted so mixed aspect ratios render cleanly in cards, lists, carousels, and widgets.

Persist display preferences through shared types and user-preferences endpoints so these settings stay consistent across sessions and devices.

Closes #152
2026-05-30 18:57:29 -06:00
MohammadYusif c37f668bed fix: percent-encode credentials when building DATABASE_URL (#126) (#167)
When DATABASE_URL is not provided, entrypoint.sh assembled it by
interpolating POSTGRES_USER, POSTGRES_PASSWORD and POSTGRES_DB directly
into a postgres:// URL. Any reserved URL character in those values (for
example a '#', '/' or '?' in the password) produced an invalid URL, and
pg-connection-string's new URL() call then threw ERR_INVALID_URL,
preventing the container from starting.

Percent-encode the user, password and database components via
encodeURIComponent before building the URL so passwords containing
special characters work without manual escaping.

Co-authored-by: MohammadYusif <MohammadYusif@users.noreply.github.com>
2026-05-30 18:57:08 -06:00
neon 3f6f7163d8 fix(auth): allow https in csp img-src for oidc provider icons (#140)
The Content Security Policy was previously blocking external images,
preventing admin-configured OIDC provider icons from loading.
This allows https: images to be loaded while continuing to block
plain http: to maintain mixed-content protection.

Closes #131
2026-05-30 12:28:09 -06:00
neon a1fe471e83 feat(settings): add theme persistence across devices
Introduce a user-preferences module and database schema to sync theme
settings (theme, accent, radius, background, brightness) across devices.
Users can now enable theme sync to persist their customization choices.

Closes #146
2026-05-30 17:27:08 +00:00
Chris Mansell 100334773c feat(metadata): add bulk metadata edit dialog (#164)
Add a dialog to batch-edit metadata for multiple selected books.

Support add/remove/replace/clear modes for list fields, with clear as an explicit
frontend-only mode.

Fix scalar input border rendering, year field validation/coercion, tags replace
optimistic updates, and submit error handling.

Closes #150
2026-05-30 11:21:27 -06:00