Skip to content

v2.0.0 "Omnibus"

Choose a tag to compare

@bndct-devops bndct-devops released this 19 Jul 17:44
· 43 commits to main since this release
c3d3acf

An omnibus is a single volume that collects many works. This release is that:
sixteen features in one cut, the largest so far. The jump to 2.0 marks the
first public-facing surface (share links) - everything else stays fully
backward compatible.

Highlights

Your reading life, on one ribbon. The new Timeline tab on Reading Stats
draws every book you've ever read as a bar in time - one lane per series,
volumes as numbered bars, each day's reading shaded inside them. It's lifetime
and fully reconciled (imported KOReader history included), opens at today, and
zooms from years down to weeks. Hover any bar and it answers to the day:
"15 May · 22m".

Sync that has your back. Tome now keeps a short position history per
book, so the classic sync horror story - a device jumping a book to 100% and
propagating it everywhere - is one click to undo, falsely-finished status and
all. And on the device, the new sync on suspend toggles mean your morning
stats are current without ever waking the reader: close the lid, everything
pending catches up (with an aggressive variant that turns WiFi on first for
radio-sleepy devices like PocketBook - thanks @diogocardoso28 for the
request, #128).

The device browser grows shelves. KOReader's TomeSync browser now has four
ways in: series, search, authors - and your shelves from the web app,
resolved live with book counts. Your "German" shelf is one tap away on the
Kindle.

Reading history from your old life. Settings → Import takes a Goodreads
or StoryGraph export
and fills the gaps - statuses, ratings, finish dates -
without ever overwriting what Tome already knows. Pre-Tome years finally land
on the timeline.

Share a shelf, a series, or a single book. Each can mint a revocable
public link - a clean read-only page with covers, titles, tags, descriptions,
your ratings and highlights, and your reading itself: time, days, finish
dates, and a day-by-day activity strip. Shared series mirror the real series
page, arcs and arc descriptions included. Links can expire on their own
(1/7/30 days) or live until revoked, and Settings -> Share links lists every
one you've minted. Never files: no downloads, no reading, no route to book
content at all, unguessable and unlisted. Your library stays yours; your
taste gets to travel.

Quality of life, everywhere. Cmd+K command palette. "Time left in chapter"
in the web reader at your measured pace. Edit highlight notes from the web,
synced back to the device. Push notifications to ntfy/Gotify/webhooks. Upload
dedupe before the bytes move. A cover-quality audit. One-click instance backup
with staged, safety-netted restore. A What's-New panel so features stop
shipping invisibly - starting with this release. An audit log that covers
everything again. And the mobile web app finally feels like an app: no more
sideways drag, edge bounce, or double-tap zoom.

KOReader plugin

This release ships plugin build 36 (1.10.0) - covering builds 32→36 for
anyone updating from 1.8.0: position pull strategy, device search + author
browse + status write-back, library sweep, sync on suspend, and shelves.

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, no config changes required. New optional env vars:
TOME_UPDATE_CHECK and TOME_OUTBOUND_NOTIFY (both default on, both purely
additive).


Full changelog

Added

  • Share a shelf, a series, or a single book — metadata only, by design.
    Shelves (share icon in the sidebar), series (share icon on the series
    page), and individual books (Share button on the book page) can each mint
    a revocable public link: a clean read-only page with covers, titles, tags,
    descriptions, your ratings and highlights — and your reading of it: time,
    reading days, finish dates, and a little day-by-day activity strip. It never exposes files — no
    downloads, no reading, no route to book content at all; links are
    unguessable, marked noindex, and die the moment you revoke them.
  • Reading Timeline — your reading life on one ribbon. A new Timeline tab on
    Reading Stats draws every book you've ever read as a bar in time: one lane
    per series (named in a frozen rail on the left), volumes as numbered bars
    spanning first to last active day, and the intensity of each day's reading
    shaded inside the bar. Lifetime data, including imported KOReader history,
    reconciled the same way as the rest of stats. Zoom from a year-at-a-glance
    down to month detail, hover any bar for the cover and totals, click through
    to the book. The tab renders full-bleed — edge to edge, viewport-tall — and
    the ribbon is also available as a regular tile in the dashboard gallery.
  • Sync on suspend (KOReader plugin, build 35). Two new opt-in settings
    make morning stats current without waking the device (#128). "Sync on
    suspend" catches up anything still pending — sessions, ratings, and the
    reading-history backfill — when the device goes to sleep, provided WiFi is
    already connected. "Aggressive sync" additionally turns WiFi on first for
    devices that sleep the radio (e.g. PocketBook), letting the system power it
    back down as the device suspends. Everything on this path is
    queue-or-resume safe: if the device sleeps before the sync finishes, it
    completes on the next connection. Reconnecting WiFi now also catches up the
    reading-history backfill (previously launch-only) and flushes pending
    sessions even before a book is opened.
  • Shelves on your device (KOReader plugin, build 36). The TomeSync series
    browser gains a Shelves entry: your saved shelves listed with live counts,
    each drilling into the same book list as a series — download per book or
    all at once, read-status markers included. Shelf filters resolve
    server-side (search, series, author, tag, format, language, library,
    reading status, rating).
  • Sync closed books (KOReader plugin, build 34). A new TomeSync menu
    action walks the device for books the plugin has never synced — read before
    Tome existed, sideloaded, or opened under another launcher — matches them
    against your library by content hash, and adopts each one's status, rating
    and reading position from its KOReader sidecar. Adoption only fills what
    Tome doesn't already have: it can never overwrite live sync state or your
    own curation. The sweep is resumable (interrupting it loses nothing) and
    cheap to re-run — books are skipped until their sidecar actually changes.
    Matched books also become fully synced from then on, positions, highlights
    and all.
  • Search your library from the device (KOReader plugin, build 33). The
    series browser gains a "Search library…" entry: submit-based free-text search
    over title, author, and series, with your last searches one tap away. Results
    open the same drill-down list as a series — tap to download, hold to set read
    status.
  • Browse by author on the device (build 33). A new author axis in the
    series browser — the natural way into standalone books, which previously all
    hid behind the single "No Series" bucket. Downloads file each book by its own
    series/author identity, exactly like the web.
  • Set read status from the device browser (build 33). Hold any book row in
    a series, author, or search list to mark it unread / reading / read on the
    server — no need to open the book. The lists also show each book's current
    status alongside the existing "on device" marker.
  • Position pull strategy (KOReader plugin, build 32). What happens on book
    open when the server position differs from the device is now configurable,
    like stock KOSync: "Server position is ahead" and "Server position is
    behind" each offer Ask before jumping / Jump automatically / Do nothing
    (TomeSync settings). Defaults keep the historic behavior — forward jumps
    happen silently, backward jumps never — and the ask-dialog is deferred a
    moment after open so it can never swallow a "on book opening" profile the
    way the old layout-reset bug did.
  • Position history — undo a bad sync. Tome now keeps a short log of every
    meaningful reading-position change per book (device, web, manual — the
    idle heartbeat doesn't spam it). A history button on the book page's
    Reading Stats header lists them, and any entry can be restored as the live
    position with one click — including explicitly un-finishing a book that a
    device falsely jumped to 100%. Devices pick the restored position up on
    their next sync. The classic sync horror story is no longer unrecoverable.
  • Import your Goodreads or StoryGraph history. Settings → Import reading
    history takes either service's CSV export, matches it against your library
    (ISBN first, then title/author), and shows a full preview before anything
    is written. Importing only fills gaps — statuses, ratings, reviews, and
    finish dates you already have are never overwritten — and "to read"
    shelves are skipped. Pre-Tome reading finally lands on the lifetime
    timeline.
  • Push notifications to ntfy, Gotify, or any webhook. Settings →
    Notifications lets each user add outbound channels; every in-app
    notification (wish fulfilled, new volume detected, reading goals) is
    pushed the moment it happens instead of waiting for the next visit. Each
    channel has a test button, can be paused, and tokens are stored
    server-side only. TOME_OUTBOUND_NOTIFY=false switches the whole feature
    off; nothing is sent unless a user configures a channel.
  • "Time left in chapter" in the web reader. The reader footer now shows
    "~12 min left" beside the chapter name, computed from the book's chapter
    map and your own measured reading pace (a sensible default until you have
    reading history). Quietly absent for books without a chapter map or word
    count.
  • Edit highlight notes from the web. The Highlights page and the book
    page's Highlights & Notes section can now edit (or add) the note on any
    highlight — including ones made in KOReader — not just delete them. Edits
    win on your devices at their next sync, exactly like an edit made on
    another device.
  • Command palette. Press Cmd+K (Ctrl+K) anywhere to jump straight to a
    book, series, author, or page — full-text book search with covers, ranked
    series/author matches, and quick navigation, all keyboard-driven. The
    header search box hints it, and it's listed under "?" shortcuts help.
  • Search previews everywhere. On Stats, Highlights, Wishlist, and the
    other section pages, typing in the header search now shows a live dropdown
    of top matches (Enter still opens the full filtered grid) — previously
    those pages gave no feedback until Enter.
  • Upload knows what you already have. Files added to the upload dialog are
    hashed in the browser and checked against the library before anything is
    sent — exact duplicates get an "already in your library" note with a link to
    the existing book and are skipped, instead of uploading megabytes just for
    the server to silently discard them.
  • Admin → Covers: cover-quality audit. Lists books whose covers are
    missing, unreadable, or genuinely low-resolution (real thumbnails, not
    standard-source covers), with sizes shown. Books with no cover at all offer
    a one-click auto-fix from the cover search (nothing to downgrade); low-res
    ones deep-link to the book page to pick a better candidate by eye.
  • One-click instance backup and staged restore. Admin → Server gains an
    Instance backup card: download a consistent snapshot of everything Tome
    knows (database + covers + manifest; book files stay on disk), and restore
    one by uploading it — the restore is validated, requires typing RESTORE,
    and applies at the next server restart so it never happens under a live
    database. The previous database is kept alongside as a safety copy.
  • "What's new" after an upgrade. The first visit after the server moves to
    a new release shows a one-time panel with that release's notes, straight
    from the changelog — so features stop shipping invisibly. Dismiss it and it
    stays gone until the next release; fresh installs never see it.
  • Update indicator for admins. Settings → About quietly shows "vX.Y.Z
    available" (linking to GitHub releases) when a newer release exists, via a
    daily-cached server-side check. Set TOME_UPDATE_CHECK=false to disable
    the lookup entirely — nothing else phones home.
  • Timeline: the tooltip now answers at day level. Hovering a bar resolves
    the exact day under the cursor — "15 May · 22m", or "no reading" on a gap
    day — alongside the book's totals. The day data was always drawn as tick
    intensity; now it's readable.
  • Timeline on phones. The series rail narrows so the ribbon keeps most of
    the screen, and bars are tap-friendly: the first tap shows the details
    tooltip, a second tap opens the book (tapping empty space or scrolling
    dismisses it). Previously any tap navigated away immediately.
  • Highlights page polish. The deferred cluster from the original
    commonplace-book release: an only-notes filter (show just the highlights
    carrying your own notes — composes with search and on-this-day), a real
    file export (download all matching highlights as a Markdown file, next to
    the existing copy-to-clipboard), keyboard shortcuts (/ search, Esc
    clear, c collapse all, n only-notes, e export — listed in the ?
    help), and a shuffle button on the Home tab's highlight spotlight that
    re-rolls to a different quote.
  • Time per chapter. Book pages now show where your reading time went
    chapter by chapter: the book's table of contents is extracted at ingest into
    device-independent chapter boundaries, and KOReader per-page reading data is
    mapped into them — robust to font/margin changes, since every page record is
    interpreted against its own pagination. Renders on the book detail page next
    to the reading-intensity curve whenever both a chapter map and synced page
    data exist. Existing libraries get chapter maps via the Admin → Word Counts
    backfill, which now also extracts chapters (and intrinsic page counts, below)
    in the same pass.
  • Intrinsic page counts for fixed-layout books. PDFs and comic archives now
    store their real page count at ingest (EPUB deliberately doesn't — reflowable
    pagination is not a property of the book). Backfilled by the same admin job.

Fixed

  • The audit log covers new features again. A coverage pass wired audit
    entries into everything that had shipped without them: instance backup
    download and restore staging/cancel/apply, OPDS PIN and KOReader plugin
    key lifecycles, book type and series/arc curation, Hardcover account
    link/unlink, notification channels (never the token), reading-history
    imports, cover changes, bulk downloads, session deletes, highlight
    deletes, and position restores. Device sync telemetry and personal
    micro-writes stay deliberately unlogged.
  • Stats on phones: dead gap and misaligned range picker. The Stats page
    header paid the notch inset a second time inside the app shell (the top bar
    already covers it), opening a large empty band between the top bar and the
    page title on the installed app; and when the timeframe picker wrapped below
    the title on narrow screens it stayed floated right, reading as misaligned.
    The header now sits flush and the picker takes a full, left-aligned row.
  • The mobile app no longer feels like a draggable website. On phones the
    page content could be dragged sideways and rubber-banded (on iOS the Focus
    view's scaled cover fan still counted its full unscaled width as scrollable
    overflow), the viewport bounced past its edges, double-tap zoomed, and a
    long press selected interface text — classic browser-tab behavior. The app
    now clamps content to the viewport width, suppresses edge bounce and scroll
    chaining, removes double-tap zoom (taps fire immediately), disables text
    selection on interface chrome for touch devices (text fields and the reader
    keep it), and sizes the shell to the real visible viewport instead of
    overhanging behind mobile browser toolbars.
  • The notifications panel no longer renders behind sticky page content. The
    top bar sat at the same layer as page-level sticky toolbars (and below the new
    timeline axis), so the open notification dropdown was cut by the Stats
    toolbar. The top bar now stacks above content-level sticky elements.
  • Chapter maps now extract from EPUB2 books. Older EPUBs keep their table
    of contents in an NCX file rather than an EPUB3 nav document; chapter
    extraction ignored the NCX, so classics and older rips silently produced no
    Time-per-chapter data. Extraction now falls back to the NCX whenever the nav
    yields nothing — re-run Admin → Word Counts to pick up the affected books.
  • TOC-less EPUBs no longer re-queue in the Word Counts backfill forever.
    Books whose files genuinely have no usable table of contents were re-parsed
    on every run because "done" was inferred from having chapter rows; a
    dedicated attempt marker now records "tried, nothing there" once.
  • A fast server clock can no longer silently swallow highlights (build 32).
    Highlight edits and deletes made in the web reader are stamped with the
    server's clock; on a device whose clock runs behind (UTC container vs local
    device time), those stamps landed in the device's future and outranked every
    later local change — a re-highlight after a web delete just vanished until
    the clocks crossed. The plugin now stamps its wall-clock on every highlight
    sync and the server shifts the stamps it minted itself into that device's
    clock frame, both when comparing and in what it returns; the plugin
    additionally refuses to store any stamp from the future. Older plugins keep
    the previous behavior.
  • The TomeSync plugin no longer bloats KOReader's global settings file
    (build 32).
    Its data tables (book map, pending sessions and ratings, sync
    baselines, repair aliases) — which grow with your library and were parsed by
    KOReader at every boot — moved into a dedicated tomesync_state.lua,
    migrated automatically and crash-safely on first launch. State for books no
    longer on the device is pruned; pending queues are never pruned.
  • The plugin's series list no longer runs one query per series. Loading the
    series browser was an N+1 that scaled with the library; it's now a single
    query with the same response.
  • The Highlights "copy all as Markdown" export never worked. It requested
    more highlights than the API's page cap allowed, got a 422, and failed
    without any feedback. The cap is raised, the export stays under it, and a
    failure now shows an error toast instead of silently doing nothing.
  • Bindery no longer invents a series from the filename. Prose ebooks named
    Title 5.epub used to come out of review with their series set to their own
    title (the bare-number manga-chapter heuristic misfiring on novels); the
    real series name in (Series Book N) parentheticals — the common
    Amazon/Calibre naming — was stripped as noise; and the metadata embedded in
    the file itself (calibre:series etc.) was extracted but never reached the
    review form. All three are fixed: the filename parser now understands
    (Series Book N) / (Series #N) markers and the NN. Title - Author (Year)
    layout (filling the author field too), bare trailing numbers on EPUB/PDF no
    longer fabricate a series, and the review form pre-fills from embedded
    metadata with the same "file beats filename" precedence auto-import has
    always used.