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.
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.
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
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.
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
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.
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.
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.
Let users inspect missing fields without launching provider searches.
Keep metadata searches manual by default and expose a remembered
opt-in beside Search.
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.
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
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
Refresh dashboard and statistics caches immediately after reading history,
projection, reset, import, and shared deletion changes. Coalesce bulk
notifications while keeping committed changes visible to concurrent reads,
and isolate listener failures from successful writes.
Skip unchanged Hardcover attempt updates and protect cache generations
against stale in-flight loads. Cover date edits, projection-only resumes,
rollback, bulk failures, user scope, and cache races with regression tests.
Ref #1695
Register the identity of delivered bytes so Kobo conversions and audio
removal continue matching their source books in KOReader. Keep download
registration recoverable without allowing database lock waits to stall it.
Preserve manual corrections across cached device identities, make review
semantics explicit, and keep cache invalidation bounded for large libraries.
Add unit, database, lifecycle and scale regressions with one generated migration.
Closes#1697
Align collection visibility across OPDS and KOReader with the web catalog.
Count only books the viewer can access in one aggregate query, and cover
public access, private revocation, and filtered counts with regression tests.
Closes#1701
Allow native KEPUB files to exchange precise reading progress, bookmarks
and highlights with Kobo while preserving sync permissions and settings.
Use the original KEPUB archive for Kobo spans and project its added
wrappers away for shared EPUB CFI and KOReader XPointer positions.
Preserve existing EPUB conversion behavior and API compatibility with
released iOS clients.
Cover native KEPUB context, canonical positions and two-way exchange with
unit tests and paired EPUB/KEPUB API E2E scenarios.
Ref bookorbit/bookorbit-ios-support#36
Remove content before committing book deletion so surviving files cannot be reimported
under new records. Preserve records and covers on failure, bound cleanup concurrency,
and allow retries after partial removal. Defer watcher events through the database
commit and cover delayed operations, failure recovery, and retry behavior in tests.
Ref bookorbit/bookorbit-ios-support#42
In folder-as-book libraries a pattern that files several books under one folder either failed on
the folder_path unique index or silently merged a different book into the folder's owner, deleting
its reading history. Check the folder owner on every rename path and merge only when both books
share a title and primary author; otherwise skip with a clear reason. The bulk preview now reports
these as collisions.
Fixes#1682
Add read-only /notebook routes that list highlights, journal entries, bookmarks and reviews
across every book a reader can open, as one cursor-paged stream with per-kind counts, a By Book
listing, a daily review deck, a seeded review shuffle, On this day and a library-wide trash. Each
kind is read through its own index-ordered arm cut at the page size before a UNION ALL merge, so a
deep page costs what the first does, and book labels travel once per page in a sidecar map.
Scope follows library access and content filters. Everything is additive and advertised as the
notebook-hub app-info feature. The iOS app calls these routes and the web client does not yet, so
they look unused from the client alone. No migration: the extra indexes for the edited sort and
search wait until the chapter-editor migrations land.
Add per-book journal entries keyed by a client id, a star toggle that does not bump the annotation
version pushed to devices, a per-user colour legend, and an edit route so bookmark title and note
changes reach the server. All of it is additive and advertised through app-info features, so iOS
sends new fields only to servers that support them. Also sort annotations by numeric CFI steps
instead of comparing CFI strings.
Include whether each session was spent reading, listening to text to speech or listening to audio,
so clients can tell Read Along listening on an EPUB apart from reading it. The column was already
stored; only the per-book list left it out. Unknown stored values read as reading.
The field is optional and additive: released iOS builds ignore it, and the iOS reading timeline
treats it as optional and falls back to the file format on servers without it. The web client does
not read it yet.
Convert complete source CFIs on the server to avoid chapter-start resets
and browser-generated locators that disagree with CREngine. Preserve
engine whitespace, Unicode offsets, element anchors and long text nodes.
Handle prefixed OPF namespaces and retry outdated annotation conversions.
Closes#1621Closes#1288
Return saved organization and automation settings in the user-scoped library list so
non-superuser summaries reflect the saved configuration.
Cover enabled and disabled settings, library isolation, and permission denials with
API regression tests.
Closes#1664
Keep dashboard layouts browser-local by default and let users opt in to account storage.
Group library selection and shelf sync in one dropdown, preserve legacy client settings,
and block sync changes for demo-restricted accounts.
Fixes#1646
Apply needs-triage to new bug and feature issues from the templates.
Drop the retired npm label from the Dependabot npm updates.
Give Docker, Dockerfile, and compose paths their own docker label
instead of folding them into ci.
The collapsed order by had no metadataScore case, so the sort was dropped
and the list fell back to title order. Order by metadata_score there and
select it in the collapsed jump-bucket query that shares the order by.
Fixes#1638
Use the package media:duration when a SMIL clip cannot be measured.
Storyteller 2.x writes a backwards clip at audio track boundaries, which
nulled the total and blocked the audiobook bridge. Stored nulls are
re-measured via a migration, the detail page and an unchanged-folder scan.
Fixes#1619
The three-column layout left the editor 270px wide at 1280 and broke resolved paths mid-word.
Draw the pattern one folder per line, preview it against long-name books, and list only what
missing metadata changes. Add resolvePlaceholders to the shared resolver to report fallbacks.
Keep TypeScript at 6.0.3 while moving the remaining server and client packages onto their current supported releases.
Allow the PWA asset generator 2 peer range because vite-plugin-pwa still declares the compatible version 1 range.
Keep long request titles from widening the auto-layout table and hiding row actions. Guard the intrinsic-sizing chain with focused component regression tests.
Fixes#1613
Generate RFC 4122 UUIDs with getRandomValues when randomUUID is unavailable so plain HTTP deployments can save playback state and bookmarks.
Fixes#1608
* fix(authors): keep non-latin letters when matching enrichment candidates
Keep letters and digits of any script in normalizeName() instead of
dropping everything outside [a-z0-9], and stop treating two empty token
lists as a token-set match. Names without ASCII letters normalized to an
empty string, so any two of them scored 0.96 and passed the confidence
gate, and enrichment linked authors to unrelated people.
Closes#1459
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(authors): keep combining marks when normalizing author names
Keep \p{M} in normalizeName() alongside letters and digits. Vowel signs
in scripts such as Devanagari are combining marks, not letters, so
dropping them merged distinct names: कमल and कमला both normalized to
कमल and matched with score 1. Latin diacritics are still folded by the
earlier U+0300-U+036F strip, so Latin and Cyrillic matching is unchanged.
Refs #1459
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
Cut long paths from the start, name layouts and schedules the way the editor
does, and switch to cards when the ledger would scroll sideways. Rows now
toggle automation in place with undo, open recent scan history, show live
scan counts, flag failed or never-scanned libraries, and can seed a new
library from another's settings.
Bump every direct dependency to its newest same-major release, moving the
embedpdf patches and packageExtensions to 2.15.1 and deduping the lockfile.
Hold jsdom at 30.0 because 30.1 breaks vitest's URL.createObjectURL shim,
and skip releases still inside pnpm's minimum release age.
Search and Compare Metadata become one two-pane sheet, shared with the Book Dock. Results are
ranked by match strength beside a field-by-field comparison with Keep/Use per row, word-level
diffs, other sources inline, a cover strip, and picks that survive switching results.
The search runs on open and a single source can be retried. No API change.
Replace tinted modal veils with dedicated scrim tokens so dialogs, sheets, and image lightboxes dim consistently in both light and dark themes. Enforce scrim token usage in style validation to prevent backdrops that wash out in dark mode.
Replace the seven-step wizard with a sheet whose section rail summarizes each
setting. Format priority shows only the formats a library holds, folders are
checked as they are added, and people can be granted access while creating.
Expose media-overlay-aware naming across file creation and delivery paths while preserving existing client contracts. Keep settings router mocks compatible with the application router exports.
Closes#1590
Handle both idle pool errors and checked-out client errors so a database restart fails only the affected operation. Keep connection-loss logging sanitized and deduplicated while allowing the pool to reconnect.
Fixes#1581
Remove device-scoped annotation delivery state with the rest of its KOReader data so stale acknowledgements cannot block permanent deletion.
Fixes#1576
Save the library and folder shown in the metadata sheet before closing it. Avoid duplicate target updates after explicit selection and keep the sheet open when persistence fails.
Fixes#1573