v2.2.0 "Unopened"
v2.2.0 "Unopened"
Old books were sold with their pages folded shut and uncut - you sliced each
one open as you read it, so an unopened copy meant something specific: a book
you own but haven't yet begun. That is this release: Tome finally has a real
place for those books, sitting between the wishlist and the first page turn.
Highlights
A place for the books you're about to read. Until now a book was either
unread, being read, or done - "unread" lumping together the book you're
starting tomorrow with the one you forgot you owned. The new Want to Read
status is the missing state: owned, not started, queued next. Set it from the
book page, filter by it on the dashboard, and forget about it - the moment
real progress arrives from KOReader or the web reader, the book promotes
itself to Reading. Series "continue" suggestions prefer a queued volume over
a plain unread one, and the Library Completion tile counts your queue. Best
of all, the wishlist now feeds it: when an admin fulfils your wish - or a new
volume of a series you follow arrives - the book lands on your Want to Read
automatically. The intent that created the wish carries over instead of
evaporating the moment the file shows up.
Hardcover Want to Read syncs both ways. Ratings and reading progress
still flow one way, Tome to Hardcover - but the Want to Read shelf is now a
genuine two-way street. Queue a book in Tome and it appears on your Hardcover
shelf; shelve a book on Hardcover and it turns up queued in Tome. Shelve a
book Tome doesn't even have, and it becomes a wish on your Tome wishlist
instead, cover and author included - un-shelve it and the wish is dismissed,
re-shelve it and the same wish reopens. The sync is deliberately cautious: it
never overwrites a book you're actually reading, and nothing is ever deleted
on Hardcover.
Duplicate cleanup in one pass. The admin Duplicates tab used to reset
your selections after every single merge or dismiss. Now you pick the book to
keep and an action per group - Merge, Delete Others, or Dismiss - and hit one
"Apply All". "Delete Others" is new: keep the selected copy, delete the rest
including their files, with missing-from-disk copies badged so dead entries
are easy to spot. Two long-standing merge bugs died along the way: merging
now actually transfers the removed book's files to the kept book (they were
silently deleted before), and dead file references are dropped instead of
carried over. (#165)
Library Health finds books whose files are gone. Files deleted or moved
outside of Tome used to leave ghost entries that errored on open. Library
Health now lists these orphans and offers a one-click "Remove Dead Entries" -
dead file entries are removed, books left with no files at all are deleted,
and entries whose file still exists are never touched. (#165)
A PDF.js security fix that actually matters. This release updates
pdfjs-dist past an arbitrary-JavaScript-execution advisory - and unlike
most dependency advisories, this one is reachable in Tome: the web reader
renders library PDFs in the app's origin, so a crafted PDF could run script
with access to the session. If you host PDFs for multiple users, update.
Also fixed: OPDS feed links behind a TLS-terminating reverse proxy now carry
the correct https scheme (#167), "Select all" on the dashboard selects every
matching book instead of only the ones infinite scroll had loaded (#165),
and toggling "Group series" no longer occasionally duplicates books in the
grid (#165).
KOReader plugin
This release ships plugin build 38 (1.11.1): popup menus - the series
browser, Authors, Shelves, the Inbox and the TomeSync menu itself - could
freeze on their first page when a full-screen home-screen plugin (such as
bookshelf.koplugin) covers the file browser. The menus now repaint through
their own window. (#166)
Upgrade note: the plugin updates gracefully in-app - TomeSync → Settings →
"Check for updates" (or enable auto-check). No breaking changes; existing
installs keep working untouched until you update.
Upgrade
docker pull ghcr.io/bndct-devops/tome:latest && docker compose up -d
No migrations to run and no configuration changes. On first start the server
creates one new database index automatically (used by the Hardcover shelf
sync). If you use Hardcover sync, there is nothing to re-link - existing
connections pick up the Want to Read direction on their next cycle.
Full changelog
Security
- Updated
pdfjs-distto 6.2.108, clearing an arbitrary-JavaScript-execution
advisory triggered by opening a malicious PDF (GHSA / CVE for PDF.js). This
one is real in Tome: the web reader renders library PDFs with PDF.js in the
app's origin, so a crafted PDF opened in the reader could run script with
access to the session. Anyone hosting PDFs for multiple users should update. - Updated
fast-uri(build-time, via vite-plugin-pwa's workbox tooling) to
3.1.5, clearing a host-confusion advisory. Not reachable in Tome - it only
parses our own build configuration duringvite build. - Updated
js-yamlto 4.3.1 in the frontend (dev-only, eslint's config
loader) and the website build, clearing a quadratic-CPU advisory. Neither
parses untrusted input. - Updated
postcssto 8.5.26 in the website build, picking up the completed
fix for the source-map advisory partially addressed in v2.1.1. Build-time
only, same as before.
Added
- New "Want to Read" reading status - the missing state between the wishlist
and actually starting a book: owned, not started, queued next. Set it from
the book page (next to Shelved), filter by it on the dashboard, and it
self-promotes to Reading the moment real progress arrives from KOReader or
the web reader. Series "continue" suggestions prefer a queued volume over a
plain unread one, and the Library Completion stats tile shows a queued
count. When an admin fulfils your wish, the arriving book lands on your
Want to Read automatically - the intent that created the wish carries over
(never overwriting a book you're already reading). Volumes arriving for a
followed series do the same. - Hardcover sync now covers Want to Read - in both directions. Queueing a
book in Tome shelves it as "Want to Read" on your Hardcover profile, and
books you shelve on Hardcover appear as Want to Read in Tome (for books
Tome has matched to the Hardcover catalogue). Removing a book from the
Hardcover shelf reverts it in Tome only when both sides had agreed on it;
a book you're actively reading in Tome is never touched, and ratings and
progress remain push-only as before. Shelving a book Tome doesn't have at
all creates a wish on your Tome wishlist instead (with cover and author from
the Hardcover catalogue), un-shelving it on Hardcover dismisses that wish
again, and re-shelving it reopens the same wish. Books already in the
library that merely lack a catalogue match are recognised and skipped
rather than wished for twice. - Library Health now detects orphaned entries - books whose files no longer
exist on disk (for example after files were deleted or moved outside of
Tome). A new section lists them and a one-click "Remove Dead Entries" action
cleans them up: dead file entries are removed and books left with no files
at all are deleted entirely. Entries whose file still exists are never
touched. (#165) - Duplicates (Admin) gained a "Delete Others" action: keep the selected book
and delete the other copies in the group, including their files on disk,
with an inline confirmation step. Files that are missing from disk are now
badged as such on each duplicate, so dead copies are easy to spot. (#165) - New
POST /api/books/bulk-deleteendpoint deletes several books in one
request with per-book permission checks and error reporting. The dashboard's
multi-select delete now uses it instead of issuing one request per book,
and failures are reported instead of silently skipped. (#165) - The Duplicates tab now works in one pass: pick the book to keep and an
action (Merge, Delete Others, Dismiss) per group, then hit a single "Apply
All" - instead of the screen refreshing and resetting your selections after
every individual merge or dismiss. A summary reports what was applied and
any failures. (#165)
Fixed
- OPDS feed links now carry the correct public scheme behind a TLS-terminating
reverse proxy. The feed built its links from the request as the app server
saw it - plain http - so every navigation, download, and cover link came out
ashttp://even when the catalog was reached over https. OPDS now resolves
the public origin the same way the KOReader plugin URL and OIDC redirect do:
TOME_PUBLIC_URLwhen set, otherwise theX-Forwarded-Protoheader. (#167) - KOReader plugin (build 38 / 1.11.1): popup menus - the series browser,
Authors, Shelves, the Inbox and the TomeSync menu itself - could freeze on
their first page when a full-screen home-screen plugin (such as
bookshelf.koplugin) covers the file browser: page turns happened internally
but the screen never repainted, and stale refreshes could leave blank white
rectangles behind. The menus now repaint through their own window instead of
the hidden file browser. (#166) - "Select all" on the dashboard now selects every book matching the current
filters, not just the ones the infinite scroll had already loaded - so bulk
actions on large libraries no longer silently miss the books further down.
(#165) - Toggling "Group series" no longer occasionally shows duplicate books in the
grid: an in-flight page request from the previous view could land after the
toggle and append stale results onto the fresh list. Page requests are now
cancelled when the view changes, and appends are deduplicated. (#165) - Merging duplicates now actually transfers the removed book's files to the
kept book. Previously the transferred file entries were silently deleted
together with the removed book, leaving the files on disk untracked. - Merging duplicates no longer carries dead file references over to the kept
book: entries whose file is missing from disk are dropped during the merge
instead of leaving the kept book with a file that errors on open. (#165)