Commit Graph

596 Commits

Author SHA1 Message Date
neon 3fabadcf0d fix(kobo): use server reading streak on plugin dashboard
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
2026-07-26 22:27:26 +00:00
neon 8db3656633 build(deps): update dependencies across root, server, and client
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.
2026-07-26 22:03:55 +00:00
neon c0bd9ecf69 fix(smart-scope): handle invalid filters gracefully in count calculation
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
2026-07-26 21:08:51 +00:00
neon 9b2430a47e fix(server): allow google translate origin in content security policy
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
2026-07-26 19:17:33 +00:00
neon 3c6e8ed0d4 fix(scanner): annotate findBookFilesByBookIds return type
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.
2026-07-26 19:09:17 +00:00
neon bb6696c0d1 fix(cover): re-encode custom covers as baseline jpegs
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
2026-07-26 18:42:05 +00:00
neon b37335306c fix(smart-scope): enable series collapsing when scope contains saved series rules
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
2026-07-26 18:03:22 +00:00
neon a94f5068be fix(server): set ssl host from database url in postgres client config
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
2026-07-26 17:50:21 +00:00
neon bcc80d7bf4 fix(books): hash duplicate scan keys to prevent btree index overflow
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 #762

Closes #768
2026-07-26 17:28:38 +00:00
neon d4b6f65791 fix(server): send HSTS header conditionally for HTTPS requests
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
2026-07-26 17:02:45 +00:00
neon b1357457fe fix(scanner): suppress file watcher events during internal file writes
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.
2026-07-23 06:06:06 +00:00
neon 58c5b422d3 feat(scanner): align bookdock duplicate detection with upload behavior
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
2026-07-22 20:06:49 +00:00
neon fb93f6ec20 fix(kobo): support GET request on analytics gettests endpoint
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
2026-07-22 17:39:45 +00:00
neon 596284c389 feat(settings): expand accent color palette options
Add vivid and pastel accent color choices across client themes, user preferences, and shared types.
2026-07-22 16:47:06 +00:00
neon 0cacd0b9b8 fix(scanner): re-evaluate primary file format priority on upload
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
2026-07-22 15:21:33 +00:00
neon a38288b1a2 fix(books): join metadata table when resolving query-based book ids
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
2026-07-22 06:31:31 +00:00
neon 0ee6cfe7ec fix(metadata): normalize book dock metadata schema and field sources
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
2026-07-22 05:26:31 +00:00
neon ac129ce754 fix(cover): write compliant epub cover images and metadata structures
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
2026-07-22 04:55:28 +00:00
neon 544f4d5e53 fix(books): respect library cover aspect ratio for combined media books
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
2026-07-22 04:12:13 +00:00
chooh2 d051039a2d fix(storygraph): preserve reading attempt start date (#687)
* 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>
2026-07-21 21:48:44 -06:00
dependabot[bot] 4ecc44b2e5 chore(deps): bump the production-dependencies group with 15 updates (#714)
Bumps the production-dependencies group with 15 updates:

| Package | From | To |
| --- | --- | --- |
| [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) | `4.3.2` | `4.3.3` |
| [@tanstack/vue-virtual](https://github.com/TanStack/virtual/tree/HEAD/packages/vue-virtual) | `3.13.31` | `3.13.32` |
| [@tiptap/extension-link](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/extension-link) | `3.27.3` | `3.28.0` |
| [@tiptap/pm](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/pm) | `3.27.3` | `3.28.0` |
| [@tiptap/starter-kit](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/starter-kit) | `3.27.3` | `3.28.0` |
| [@tiptap/vue-3](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/vue-3) | `3.27.3` | `3.28.0` |
| [dompurify](https://github.com/cure53/DOMPurify) | `3.4.11` | `3.4.12` |
| [driver.js](https://github.com/nilbuild/driver.js) | `1.6.0` | `1.7.0` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) | `4.3.2` | `4.3.3` |
| [vue](https://github.com/vuejs/core) | `3.5.39` | `3.5.40` |
| [vue-router](https://github.com/vuejs/router) | `5.1.0` | `5.2.0` |
| [@fastify/compress](https://github.com/fastify/fastify-compress) | `9.0.0` | `9.1.0` |
| [@fastify/cookie](https://github.com/fastify/fastify-cookie) | `11.1.1` | `11.1.2` |
| [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) | `5.9.3` | `5.10.1` |
| [mysql2](https://github.com/sidorares/node-mysql2) | `3.22.6` | `3.23.0` |


Updates `@tailwindcss/vite` from 4.3.2 to 4.3.3
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.3/packages/@tailwindcss-vite)

Updates `@tanstack/vue-virtual` from 3.13.31 to 3.13.32
- [Release notes](https://github.com/TanStack/virtual/releases)
- [Changelog](https://github.com/TanStack/virtual/blob/main/packages/vue-virtual/CHANGELOG.md)
- [Commits](https://github.com/TanStack/virtual/commits/@tanstack/vue-virtual@3.13.32/packages/vue-virtual)

Updates `@tiptap/extension-link` from 3.27.3 to 3.28.0
- [Release notes](https://github.com/ueberdosis/tiptap/releases)
- [Changelog](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-link/CHANGELOG.md)
- [Commits](https://github.com/ueberdosis/tiptap/commits/v3.28.0/packages/extension-link)

Updates `@tiptap/pm` from 3.27.3 to 3.28.0
- [Release notes](https://github.com/ueberdosis/tiptap/releases)
- [Changelog](https://github.com/ueberdosis/tiptap/blob/main/packages/pm/CHANGELOG.md)
- [Commits](https://github.com/ueberdosis/tiptap/commits/v3.28.0/packages/pm)

Updates `@tiptap/starter-kit` from 3.27.3 to 3.28.0
- [Release notes](https://github.com/ueberdosis/tiptap/releases)
- [Changelog](https://github.com/ueberdosis/tiptap/blob/main/packages/starter-kit/CHANGELOG.md)
- [Commits](https://github.com/ueberdosis/tiptap/commits/v3.28.0/packages/starter-kit)

Updates `@tiptap/vue-3` from 3.27.3 to 3.28.0
- [Release notes](https://github.com/ueberdosis/tiptap/releases)
- [Changelog](https://github.com/ueberdosis/tiptap/blob/main/packages/vue-3/CHANGELOG.md)
- [Commits](https://github.com/ueberdosis/tiptap/commits/v3.28.0/packages/vue-3)

Updates `dompurify` from 3.4.11 to 3.4.12
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.11...3.4.12)

Updates `driver.js` from 1.6.0 to 1.7.0
- [Release notes](https://github.com/nilbuild/driver.js/releases)
- [Commits](https://github.com/nilbuild/driver.js/compare/1.6.0...1.7.0)

Updates `tailwindcss` from 4.3.2 to 4.3.3
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.3/packages/tailwindcss)

Updates `vue` from 3.5.39 to 3.5.40
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.5.39...v3.5.40)

Updates `vue-router` from 5.1.0 to 5.2.0
- [Release notes](https://github.com/vuejs/router/releases)
- [Commits](https://github.com/vuejs/router/compare/v5.1.0...v5.2.0)

Updates `@fastify/compress` from 9.0.0 to 9.1.0
- [Release notes](https://github.com/fastify/fastify-compress/releases)
- [Commits](https://github.com/fastify/fastify-compress/compare/v9.0.0...v9.1.0)

Updates `@fastify/cookie` from 11.1.1 to 11.1.2
- [Release notes](https://github.com/fastify/fastify-cookie/releases)
- [Commits](https://github.com/fastify/fastify-cookie/compare/v11.1.1...v11.1.2)

Updates `fast-xml-parser` from 5.9.3 to 5.10.1
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.9.3...v5.10.1)

Updates `mysql2` from 3.22.6 to 3.23.0
- [Release notes](https://github.com/sidorares/node-mysql2/releases)
- [Changelog](https://github.com/sidorares/node-mysql2/blob/master/Changelog.md)
- [Commits](https://github.com/sidorares/node-mysql2/compare/v3.22.6...v3.23.0)

---
updated-dependencies:
- dependency-name: "@tailwindcss/vite"
  dependency-version: 4.3.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@tanstack/vue-virtual"
  dependency-version: 3.13.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@tiptap/extension-link"
  dependency-version: 3.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: "@tiptap/pm"
  dependency-version: 3.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: "@tiptap/starter-kit"
  dependency-version: 3.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: "@tiptap/vue-3"
  dependency-version: 3.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: dompurify
  dependency-version: 3.4.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: driver.js
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: tailwindcss
  dependency-version: 4.3.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: vue
  dependency-version: 3.5.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: vue-router
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: "@fastify/compress"
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: "@fastify/cookie"
  dependency-version: 11.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: fast-xml-parser
  dependency-version: 5.10.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: mysql2
  dependency-version: 3.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-21 20:03:56 -06:00
neon 06286d49b1 fix(metadata): persist hardcover and open library ids during book dock import
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
2026-07-16 05:45:36 +00:00
neon 095b347aff feat(books): add jump rail display preference
Let readers disable jump rails from grid display controls and skip bucket queries while the preference is off.
2026-07-15 22:32:59 -06:00
neon 504c9ce0e7 feat(books): expand and refine library jump navigation
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.
2026-07-15 22:32:59 -06:00
neon 5923ea95a5 feat(books): add adaptive temporal jump rail
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.
2026-07-15 22:32:58 -06:00
neon f6394a9b0c security: remediate dependency and code scanning alerts
Upgrade vulnerable transitive dependencies and harden filesystem, URL, HTML, cryptographic, and input-processing boundaries identified by security scans.
2026-07-15 18:42:07 +00:00
neon 876e32654a feat(client): support system theme mode
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
2026-07-15 15:22:15 +00:00
neon 8c8293b797 fix(stats): convert postgres storage sum from string to number
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
2026-07-15 15:01:28 +00:00
neon ed5dbc9507 feat(books): add duplicate book detection and resolution tools
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.
2026-07-15 05:20:16 +00:00
neon 07b1ddb150 fix(annotations): filter out deleted highlights in highlight widget
Add isNull(annotations.deletedAt) condition to both count and offset queries in DashboardWidgetRepository to prevent soft-deleted annotations from being selected for the Highlight of the Day widget.

Closes #685
2026-07-14 11:53:57 -06:00
Jadehawk ec84703cef feat(koreader): enhance settings and plugin behavior (#669)
* feat(koreader): add device file naming and improve plugin downloads (BO-658)

* fix(koreader): secure download paths and test collisions

* fix(koreader): preserve bulk collision identities

* fix(koreader): improve device file naming validation and path generation

* fix(koreader): remove duplicate settings lookup and audit file naming changes

* fix(koreader): resolve remaining CodeRabbit review issues

* fix(koreader): validate book detail query and finalize file naming release

validate book detail deviceId via DTO and ValidationPipe

localize new KOReader file naming settings (de, nl, sl)

bump KOReader plugin version to 1.3.0

* chore: rerun CI

* chore: normalized Closes #658 to not have embedded URL to issue. This is failing PR Conventions test

* test(koreader): align source and device removal assertions

* test(koreader): cover file naming settings flows

* test(koreader): cover file naming sync requests

* test(koreader): close remaining patch coverage gaps

* test(koreader): cover file naming server paths

* docs: add fixed2 modifier to file naming reference

* feat(koreader): support custom file naming patterns for KOReader sync

Add support for configurable KOReader file naming patterns, allowing users to define dynamic path templates for sync targets. Include UI draft settings, preview updates, and server path resolution.

Closes #658

---------

Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
Co-authored-by: jadehawk <jadehawk@hotmail.com>
2026-07-14 11:26:27 -06:00
neon 72a56575c7 fix(metadata): support mp4 native series tags in audio format writer and extractor
Write and extract MP4-native series tags ('show', 'episode_id', 'episode_sort') for M4B and M4A audio files alongside existing custom tags to ensure series metadata is preserved during tag extraction and library scans.

Closes #680
2026-07-13 20:44:52 +00:00
neon 214d887dd1 fix(authors): allow closing author enrichment progress notification
Ensure author enrichment progress notifications can be dismissed and resolve stuck status indicators that persist on screen after completion or matching failures.

Closes #678
2026-07-13 19:39:18 +00:00
neon 74e0e6112a fix(library): filter entity duplicate detection by accessible libraries
Ensure entity manager strategies and duplicate computation restrict book references and candidate entities to libraries accessible by the current user.

Closes #664
2026-07-13 19:09:57 +00:00
neon 4c88c15365 db(library): add missing foreign key indexes for deletion
Add indexes on foreign key columns referencing books, book files, and libraries across user activity and integration tables to prevent table scans during cascade deletes.

Closes #663
2026-07-13 18:50:44 +00:00
neon 353421ded0 fix(kobo): preserve reading session duration without subtracting idle time
Kobo devices report active reading duration in SecondsRead. Subtracting IdleTime reduced session durations incorrectly, preventing reading logs from populating accurately.

Closes #653
2026-07-13 05:59:14 +00:00
neon 45e0bed6e3 fix(metadata): fallback to file name when book dock title is missing
Use the cleaned file stem as the search title when searching for book dock metadata if no title is present in embedded or selected metadata.

Closes #655
2026-07-13 05:40:50 +00:00
Chris Mansell a7c281955a feat(stats): expose privacy-aware reading insights (#662)
* build(deps): synchronize i18n lockfile

Record the locale dependencies so frozen installs can resolve the client workspace.

* feat(stats): expose privacy-aware reading insights

- Give administrators permission-gated access to bounded account activity.
- Let readers opt into auditable shared reading insights.

Ref #501
2026-07-12 23:11:35 -06:00
neon c70ff593ca fix(kobo): prevent reading state sync feedback loop (#657)
Exclude the originating device from reading-state fan-out and ignore stale or identical state echoes so paginated syncs can advance. Preserve pending new entitlements while propagating genuine changes to other devices.

Closes #654
2026-07-12 23:10:43 -06:00
Dennis van der Stelt 31bda18c9a feat(i18n): add multi-language support with Dutch translation (#500)
* feat(i18n): add vue-i18n foundation with language switcher and Dutch locale

Introduce multi-language support for the client using vue-i18n and
@intlify/unplugin-vue-i18n. Locale is detected from a stored preference
or the browser language and persisted client-first, with optional server
sync riding the existing theme-sync mechanism (new locale category on the
generic user_preferences store, no migration needed).

Adds a language selector in Appearance > Behavior settings and seeds
en/nl message catalogs. Extraction of existing hardcoded strings follows
in subsequent commits.

* feat(i18n): add full en/nl message catalogs and test/build wiring

Populate the English and Dutch message catalogs (~4300 keys) covering the
whole UI, register a vitest setup that installs vue-i18n globally so
component tests resolve real messages, and allow inline HTML in messages
(strictMessage/escapeHtml off) for notes rendered via v-html / <i18n-t>.

* feat(i18n): localize settings and book UI strings

Replace hardcoded strings with t() calls across the settings and book
feature areas (including book detail, table, metadata edit, reading log,
highlights). Label collections captured at setup are wrapped in computed()
so they react to locale changes.

* feat(i18n): localize remaining feature UI strings

Replace hardcoded strings with t() across reader, email, library, tools,
migration, dashboard, auth, hardcover, author, series, book-dock,
book-metadata-fetch, annotations, admin, statistics, collection,
smart-scope, audit, whats-new, achievements, notifications, custom-icons,
scanner and metadata-score. Reactive label maps use computed().

* feat(i18n): localize shared components and view wrappers

Replace hardcoded strings with t() across shared components (app header,
sidebar, view header, pickers, selection bar) and top-level views.

* feat(i18n): localize settings tab bars and browser page titles

Make settings tab labels reactive via t() in the consuming components and
slim the *-tabs.ts helpers to ids/order/permission only. Route the browser
page titles in the router through the app i18n instance so document.title
follows the active locale. Adds settings.<area>.tabs.* and titles.* keys.

* feat(i18n): localize KOReader hash-linking and reader sidebar pin

Localize the strings from the KOReader manual hash-linking feature and the
reader sidebar pin/close controls that were merged from main during the
rebase, adding the corresponding en/nl keys.

* feat(i18n): localize upstream features merged during rebase onto main

Add en/nl catalog keys for the new upstream functionality pulled in by the
rebase (Kobo activity log, KOReader dismiss/remove-device and hash-link
modal, default library access, upload-size settings) and update a few
existing keys whose wording changed upstream (dynamic upload-size hints,
write-and-rename phrasing).

* feat(i18n): switch language picker to a dropdown

Replace the segmented language buttons with a native select, which scales
better as more locales are added.

* feat(i18n): add German and Slovenian translations

Register de and sl in the supported locales and ship full de.json and
sl.json catalogs (4616 keys each, structural parity with en.json).

* fix(client): harden locale switching and translation coverage

Keep locale catalogs structurally aligned, localize rebased UI changes, and use locale-aware formatting. Move language selection into the header, persist authenticated preferences, and prevent stale locale loads from winning.

---------

Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
2026-07-12 15:07:29 -06:00
neon f68a3ca98e feat(stats): add reading attempt history
Track repeat reads as distinct attempts while preserving existing status flows, device integrations, goals, sessions, and legacy data.

Closes #652
2026-07-12 17:41:35 +00:00
neon eac0917d22 fix(metadata): improve Libro.fm metadata integration
Persist Libro.fm identifiers across metadata refresh, editing, file round trips, and provider links. Enable explicitly selected audiobook providers during Auto-fill and retain AudNexus ASINs as Audible identifiers.
2026-07-12 07:06:42 +00:00
neon 5e03f92037 fix(annotations): open non-epub annotations in correct reader
Retrieve the book file format when querying the annotation hub, and dynamically determine the router parameters for navigation. This prevents hardcoding the epub format and correctly routes fb2 and other non-epub format annotations to their respective readers.

Closes #634
2026-07-12 06:19:42 +00:00
neon 37d3df4089 feat(metadata): add Libro.fm as a metadata source
Introduce a metadata provider for Libro.fm to fetch audiobook details, offering an alternative to Audible and iTunes. Add server-side mapping, fetch controller endpoints, validation DTOs, and client-side UI configurations for user metadata preferences.

Closes #636
2026-07-12 05:53:45 +00:00
neon 2d404af640 security(deps): rebuild kepubify with go 1.26.5
Rebuild the bundled binaries with the patched Go standard library to resolve CVE-2026-39822.
2026-07-11 20:20:06 +00:00
neon 95a7b94184 fix(scanner): support bigint inodes to prevent folder mis-merges
Store file inodes as numeric rather than bigint on PostgreSQL, and read/process them as BigInt in Node.js. This preserves exact 64-bit inodes from filesystems like MergerFS (hybrid-hash) and avoids folder mis-merging or disabled rename detection.

Closes #618
2026-07-11 20:18:10 +00:00
neon d182d913c6 fix(books): support accent-insensitive search
Install the PostgreSQL unaccent extension and use a custom immutable wrapper function to perform accent-insensitive ILIKE comparisons when searching for books, authors, series, and narrators. Add database indexes on the unaccented values to maintain query performance.

Closes #640
2026-07-11 17:47:29 +00:00
neon 89545e6c69 fix(storygraph): skip progress sync on read transition
Updating status to read on StoryGraph automatically logs the remaining page count. Sending a
subsequent progress update for the full book page count would create a duplicate journal entry,
inflating the logged page count. Skip the progress update when transitioning to the read status.

Closes #643
2026-07-11 17:06:49 +00:00
neon 568bf9dd6f fix(kobo): strip leading v from server version in koreader plugin
The KOReader plugin's update check response provides the server version,
which already contains a leading "v". The update and plugin popups in
the KOReader plugin format the version with an explicit "v" prefix,
resulting in a "vv" typo (e.g. "vv1.2.0").

Strip the leading "v" from the server version in the updater script
if present to ensure it is displayed with a single "v" prefix.

Closes #644
2026-07-11 17:02:32 +00:00
neon 870abecb01 feat(reader): polish the PDF reading experience
Make long PDF reading sessions easier to navigate across desktop and mobile. Keep document loading recoverable when EmbedPDF initializes or tears down out of order, without enabling document-editing capabilities.
2026-07-11 15:29:34 +00:00