Add server endpoints and KOReader plugin settings to render configurable dashboard section rows, such as Smart Scopes or custom scrollers, replacing the hardcoded Discover section. Update the plugin capability checks to fall back gracefully on older server versions.
Lifecycle handlers previously blocked on network work, so closing or suspending a book stalled the
device on slow or offline links. Persist snapshots first and drain them through a lifecycle outbox
with connected-state gates and phase-aware retries, so the UI stays responsive and pending work
survives restarts.
Move persistence behind a state manager with atomic flushes, and chunk sweeps, bulk downloads, and
annotation exchange through a background queue with checkpoints and transfer policies, so large
libraries make progress incrementally instead of restarting from scratch after an interruption.
Server side, add bulk manifest and page stats endpoints with batched queries and catalog query
filtering so the plugin can reconcile many books per round trip rather than one request per book.
Add automated Crowdin translation progress SVG chart generator, test, and workflow. Consolidate star history and translation stats generation into unified repo-charts workflow, and update README links.
Ensure metadata score calculations are awaited when book metadata or covers are saved or updated, and add concurrency queuing for on-demand score recalculations.
Expand audit log entries to record detailed resource metadata (such as book titles on deletion), and add rich filtering by action, actor, and resource in the audit log viewer UI.
Closes#747
Allow users to adjust the gap between pages when reading comics in two-page spread mode. Include backend preference validation, shared settings defaults, translation keys, and reader settings UI controls.
Closes#740
Replace pipe-delimited Vue I18n plural messages with ICU MessageFormat syntax across all locale catalogs and Vue components. Configure custom message formatting and validation to enforce ICU syntax and argument parity.
Closes#792
* i18n(client): sync Portuguese, Brazilian translations from Crowdin
Keep translated catalogs synchronized with reviewed Crowdin content.
* i18n(client): sync German translations from Crowdin
Keep translated catalogs synchronized with reviewed Crowdin content.
* i18n(client): restore Portuguese plural fallbacks
Keep the Crowdin sync mergeable while the malformed translations are
corrected at their source.
* fix(reader): fall back to percentage jump when kosync response has no xpointer
The KOReader plugin's progress pull calls syncToProgress(body.progress),
which fires GotoXPointer(nil) or GotoPage(nil) when body.progress is nil.
Both silently no-op, so the reader position does not move and the user
sees 'Progress has been synchronized.' with nothing changing.
This happens whenever the kosync response has percentage-only progress
(e.g. progress written by the BookOrbit web reader, or by an external
audiobook->ebook progress bridge that only knows the percentage, not
an EPUB xpointer). hasUsableRemoteProgress already guards this case in
reconcileProgressBeforeBookSync, but getProgress / applyRemoteProgress
never got the same guard.
Extend syncToProgress to accept an optional percentage_fallback (0-1,
kosync scale). When there is no usable xpointer/page but a fallback
percentage is present, fire GotoPercent (0-100 scale) so the reader
actually jumps.
* fix(reader): apply percentage fallback in pre-book-sync reconcile
Drop the hasUsableRemoteProgress short-circuit so the reconcile that runs before a manual book
sync behaves like the pull paths. Now that syncToProgress falls back to a percentage jump, the
two flows disagreed on identical data: a manual pull moved the reader while the pre-sync
reconcile reported "no exact location" and changed nothing, which also left the percentage
argument passed to applyRemoteProgress unreachable.
An earlier guard already returns when body.percentage is absent, so every response reaching this
point can resolve a target. The strategy branches keep the conservative path intact: DISABLE
still skips the progress push when the remote is newer.
---------
Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
Prefer the server account reading streak when provided by the dashboard endpoint, falling back to local KOReader statistics database data when offline or absent. This aligns the KOReader plugin day streak display with the web app.
Closes#711
Update dependency versions across root, server, and client package files and refresh the lockfile.
Upgrade @fastify/static to the patched major release and verify production static-serving compatibility.
Validate smart scope filter rules before constructing query clauses during count computation. Catch validation errors for broken rules so invalid filters return null for bookCount rather than triggering an internal server error when fetching all smart scopes.
Closes#787
Add translate.googleapis.com to the connect-src Content-Security-Policy directive so the built-in eBook reader's translation feature can perform fetch requests without being blocked by CSP.
Closes#786
Add an explicit return type to findBookFilesByBookIds so TypeScript
resolves the bookFiles row shape instead of collapsing it to an index
signature, which broke structural typing against fileStateMatches.
Re-encode uploaded progressive JPEG custom cover images to baseline JPEG format so they render correctly across OPDS clients that lack progressive JPEG support.
Closes#782
Separate transient query filter rules from saved smart scope rules when evaluating series collapsing eligibility so series collapse as expected when requested in smart scopes.
Closes#780
When creating Postgres connection clients or pools, pg-connection-string
parsed SSL configurations did not explicitly set the SSL host matching
the database host, causing hostname verification failures against
localhost when DATABASE_URL specified an external host.
Use a helper to construct postgres client configurations that set the
SSL host from the parsed DATABASE_URL host across the server database
module and CLI scripts.
Closes#778
Raw file hash and exact metadata signatures can exceed PostgreSQL's btree tuple size limit (2704 bytes) for books with large file counts or long author lists, causing duplicate scans to fail. Hashing signature values with md5 ensures indexed duplicate scan keys maintain a fixed length within PostgreSQL index limits.
Closes#762Closes#768
Disable default HSTS header in fastifyHelmet and register an onSend hook that includes Strict-Transport-Security only when request protocol is HTTPS. This prevents unencrypted HTTP setups and other services on the host from being forced onto HTTPS by browser HSTS caching.
Closes#760
Register internally written and renamed library files with a self-write registry to prevent the file watcher from triggering redundant rescan events during application file operations.
Update metadata and cover editing components to align UI state handling with self-write updates.
Replace metadata-based duplicate checks (ISBN, title/author) during BookDock finalization with destination path lookup. This allows books with shared or incorrect metadata to be imported whenever their resolved library target paths differ, matching the standard upload workflow.
Closes#736
Kobo devices send GET requests to /v1/analytics/gettests during sync checks. Previously only POST was handled, causing 404 errors during subsequent syncs.
Closes#697
Re-evaluate the library format priority when uploading additional files to an existing book so higher-priority file formats properly take over as the primary file.
Closes#755
Update the header documentation URL and README links to use clean routes without the legacy .html extension, resolving broken navigation links.
Closes#754
Query-based book selections failed with a 500 error when filtering by metadata fields because findIdsByWhere queried the bare books table without joining book_metadata. Left join book_metadata so WHERE clause predicates referencing metadata fields resolve correctly.
Closes#732
Virtualize CBZ strip pages using TanStack Virtual to reliably anchor
and update reading position during continuous scrolling, prevent initial
zero-page overwrites when reopening the reader, and flush pending progress
saves when navigating away.
Fixes#735
Normalize legacy and invalid fields in BookDock metadata objects before returning them to the client or processing DTO updates. This prevents unexpected properties such as legacy duration keys or extra rating attributes from failing DTO validation during file updates and finalize operations.
Closes#729
Ensure EPUB cover image updates produce standards-compliant EPUB2 and
EPUB3 metadata, manifest items, guide entries, and landmarks so e-readers
such as Readest and KOReader can render updated covers correctly.
Closes#730
Books containing both ebook and audiobook formats were incorrectly rendered with square covers in dashboard widgets, series views, and cards because aspect ratio logic checked for any audio format file instead of relying on the configured cover aspect ratio or primary media profile.
Closes#712
* fix(storygraph): preserve reading attempt start date
Skip redundant active-reading status updates before syncing progress so StoryGraph keeps the existing reading attempt and start date.
Fixes#667
* test(storygraph): cover active status equivalence
Exercise exact and cross-mapped active reading statuses so patch coverage verifies every start-date preservation path.
* test(storygraph): complete active status matrix
Cover the exact rereading status pair and retain literal tuple types for every active-reading equivalence case.
---------
Co-authored-by: chooh2 <chooh2@users.noreply.github.com>
Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
Pass external provider IDs (including Hardcover and Open Library IDs) from book dock metadata selection through ingest and finalization so they are saved to book metadata on import.
Closes#704
Extend jump rails across alphabetical, temporal, and categorical sorts.
Keep large libraries responsive with bounded database buckets and exact offsets.
Refine active-state tracking, Unicode initials, localized labels, accessibility, adaptive sizing, and flat or collapsed-series navigation.
Add bounded, user-scoped temporal buckets for supported date sorts and adapt resolution to populated dates. Keep rail navigation responsive with viewport sizing, sparse-gap compression, and virtual-grid synchronization.
Add system preference option for appearance theme with auto-switching based on OS color scheme settings. Update default theme preference to system and listen for OS dark mode changes dynamically.
Closes#695
Parse the sum aggregation for book file sizes as a JavaScript number to match the statistics API contract, preventing missing values in the library stats overview.
Closes#696
Introduce backend duplicate scanning services, persistence schemas, and frontend view components to allow users to scan their library for duplicate books by title/author similarity, group potential matches, and bulk delete redundant duplicates safely.