Commit Graph

775 Commits

Author SHA1 Message Date
neon da5d0bb405 fix(reader): start read along at the selected narrated sentence
"Read from here" and the page start resolved the range to the nearest element with any id and
matched SMIL entries against that id. Storyteller keeps the book's inline elements inside its
sentence spans with their ids intact (Kobo's kobo.N.N, calibre's calibre_link-N), so in those
books the nearest id named no entry and narration restarted at the top of the chapter, while
playback kept highlighting the same sentences correctly.

Start at the first SMIL entry whose element overlaps the range instead, looking each entry up the
way foliate resolves the highlight. Foliate already walks entries in reading order through the
start filter, so the vendored engine is unchanged.

Fixes #1528
2026-09-24 13:15:24 +00:00
neon e28bd67fa3 feat(cover): give books with both media separate ebook and audiobook covers
Keep one cover slot per medium and show the one each surface needs: the
library's shape for the face, square art on audio screens, the ebook slot
for Kobo and OPDS. Legacy covers convert on upgrade or on first read, and a
write that names no slot keeps working for released iOS builds. Also read
the dev client origin from one constant.
2026-09-23 19:55:25 +00:00
neon 4b86ff73cf build: move local development off port 3000
Run the dev API on 6262 and Vite on 6263 with strictPort; production
defaults stay on 3000. Define the dev client origin once and read the
typed appConfig instead of repeating its fallback in every gateway.
2026-09-23 18:18:51 +00:00
neon 1dd29c742f fix(auth): keep signed-out reset links on their page
Load read-aloud voices only once playback starts, so the app-wide player
no longer fires a 401 on public pages. Let the session-failure handler
clear auth without leaving a public route, which also keeps magic links
and the sign-in redirect intact.

Fixes #1503
2026-09-23 13:02:00 +00:00
neon 3c032e0e3c fix(reader): sync progress between an EPUB and its read-along copy
Carry positions between sibling EPUBs even without an audiobook, and keep
narration markers on the read-along file only. Point the KOReader book panel
and hold release at the copy devices sync, and label EPUB-only sync in the
read-aloud panel.

Fixes #1508
2026-09-23 12:30:01 +00:00
neon 27cfdc2028 fix(client): keep confirmation dialogs above sheets
Raise shared confirmation layers above sheet overlays so mouse input reaches privilege-change prompts.

Fixes #1502
2026-09-23 01:40:28 +00:00
neon bc10ebcc33 feat(stats): record android as a reading source
Accept android as a reading-session source from clients and report it as
its own statistics bucket, labelled Android app, beside the iOS app and
Apple Watch. A generated migration adds it to the reading_sessions check
constraint, achievements count Android reading toward Full Orbit and Two
Worlds, and the web charts draw it in a new --pill-android token at hue 95.
2026-09-23 01:34:19 +00:00
neon 6fa4d68728 fix(reader): prevent duplicate media overlay playback
Wait for the requested SMIL fragment to resolve before falling back, and invalidate stale audio loads so overlapping starts cannot orphan playback.

Fixes #1477
2026-09-22 11:38:28 +00:00
neon 12cf724c39 fix(books): align progress bar color with read status
Use the authoritative read status so cards completed at a library's configured threshold no longer appear in progress.

Fixes #1465
2026-09-22 11:11:24 +00:00
neon 926f5de225 fix(reader): preserve narration highlights across themes
Use the EPUB media-overlay active class and a theme-aware highlight variable so forced page backgrounds cannot hide the narrated sentence.

Fixes #1479
2026-09-22 10:52:32 +00:00
neon 304ccd5640 fix(reader): preserve iOS text selection adjustment
Keep pagination and the selection popup idle until native selection gestures finish, including cancelled touches.

Cover paginated and scrolled flows while retaining ordinary swipe snapping.

Closes #1487
2026-09-22 10:19:38 +00:00
neon 3bdd25e968 test(client): type the recorded request bodies
The new assertions read `apiMock.mock.calls[0][1].body` straight off an `unknown`, which vitest
runs happily and `vue-tsc` rejects. Read them through one typed helper instead.
2026-09-21 17:29:36 +00:00
neon d87312a8ca fix(client): send only the reader settings that changed
Every settings write from the reader PUT the whole object: the defaults write sent all twenty-one
EPUB fields and the per-book write sent the entire accumulated delta. PUT replaces the stored row,
so a write from this client threw away whatever another one had set since the page loaded.

That is a real conflict now rather than a theoretical one. The iOS reader owns the look fields and
keeps the layout fields on the device, so it writes a small subset and leaves the rest alone. A
full snapshot from a web tab reverted its look edits silently, and there was nothing either side
could do about it: last writer won the whole row.

Move the three writes to the PATCH routes, which merge field by field on the server, so two
clients editing different fields no longer race. An empty patch is dropped rather than sent,
because the server rejects an empty body.

Reset still deletes, on both routes: removing a customization is a whole-row operation and means
the same thing to every client.
2026-09-21 17:24:30 +00:00
neon 67ef7f29a5 fix(client): localize the read-aloud interface
Replace the hardcoded English in the TTS and narration components with
message keys, label every icon-only control, and add settings.common.nav.tts,
which the settings sidebar rendered as a raw key.

Stop requiring PODCAST_ENCRYPTION_KEY while APP_FEATURES.podcasts is off, and
skip podcast routes and permissions in the authorization matrix for the same
reason.

Pass the direct-download settle() helper the SETTLE_MS budget the file already
defines: vi.waitFor's one-second default cannot cover six DNS-resolved redirect
hops on a cold CI resolver.
2026-09-21 06:36:24 +00:00
neon 6e1cbbf3e0 chore(client): fix tooltip provider lookup and desktop middle-tap
Both failures broke Tests (Client) on main. reka-ui tooltip parts inject a provider
context that only App.vue supplies, so any spec mounting a subtree threw; the tooltip
primitive now stands in its own provider when none is in scope. The foliate click
handler's final else had no isMobile guard, letting a desktop middle-zone tap toggle
the reader chrome. Also record the v3.0.0 server floor beside the App Store badge.
2026-09-21 03:15:58 +00:00
neon b057e5e9d1 feat(client): link the iOS app from the sidebar footer
Add an App Store link and an Android placeholder beside the existing
project links, and regroup the footer so support and client links sit
on opposite sides of the version label. Size the Android mark larger
than the Apple one because its head fills only 56% of its viewBox.
2026-09-21 02:24:32 +00:00
neon 33952322f2 feat(settings): add Prowlarr and SABnzbd support (#1416)
* feat(settings): add SABnzbd download client

Support API-key authentication, NZB uploads, queue monitoring, reconciliation, and completed-download imports through SABnzbd.

Expose the client in request settings and validate its required category and credentials.

Ref #1312

* feat(settings): add Prowlarr indexer management

Manage synchronized torrent and Usenet sources through a shared Prowlarr connection.

Ref #1312

* fix(settings): correct SABnzbd adoption and managed search retries

Address four defects found in review of the Prowlarr and SABnzbd work.

SABnzbd keeps a failed job in its history until somebody clears it, and BookOrbit removes a client
download only on an explicit action. Because the client key is a stable digest, re-grabbing the same
release adopted that dead history entry, never uploaded the NZB, and failed instantly and forever.
Adopt only an entry that is not already failed; a queue entry still wins, so a fresh upload reports
correctly.

The category-expansion retry reused the title-and-author query, making it strictly narrower on text
than the title-only attempt that had just returned nothing. A release matching only a title-only
search with expanded categories was therefore unreachable. Drop the author there so each rung of the
ladder is genuinely broader than the last.

Changing the download client type through the create form's select bypassed the picker's handler, so
a username typed for qBittorrent was still sent when SABnzbd was chosen. The server stores it, the
API-key form hides it, and it can no longer be edited away. Watch the credential kind instead, so
both controls clear it.

Finally, a swallowed managed-release refresh failure left nothing behind at all; give it its own
fail log while still reporting the original refusal to the caller.

* fix(requests): cast managed search health flags to boolean

The bulk search-health update bound each case branch as an untyped
parameter, so Postgres could not resolve it against the boolean column.
Cast every branch explicitly and assert the cast in the repository test.

* fix(requests): close review gaps in Prowlarr and SABnzbd support

Inventory the eight indexer-manager routes so the authorization matrix
probes them, resolve a managed indexer without reading its manager's
whole source list, keep an unreadable credential out of the test-failed
mapping, translate manager error codes, and show per-source search
health. Documents Prowlarr connections in docs/BOOK_REQUESTS.md.

* i18n(client): keep the retired sources empty-state key

Dropping bodyOneWay from en.json forced pruning it from five Crowdin
target catalogs, which the localization policy check rejects outright.
Leave the now-unused key in place; nothing validates unreferenced
English source keys, so Crowdin can retire it on its own schedule.

* db: regenerate the SABnzbd and Prowlarr migration onto main

Rebasing collided with main's own 0091 and 0092, which left this branch's
two migrations on disk with no journal entry referencing them. Drop both
and regenerate a single migration on main's lineage; the three affected
tables are schema-identical to the pre-rebase snapshot.
2026-09-20 18:38:36 -06:00
neon c239cfa2dd feat(books): rebuild duplicate books as a ledger
Sort groups by reclaimable space, pre-pick a keeper with a rule that states
its reasoning, and expand any row into a field-by-field comparison that shows
only what differs. Persist "not duplicates" so a judgement survives a rescan,
and review every copy before deleting. Reading progress no longer renders 0%.
2026-09-20 20:11:34 +00:00
neon 6e608e79a4 fix(client): show the platform's own shortcut modifier
Lift the bulk rename empty state out of the vertical centre of the
tools pane so it sits near the top instead of floating in the void.

Replace the hardcoded Cmd in the settings search hint with a shared
useModifierKey composable, so Windows and Linux see Ctrl+K. The
translated hint now takes the combo as a placeholder.
2026-09-20 17:49:01 +00:00
neon 2da27cb5c2 fix(settings): stop cropping the sidebar search placeholder
Reserve the clear button's 32px of right padding only while it renders,
which leaves the placeholder 124px instead of 102px at the default
sidebar width. Add text-ellipsis so longer translations end in an
ellipsis rather than a sliced glyph, and hide the native WebKit search
cancel button that doubled up with our own.
2026-09-20 17:36:19 +00:00
neon d3f3382bfa feat(reader): synchronize Storyteller reading progress
Keep audiobook, EPUB, Kobo, and KOReader positions coherent while serving each client the safest suitable book variant.
2026-09-20 14:12:18 +00:00
neon 4dabacb2b3 fix(migration): verify BookLore v2.4.0 compatibility 2026-09-19 16:52:25 +00:00
neon e0d3d42150 feat: add read-aloud and media playback support
Add EPUB narration, shared media controls, and native device session integration.

Apply the generated migrations and update all first-party clients alongside the server.

BREAKING CHANGE: introduce incompatible database and API contracts for media playback
2026-09-19 02:27:05 +00:00
neon c292d6ccd2 fix(metadata): honor configured Amazon domain in book links
Use the sanitized provider-link setting so book detail URLs target the selected marketplace.

Fixes #1423
2026-09-18 16:32:18 +00:00
neon 6cbf8f5c35 fix(library): preserve folder creation order
Keep unrelated folder selections in the order users add them, and make API reads deterministic so web and iOS defaults use the same first folder.

Fixes #1412
2026-09-18 15:58:18 +00:00
neon d22faeaaf4 i18n(client): sync translations from Crowdin (#1427)
Keep sparse translated catalogs synchronized with reviewed Crowdin content.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-18 09:47:01 -06:00
dependabot[bot] 3860d38eb6 chore(deps): bump the production-dependencies group with 6 updates (#1441)
Bumps the production-dependencies group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [@formatjs/icu-messageformat-parser](https://github.com/formatjs/formatjs/tree/HEAD/packages/icu-messageformat-parser) | `3.5.17` | `3.5.18` |
| [@lucide/vue](https://github.com/lucide-icons/lucide/tree/HEAD/packages/vue) | `1.45.0` | `1.46.0` |
| [@tanstack/vue-virtual](https://github.com/TanStack/virtual/tree/HEAD/packages/vue-virtual) | `3.13.38` | `3.13.39` |
| [intl-messageformat](https://github.com/formatjs/formatjs) | `11.2.14` | `11.2.15` |
| [tailwind-merge](https://github.com/dcastil/tailwind-merge/tree/HEAD/packages/tailwind-merge) | `3.6.0` | `3.7.0` |
| [zod](https://github.com/colinhacks/zod) | `4.6.2` | `4.6.5` |


Updates `@formatjs/icu-messageformat-parser` from 3.5.17 to 3.5.18
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Changelog](https://github.com/formatjs/formatjs/blob/main/packages/icu-messageformat-parser/CHANGELOG.md)
- [Commits](https://github.com/formatjs/formatjs/commits/@formatjs/icu-messageformat-parser@3.5.18/packages/icu-messageformat-parser)

Updates `@lucide/vue` from 1.45.0 to 1.46.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.46.0/packages/vue)

Updates `@tanstack/vue-virtual` from 3.13.38 to 3.13.39
- [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.39/packages/vue-virtual)

Updates `intl-messageformat` from 11.2.14 to 11.2.15
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Commits](https://github.com/formatjs/formatjs/compare/intl-messageformat@11.2.14...intl-messageformat@11.2.15)

Updates `tailwind-merge` from 3.6.0 to 3.7.0
- [Release notes](https://github.com/dcastil/tailwind-merge/releases)
- [Commits](https://github.com/dcastil/tailwind-merge/commits/tailwind-merge@3.7.0/packages/tailwind-merge)

Updates `zod` from 4.6.2 to 4.6.5
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](https://github.com/colinhacks/zod/compare/v4.6.2...v4.6.5)

---
updated-dependencies:
- dependency-name: "@formatjs/icu-messageformat-parser"
  dependency-version: 3.5.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@lucide/vue"
  dependency-version: 1.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: "@tanstack/vue-virtual"
  dependency-version: 3.13.39
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: intl-messageformat
  dependency-version: 11.2.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: tailwind-merge
  dependency-version: 3.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: zod
  dependency-version: 4.6.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  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-09-18 09:46:49 -06:00
neon b10bb58a88 i18n(client): sync translations from Crowdin (#1418)
Keep sparse translated catalogs synchronized with reviewed Crowdin content.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-15 09:18:54 -06:00
dependabot[bot] b485d06688 chore(deps): bump the production-dependencies group across 1 directory with 6 updates (#1417)
Bumps the production-dependencies group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@lucide/vue](https://github.com/lucide-icons/lucide/tree/HEAD/packages/vue) | `1.42.0` | `1.45.0` |
| [@tanstack/vue-virtual](https://github.com/TanStack/virtual/tree/HEAD/packages/vue-virtual) | `3.13.37` | `3.13.38` |
| [cronstrue](https://github.com/bradymholt/cRonstrue) | `3.24.0` | `3.26.0` |
| [fastify](https://github.com/fastify/fastify) | `5.12.3` | `5.12.4` |
| [mysql2](https://github.com/sidorares/node-mysql2) | `3.24.3` | `3.24.4` |
| [zod](https://github.com/colinhacks/zod) | `4.5.4` | `4.6.2` |



Updates `@lucide/vue` from 1.42.0 to 1.45.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.45.0/packages/vue)

Updates `@tanstack/vue-virtual` from 3.13.37 to 3.13.38
- [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.38/packages/vue-virtual)

Updates `cronstrue` from 3.24.0 to 3.26.0
- [Release notes](https://github.com/bradymholt/cRonstrue/releases)
- [Changelog](https://github.com/bradymholt/cRonstrue/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bradymholt/cRonstrue/compare/v3.24.0...v3.26.0)

Updates `fastify` from 5.12.3 to 5.12.4
- [Release notes](https://github.com/fastify/fastify/releases)
- [Commits](https://github.com/fastify/fastify/commits/v5.12.4)

Updates `mysql2` from 3.24.3 to 3.24.4
- [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.24.3...v3.24.4)

Updates `zod` from 4.5.4 to 4.6.2
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](https://github.com/colinhacks/zod/compare/v4.5.4...v4.6.2)

---
updated-dependencies:
- dependency-name: "@lucide/vue"
  dependency-version: 1.45.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: "@tanstack/vue-virtual"
  dependency-version: 3.13.38
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: cronstrue
  dependency-version: 3.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: fastify
  dependency-version: 5.12.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: mysql2
  dependency-version: 3.24.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: zod
  dependency-version: 4.6.2
  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-09-15 09:18:41 -06:00
neon 50063b7775 ci: make crowdin source synchronization deterministic
Upload and verify the checked-out English catalog before exporting translations so delayed webhooks cannot stall the scheduled workflow.
2026-09-15 13:11:24 +00:00
neon 911f61e3dc fix(reader): preserve touch text selection in PDF reader
Route touch selection through EmbedPDF pointer mode while keeping swipe pagination limited to pan mode. Keep NestJS testing aligned with the application major and prevent incompatible standalone major updates.

Fixes #1388
2026-09-13 18:44:02 +00:00
neon 2f22abe03e fix(library): respect locale for cron time display
Derive the clock convention from the active locale so custom scan schedules match the rest of the interface.

Closes #1391
2026-09-13 12:38:15 -06:00
neon 3bb33b615c feat(book-requests): add per-indexer seed goals
Add configurable seed ratio and seed time goals to request indexers, supporting both static goals and tracker-advertised ratio/seed-time limits via torznab attributes. Enforce indexer-specific seed policy during request fulfillment and display active seed targets in the request seed panel.

Closes #1360
2026-09-13 17:42:12 +00:00
neon 8f1215d331 feat(book-requests): add indexer plugin updates and release profiles
Add an in-app update service and UI controls for installed indexer plugins, verifying releases and fetching updates securely. Introduce configurable release profiles for fine-tuning score weights, format preferences, and rejection criteria in book request automation.
2026-09-13 15:04:20 +00:00
neon fcdd72a384 feat(book-requests): add newznab and nzbget support
Support Usenet indexers via the built-in Newznab adapter and Usenet downloads via NZBGet. Generalize active download tracking from torrent client hashes to protocol-agnostic client keys, add NZB release scoring and file handling, and expose Newznab indexer and NZBGet client options in settings and grab flows.

Closes #1312
2026-09-13 06:47:06 +00:00
neon 7a203a03d7 fix(client): add missing icon tooltips
Make icon-only controls discoverable to mouse and keyboard users with localized tooltips and accessible names.

Fixes #588
2026-09-12 09:24:32 +00:00
neon ceda7428b0 feat(reader): add dedicated audiobook playback API 2026-09-11 05:41:29 +00:00
dependabot[bot] 7ecc52ee30 chore(deps): bump the production-dependencies group with 12 updates (#1368)
Bumps the production-dependencies group with 12 updates:

| Package | From | To |
| --- | --- | --- |
| [@lucide/vue](https://github.com/lucide-icons/lucide/tree/HEAD/packages/vue) | `1.39.0` | `1.42.0` |
| [@tanstack/vue-virtual](https://github.com/TanStack/virtual/tree/HEAD/packages/vue-virtual) | `3.13.36` | `3.13.37` |
| [@tiptap/extension-link](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/extension-link) | `3.31.0` | `3.31.3` |
| [@tiptap/pm](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/pm) | `3.31.0` | `3.31.3` |
| [@tiptap/starter-kit](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/starter-kit) | `3.31.0` | `3.31.3` |
| [@tiptap/vue-3](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/vue-3) | `3.31.0` | `3.31.3` |
| [dompurify](https://github.com/cure53/DOMPurify) | `3.4.14` | `3.4.15` |
| [vue-echarts](https://github.com/ecomfe/vue-echarts) | `8.2.0` | `8.3.0` |
| [vue-router](https://github.com/vuejs/router) | `5.3.0` | `5.3.1` |
| [fastify](https://github.com/fastify/fastify) | `5.12.1` | `5.12.3` |
| [jose](https://github.com/panva/jose) | `6.2.10` | `6.2.12` |
| [undici](https://github.com/nodejs/undici) | `8.10.1` | `8.10.2` |


Updates `@lucide/vue` from 1.39.0 to 1.42.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.42.0/packages/vue)

Updates `@tanstack/vue-virtual` from 3.13.36 to 3.13.37
- [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.37/packages/vue-virtual)

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

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

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

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

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

Updates `vue-echarts` from 8.2.0 to 8.3.0
- [Release notes](https://github.com/ecomfe/vue-echarts/releases)
- [Changelog](https://github.com/ecomfe/vue-echarts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ecomfe/vue-echarts/compare/v8.2.0...v8.3.0)

Updates `vue-router` from 5.3.0 to 5.3.1
- [Release notes](https://github.com/vuejs/router/releases)
- [Commits](https://github.com/vuejs/router/compare/v5.3.0...v5.3.1)

Updates `fastify` from 5.12.1 to 5.12.3
- [Release notes](https://github.com/fastify/fastify/releases)
- [Commits](https://github.com/fastify/fastify/commits)

Updates `jose` from 6.2.10 to 6.2.12
- [Release notes](https://github.com/panva/jose/releases)
- [Changelog](https://github.com/panva/jose/blob/main/CHANGELOG.md)
- [Commits](https://github.com/panva/jose/compare/v6.2.10...v6.2.12)

Updates `undici` from 8.10.1 to 8.10.2
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v8.10.1...v8.10.2)

---
updated-dependencies:
- dependency-name: "@lucide/vue"
  dependency-version: 1.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: "@tanstack/vue-virtual"
  dependency-version: 3.13.37
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@tiptap/extension-link"
  dependency-version: 3.31.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@tiptap/pm"
  dependency-version: 3.31.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@tiptap/starter-kit"
  dependency-version: 3.31.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@tiptap/vue-3"
  dependency-version: 3.31.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: dompurify
  dependency-version: 3.4.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: vue-echarts
  dependency-version: 8.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: vue-router
  dependency-version: 5.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: fastify
  dependency-version: 5.12.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: jose
  dependency-version: 6.2.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: undici
  dependency-version: 8.10.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  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-09-10 21:21:47 -06:00
SergeiAK 73ac0bb722 feat(authors): collapse series on author pages (#1271)
Reduce large author listings to one card per series while preserving book counts, scoped visibility, and row-based pagination. Compute both totals in the collapsed query so deep pages remain consistent without a second author-wide scan.

Closes #301

Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
2026-09-10 12:39:14 -06:00
neon b7e1e21d07 i18n(client): sync translations from Crowdin (#1307)
Keep sparse translated catalogs synchronized with reviewed Crowdin content.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-10 12:07:31 -06:00
neon d9ea13ba45 feat: add BookOrbit attribution requirements
Define AGPLv3 additional terms and expose attribution, source, and license details through unobtrusive About surfaces.
2026-09-10 18:03:11 +00:00
neon 5a5337bb31 chore: merge origin/main into main
Preserve both divergent commits while reconciling the local and remote histories.
2026-09-10 16:45:53 +00:00
bobberb 17aa7425f8 feat(library): per-library added_at source (imported/file_modified/file_created) (#1239)
* feat(scanner): set book added_at from earliest on-disk file mtime

A book's "date added" now reflects when its content files first landed on
disk (the earliest mtime across its content-role files) instead of the
moment BookOrbit imported it. Cover/metadata/supplement sidecars are
excluded. When no content file has a usable mtime, addedAt is left unset so
the DB defaultNow() fallback (import time) still applies. Only set at
initial book creation; re-scan/restore paths do not touch it.

* feat(library): add per-library added_at source with recompute

Add an addedAtSource setting to libraries so "date added" can follow the
book's files on disk rather than the moment the scanner happened to see
them. The setting takes imported (unchanged default), file_modified, or
file_created, guarded by a check constraint on the column.

Expose a recompute action so the chosen source can be applied to books
that are already imported. file_modified runs as a single set-based
update over the stored mtimes; file_created has to stat the files, since
birthtime is not persisted, so it batches those reads.

Leave every existing library on imported so behavior is unchanged unless
a user opts in.

* feat(library): add added_at source control to the library editor

Surface the new addedAtSource setting in the library editor as a radio
group, alongside a button that triggers the recompute for the library
being edited.

Keep the recompute out of the save path so changing the setting stays
cheap: the setting alone only affects books imported from then on, and
applying it to existing books is an explicit choice.

* i18n(library): translate added_at source strings (de/nl/pt/sl)

* fix(library): correct create payload, recompute floor and failure logging

The library creator posts its whole form, so omitting addedAtSource from
CreateLibraryDto made the global whitelist reject every create request
with a 400. Declare the field, validate it against the same source list
as the update DTO, and persist it so the initial scan uses the requested
source rather than silently falling back to imported.

Apply the scanner's usable-time floor to the mtime recompute query too.
It previously excluded only NULL, so a filesystem reporting epoch 0 would
rewrite added_at to 1970 instead of leaving the import time in place. The
floor now lives in library.constants rather than being spelled out twice.

Wrap the recompute in try/catch so a database or stat failure emits the
[fail] log the logging conventions require instead of propagating with
only a [start] line recorded.

* fix(library): gate recompute on the saved source and label the radios

The recompute button stayed enabled while the selected source differed
from the stored one. Because the request carries no source, clicking it
recomputed against the old stored value while the UI showed the new
selection. A hint already said to save first; disable the control as well
so the mismatch is not actionable.

Give the source list radiogroup semantics with aria-checked so screen
readers can tell which option is active, since selection was conveyed by
styling alone.

* test(library): assert the create DTO under the real validation options

The previous comment claimed the case exercised whitelist and
forbidNonWhitelisted, but the shared helper calls validate without them,
so it only proved @IsIn rejects an unknown value.

Drop the misleading comment and add a case that validates with the same
options main.ts gives ValidationPipe, so an undeclared addedAtSource
fails the way it would in a real request.

* docs(library): remove redundant date-added documentation

---------

Co-authored-by: Bob Bobber <user@example.com>
Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
2026-09-10 10:43:47 -06:00
neon 72871fad65 fix(client): preserve synced reading calendar dates
Treat exact UTC-midnight lifecycle projections as calendar dates while preserving local conversion for real timestamps.

Fixes #1322
2026-09-10 15:35:06 +00:00
neon 33c7260f18 fix(auth): explain untrusted OIDC certificate failures
Classify private trust-chain failures with a stable error code and direct administrators to a mounted CA bundle without weakening TLS verification.

Fixes #1346
2026-09-10 11:47:56 +00:00
neon e514be151a fix(library): ignore current library during folder prescan
Prevent an edited library from treating its own persisted folders as conflicts while preserving overlap warnings for other libraries.

Fixes #1340
2026-09-10 11:02:32 +00:00
neon 6c65c393b5 fix(reader): honor line spacing over publisher styles
Ensure explicit reader spacing overrides higher-specificity EPUB typography and cover the cascade with a regression test.

Fixes #1302
2026-09-09 03:20:08 +00:00
neon 7978ab0230 test(settings): cover fill-crop preference sync payload
Guard against the display preference mismatch reported in #1290 by checking author fields in cover-mode saves and verifying server acceptance of the complete payload.

Ref #1290
2026-09-09 03:12:16 +00:00
neon b9609b198e fix(annotations): preserve source highlight timestamps
Use KOReader highlight times for annotation history while retaining ingestion times for diagnostics. Export all stored location representations and backfill existing rows during sync.

Fixes #1300
2026-09-08 16:52:36 +00:00
neon cf40058cb6 fix(users): select exact content restriction matches
Prioritize exact genre and tag results within bounded catalog searches. Resolve Enter presses against existing IDs and ignore stale lookup responses.

Fixes #1295
2026-09-08 15:43:27 +00:00