Commit Graph

1296 Commits

Author SHA1 Message Date
neon 9dbe2980dd fix(reader): keep tts playing after a voice or speed change
A voice or speed change invalidated the playing block's end handler, so the next block was never
requested, and a change during loading left the player loading forever. Hand the playing block over
to the new settings, refetch any block playback was waiting on, and cancel superseded requests in
the client and at the provider. Audio that arrives during a pause no longer resumes playback.

Fixes #1734
2026-10-12 23:08:57 +00:00
neon 591dea03a2 feat(email): rebuild email settings as four quiet tabs with a send sheet
Fold six tabs into Recipients, Mail servers, Templates and History, where only problems get
colour and one star sets each default through email_preferences. Replace the send dialog with
a sheet that preselects the default recipient and follows the send. Server additions are
optional fields and routes, so released iOS builds keep working.
2026-10-12 22:18:38 +00:00
neon ddc7e848b9 fix(reader): scale publisher font sizes with the reader text size
Rewrite absolute publisher font sizes (keywords and px/pt lengths) as each EPUB loads so they
follow the reader's root size, falling back to the original value when the reader applies no
styles. Skip fixed-layout books and SVG content, and cover the rewrite and the foliate loader
hook with regression tests.

Fixes #1276
2026-10-12 22:05:19 +00:00
neon b0f0e36d30 fix(metadata): avoid ambiguous ComicVine volume matches
Probe equally ranked comic runs within the existing search budget to prevent reprints from hiding original issues. Require an unambiguous result for automatic matching while preserving manual selection and saved-ID refreshes.

Add regression coverage for the reported Generation X match, padded issue numbers, competing runs, provider failures, deadlines, and cache isolation.

Fixes #1238
2026-10-12 21:03:44 +00:00
neon df7ef5daf0 fix(authors): keep circular portrait metadata readable
Inset and center hover metadata within the circular portrait so the book count and last-added date remain readable. Add regression coverage for both shapes and metadata states.

Fixes #1413
2026-10-12 18:51:25 +00:00
neon 9e2cbfd3a5 fix(metadata): preserve epub creators with multiple roles
Read every EPUB 3 role refinement so authors and narrators survive
regardless of role order, including creators who hold both roles.
Preserve EPUB 2 role precedence and contributor handling, and add
regression coverage for ordering, normalization, and deduplication.

Fixes #1344
2026-10-12 18:04:31 +00:00
neon 1ab087dbd2 fix(reader): support epub loading without native grouping APIs
Keep EPUB loading functional on browsers without Object.groupBy or Map.groupBy.
Replace the native calls with local helpers and cover missing APIs with EPUB 2
and EPUB 3 metadata regression tests.

Closes #1683
2026-10-12 17:12:49 +00:00
neon 2b89c30a8d fix(reader): resolve non-English dictionary lookups
Use English Wiktionary's multilingual definitions endpoint to avoid HTTP 501
responses from language-specific hosts. Keep filtering definitions by the
book's language and cover host selection, language aliases, inflection
lookups, URL encoding, and popover retry recovery with regression tests.

Closes #1439
2026-10-12 16:56:34 +00:00
neon b86502fcd6 fix(metadata): stop Hardcover sync following a stale cached match
A cached Hardcover match outranked a corrected Hardcover ID or ISBN, so progress kept going to the
wrong book. Record the identifiers each link came from and re-check it when they change, honour the
metadata edition on a match, and release the old book's read links so they are never reused.

Closes #1488
2026-10-12 16:35:26 +00:00
neon 06d101316e fix(metadata): write tags into m4b files that carry mp3 audio
FFmpeg picks its ipod muxer from the .m4b temp name, and that muxer rejects the
MP3 an Audiobookshelf copy merge leaves inside an MP4. Probe the audio codec and
use the mp4 muxer for anything but AAC, ALAC and AC-3, so other files keep their
iTunes file type. The rename collision log now names the path that collided.

Closes #1593
2026-10-12 16:02:41 +00:00
neon 190d837280 fix(client): show authors on collapsed series rows in table view
The table rendered a dash in every column of a collapsed series row,
including Authors, although the row already carries the first
volume's authors and the grid and list views show them. Render them
as the same read-only author chips book rows use.

Closes #1645
2026-10-12 15:48:10 +00:00
neon 2327847bff fix(settings): honor disabled Prowlarr seed limits
Keep disabled Prowlarr limits from being reapplied through tracker metadata,
cached releases, or stale source rows after a failed synchronization.

Cover policy changes, synchronization, both torrent transports, client defaults,
and the PostgreSQL join with regression tests.

Closes #1625
2026-10-12 15:46:26 +00:00
neon b1ffb9fbce fix(server): restore socket subscriptions behind the global guards
Nest 12 runs global guards on gateway messages, and the HTTP JWT guard
crashed every subscribe on a missing Authorization header. Skip it for
sockets, which authenticate in handleConnection, and make subscribe
handlers wait for that handshake. Library rooms now require library
access, and a real-socket test runs the app's global guards.

Closes #1743
2026-10-12 15:28:42 +00:00
neon de93564e6e fix(server): import Audiobookshelf finishes dated before their start
Audiobookshelf reports a progress row's creation time as its start, while
clients set the finish date freely, so a backfilled finish can predate it.
One such row broke user_book_status's date check and the whole status batch
with it. Keep the finish date and drop the start, and store the database's
reason on a failed run instead of the failed SQL.

Closes #1678
2026-10-12 05:51:19 +00:00
neon 9a7970f0b3 feat(metadata): list every visible language for a blank language query
The iOS library filter offers languages as chips and needs the whole list, not a typeahead. A blank
term on /metadata/languages now returns every language value on a visible book, most common first
and capped at 200, under the same library and content-filter scope as the search. Every other
suggestion endpoint still answers a blank term with nothing.

The web client never sends a blank term. Released iOS builds do, when the Smart Shelf language
picker opens, and now see the list there instead of a search prompt. The iOS filter calls this
route too, though nothing in the web client shows it.

Ref bookorbit/bookorbit-ios-support#54
2026-10-12 05:30:58 +00:00
neon 30229c7451 fix(reader): open EPUBs whose package lost its default namespace
epubBuilder writes the OPF root as `mlns=` for `xmlns=`. Once a metadata save
bound `opf:` on <package>, foliate matched OPF elements by namespace, found no
spine, and failed with "reading 'children'". Match by namespace only when the
root is in it, and have the writer add the missing default namespace so
rewritten files also open in released iOS builds.

Closes #1680
2026-10-12 05:09:00 +00:00
neon 688cfdeaec fix(scanner): keep audiobook tracks in file name order
The player follows each track's stored sort order, which overlapping
folder scans, Add File, and imports joining a book could leave out of
step with the file names the Files tab shows. Realign a book's tracks
after each of those writes, under the book row lock.

Closes #1681
2026-10-12 05:05:13 +00:00
neon 0c367b2b57 fix(client): center the top glow on the main column
Paint the glow from a zero-height element in the main inset instead of the full-width shell, so it
centers on the content column and follows the sidebar as it resizes or collapses. The shell's own
background patterns (dots, mesh, aurora and others) were hidden under the old glow and now render.
2026-10-12 04:31:21 +00:00
neon 4d453c82ca fix(books): measure audiobook durations when Book Dock files them
Book Dock finalize, which also files book requests, left each audio file's
duration empty until the next library scan. The player derives progress only
from those, so a filed audiobook stayed at 0% and never reached Continue
Listening. Finalize now measures them once metadata is applied.

Refs #1757
2026-10-12 03:44:40 +00:00
neon 4440fea99a fix(server): keep tracker timeouts recoverable
Keep downloads active after transient tracker failures so later completions
reach the importer. Reserve early failure for explicit rejections and import
completed content even when the tracker still reports an old rejection.

Cover timeout recovery, transient failures, and explicit rejections with unit
tests.

Closes #1607
2026-10-11 07:02:19 +00:00
neon 4770032ce7 fix(metadata): import ComicInfo Tags as book tags
Map <Genre> to genres and <Tags> to tags instead of using tags as a genre
fallback, which dropped them whenever a Genre was present. Read the
ComicBookInfo genre field so those comics keep their genres.

Fixes #1572
2026-10-11 05:58:02 +00:00
neon b83a181128 chore: add community and help issue forms
Keep questions and community conversations in GitHub Issues with clear forms and guidance. Remove disabled Discussions links and exempt community topics from stale closure.

Closes #1046
2026-10-11 05:58:02 +00:00
neon 62cb4f4411 fix(koreader): open the dashboard offline without waiting for wi-fi
Open the cached dashboard at once from the menu, gesture and Dashboard
button, then ask for a connection once through KOReader's Wi-Fi setting
and refresh in place. With no cache, show the unavailable state and Retry.

Fixes #1741
2026-10-11 05:58:02 +00:00
neon 7e11d39724 fix(opds): send book descriptions as plain text
Descriptions are stored as HTML but the feed sent them escaped under
type="text", so clients that honour the type, such as Foliate, showed the
tags literally. Flatten them with htmlToPlainText, keeping line breaks.

Fixes #1569
2026-10-11 05:58:02 +00:00
neon 3e993af16b i18n(client): sync translations from Crowdin (#1707)
Keep sparse translated catalogs synchronized with reviewed Crowdin content.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-10 23:57:13 -06:00
neon c37821782a security(deps): update dependencies and rebuild kepubify with go 1.27.2
Bump every direct dependency to its newest same-major release and move the
node base image to 26.11.1, which invalidates the cached apk layer and picks
up tiff 4.7.2 for CVE-2026-4775. Rebuild all six kepubify binaries from the
pinned upstream commit with Go 1.27.2 for CVE-2026-78667, CVE-2026-78669 and
CVE-2026-97031, keeping v4-dev so rendition hashes stay stable.
2026-10-11 05:19:04 +00:00
neon e4843e4aa1 fix(metadata): keep extended m4b tags when a cover is written
Write the tags FFmpeg's iTunes mode drops (subtitle, publisher, language,
series, ASIN) as freeform atoms, and carry over the source file's own
freeform tags such as Audible's. Covered M4B and M4A writes lost them.

Ref #1744
2026-10-11 04:37:26 +00:00
neon c3abf6d9e1 fix(settings): add release tiers on plain-HTTP origins
Create client IDs with createUuid instead of crypto.randomUUID, which
browsers only expose in secure contexts, so Add tier, saved views, table
presets and podcast sessions work on HTTP installs. Lint now rejects raw
randomUUID calls.

Fixes #1722
2026-10-11 03:54:24 +00:00
neon cc50b55eeb feat(books): add read-aloud delivery policies and preserve sync
Add original and text-only EPUB delivery choices across Kobo, KOReader,
OPDS, web downloads and email while keeping source files unchanged.
Persist server defaults, device overrides and captured artifact identities
so retries and guided replacement retain the selected rendition.

Preserve saved progress across first opens, replacement resets and stale
updates, and project annotations against the copy delivered to each device.
Handle XML resource references, large inodes, retry backoff and background
worker state correctly. Consolidate the schema changes into one migration
and retain released-client request and response compatibility.

Verify with the full server and client checks, delivery and sync HTTP suites,
independent code reviews, and live KOReader download/settings/reader proof.

Fixes #1496
Closes #1603
Closes #1714
Fixes #1723
Ref #1633
Ref #1508
Ref #1621
Ref #1136
2026-10-11 03:11:27 +00:00
neon 7bb51a7a0b feat(metadata): cache metadata provider answers
Repeated searches and refreshes asked every provider again, which is slow and runs into provider
rate limits. Keep each provider's answer in Postgres, shared by all users, and reuse it until an
admin-set lifetime runs out. Search screens mark saved results and offer a fresh search, and
explicit refreshes stay live, falling back to a saved answer only when a provider fails.

Empty answers are only kept for API providers that report failures reliably, and a cache-only
request never calls a provider in cooldown. Book Dock's manual refetch stays live-only because
the dock has nowhere to report a fallback. Released iOS builds keep working: every new request
field is optional and newer clients gate it on the metadata-search-cache server feature.
2026-10-10 22:26:26 +00:00
neon c91648eaac feat(books): include comics in non-audio requests
Keep books and comic archives under the existing ebook request kind so searches, ownership checks,
format preferences and release profiles agree without changing the API contract. Cover the combined
formats and library access rules with unit and end-to-end tests.

Ref #1748
2026-10-10 21:47:09 +00:00
neon e6c0275fdf fix(settings): refresh upload limits and default to 4 GB
Share the saved upload limit with validation so changes apply without a page reload.
Seed new installations with a 4096 MB limit while preserving existing values.

Fixes #1733
2026-10-10 17:30:22 +00:00
neon 3c6dd48b5b style(books): add enchanted request button effects
Give the missing-format action a wand and subtle accent glow to make it
more inviting. Keep its status readable in narrow cards and honor reduced motion.
2026-10-10 17:17:12 +00:00
neon 5a4560c9e2 fix(metadata): make epub metadata writes idempotent and lossless
Each save left the previous save's entries behind when a package bound the OPF namespace to a
prefix other than opf, added another title refinement on EPUB 3, and kept Dublin Core written
without the dc prefix beside its replacement. Match elements regardless of prefix and remove the
refinements of whatever is replaced.

Stop both OPF parsers reading untouched text as numbers and re-escaping character references,
which dropped leading zeros from identifiers the writer was meant to leave alone.

Fixes #1706
2026-10-10 16:30:24 +00:00
neon af8f55976f feat(client): add the Nostalgia appearance style
Add a Style setting beside mode, accent, radius and background. Nostalgia restyles the app through
tokens only (neutral surface palettes, system type, flat shell, top glow) and pins background,
opacity and brightness. Add a top glow reach slider for both styles. Tidy the theme layer first:
charts read live tokens, bare `rounded` follows the radius scale, one shared sign-in toolbar.
Also carries the settings page header redesign.
2026-10-09 01:01:57 +00:00
neon c63f3ab757 fix(metadata): choose sources by medium and stop overwriting book data
Lead fetches with the primary file, give Book Dock its library's rules and read-along media,
default audiobook fields to sources that carry them, and flag providers that never fill a field.
Joining a format now fills gaps only and respects locks; a move picks its primary as a scan would.
2026-10-08 18:12:48 +00:00
neon 21b68685ad fix(settings): stop truncating the genres merge strategy control
Make the field rules table one grid with each row as a subgrid, so the
merge and status columns size to the widest control instead of fixed
272px and 116px tracks. The four-option genres control and translated
labels now fit, and the global scope drops the empty status gap.
2026-10-08 17:55:12 +00:00
neon 39ac2f1efd feat: request an ebook and audiobook as a pair
Link two ordinary requests as companions, filed into one book, with a Both search,
grouped list rows, a tabbed release picker and a book-page request for the missing
format. Retire comic requests, keeping old rows readable. File Book Dock covers by the
field rules with a shape check, and re-pick a moved book's primary by its new library.
2026-10-08 16:12:30 +00:00
neon 01b5638ea7 feat(cover): show each book's cover in the shape of its primary format
Pick the face slot from the primary file's medium instead of the library's
ratio, and send that frame per book on cards, detail, notebook labels and
recommendations. Grids keep uniform tiles, and the library setting becomes
Grid shape.
2026-10-08 06:19:00 +00:00
neon bd141802bd fix(reader): preserve reading progress across narration resume
Keep text and narration bookmarks independent when opening and navigating EPUBs.
Use the narrated section for sentence bookmarks and attribute delayed page moves to narration.
Recover stalled WebKit blob frames with a bounded fallback that preserves XHTML location structure.

Cover restoration, narration attribution, and iframe fallback behavior with regression tests.

Closes #1708
2026-10-07 21:39:38 +00:00
neon c35eb38485 fix(cover): restore audiobookcovers searches
Use separate title and author parameters to match the current upstream search form and restore cover results. Add regression coverage for title-only searches, whitespace trimming, and query encoding.
2026-10-07 21:33:50 +00:00
neon 2476195016 docs: add android coming soon badges to readme 2026-10-07 21:00:59 +00:00
neon 0d426db88e fix(scanner): preserve separate books at the library root
Use file identities for root-level imports and renames to match scanner
grouping and prevent unrelated books from sharing metadata.
Cover repeated scans, metadata write-back, and stable reading and file
identities with regression tests.

Fixes #1599
2026-10-07 20:51:27 +00:00
neon 5c093333c5 fix(smart-scope): refresh sidebar counts after saving
Return matching item counts with create and update responses so the sidebar
can display the saved scope count without requiring a page reload.
Reuse the listing count logic and verify visibility and shared sidebar state.
2026-10-07 20:12:54 +00:00
neon d719c4ee5b fix(metadata): preserve ISBN fields across metadata workflows
Carry ISBN-10 and ISBN-13 independently from accepted providers through
Auto-fill previews, saves and background refreshes. Preserve existing
identifiers and field locks, validate provider checksums and avoid
combining different editions.

Classify embedded ISBNs correctly and support ISBN-10 fallback in
search, Book Dock confidence and file naming.
2026-10-07 20:07:23 +00:00
neon 6c7d91eaac feat(metadata): add configurable missing-field reminders
Add account-scoped reminders for the metadata fields users care about.
Treat either ISBN as complete, accept a publication year or date, and
skip page-count reminders for audio-only books.

Place reminders after the genre blocklist and allow customization from
the editor without discarding unsaved changes.
2026-10-07 20:06:50 +00:00
neon 8fef9d1633 feat(metadata): add empty-field details and optional auto-search
Let users inspect missing fields without launching provider searches.
Keep metadata searches manual by default and expose a remembered
opt-in beside Search.
2026-10-07 18:38:07 +00:00
neon 3ef4a22c37 fix(scanner): play disc-folder audiobook tracks disc by disc
The walker sorted a book's files by file name, so tracks in disc folders that reuse names, such as
CD 1/01.mp3 and CD 2/01.mp3, interleaved in playback, merged chapters, and written track numbers.
Order them by their whole path instead, everywhere a track order is chosen.

A rescan that only reorders a book's existing tracks now moves every audio bookmark and the
listening progress percentage to the same moment of the same track, and rebuilds merged chapters.
Disc folders are never skipped by incremental scans, so existing libraries are fixed by their next
scan.

Also inventory the notebook and dashboard highlights routes in the authorization matrix, and pin the
app locale in two date tests that depended on the machine's locale.
2026-10-07 18:31:33 +00:00
neon 100953ea1b feat(metadata): write metadata to every file of a multi-file book
Books often carry several files, such as an EPUB beside a PDF or an audiobook split into tracks.
Write-back reached only the primary file and the audio tracks, so the other formats kept stale
metadata.

Add an opt-in per-library mode that writes every content file of a book. Target selection,
capability reporting and the Files tab now share one role-aware selector, covers resolve per
medium, and results report per-format counts. Read-along EPUBs get their own toggle, off by
default, and their own size limit of 1000 MB, so they no longer follow the EPUB settings.

Live testing on copies of real libraries surfaced write-path bugs, fixed here as well:
- tag-only writes to chaptered M4B files failed because FFmpeg copied the chapter data track
- an undecodable cover failed every file instead of falling back to metadata only
- failure reasons stored the FFmpeg command line and absolute paths; they are now sanitized
- size limits used the stored size, so an unknown size bypassed them; writes now check the disk
- atomic replace dropped the file mode and ownership
- the EPUB temp name failed on long file names and could clash with a user file
- tracks in disc folders got duplicate titles
- a PDF worker that exited without a result hung its write forever; it now fails and times out
- null on a NOT NULL library setting returned 500 instead of 400

Generates migrations 0104 and 0105. Every new API field is optional, and released iOS builds
decode none of them.

Ref #694
2026-10-07 16:52:52 +00:00
neon e767358443 feat(library): auto-select sole upload destinations
Remove redundant destination choices when only one book library or folder is available.
Preserve existing Dock targets and cover loading, selection, and failure states with unit tests.

Closes #1362
v3.3.0
2026-10-07 04:56:44 +00:00