Skip to content

v2.1.0 "Palimpsest"

Choose a tag to compare

@bndct-devops bndct-devops released this 26 Jul 18:18
· 26 commits to main since this release
4d6e2e5

A palimpsest is a manuscript page scraped clean and written over - the older
text still faintly visible underneath. That is this release: your reading
history stops being an append-only artifact and becomes something you can
inspect, correct, and rewrite - while nothing is ever silently lost.

Highlights

Your KOReader history is now part of the session log. Reading synced from
KOReader's statistics - including everything from before Tome existed - used
to count toward your totals but never appear anywhere: a book could claim
"1 session" over an empty list, and an accidental open was stuck in your
timeline forever. Imported reading now shows up as individual sittings in
Recent Sessions and on every book page, grouped the way KOReader itself
thinks about sessions, each deletable on its own - even a 7-second
accidental page flip. A small info icon next to every session list explains
the labels in place, and nothing is ever counted twice: on books with
imported history, the plugin's duplicate live sessions stay visible with a
"not counted" tag instead of quietly disappearing.

Click a day, fix a day. Every bar in a book's Activity chart is now a
button: it opens that day's sittings with the same trim and delete actions,
so removing one stray entry no longer means scrolling the full session log.

Runaway sessions are over. A device that never actually slept - a cover
that failed to suspend it, a reader who fell asleep mid-chapter - used to
book the whole night as reading (#150). The plugin now counts active reading
the way KOReader's own statistics do, with a configurable idle cap per page
turn. For sessions already on the books, there's trim: a scissors button
that shortens a session to what you actually read, pre-filled with a
suggestion computed from that session's page turns at your own reading pace.
Implausible sessions are flagged, and arriving runaways from older plugin
builds raise a notification instead of silently distorting your numbers.

History lands on the right volume - and heals itself. Imported history
could confidently attach a missing volume's entire reading log to a sibling
volume (#152): hours of sessions on a book never opened. The matcher now
treats volume numbers as authoritative, and on your first start after
upgrading, a one-time repair re-verifies every stored match under the fixed
rules - ghost data is removed, the device re-syncs clean history on its next
connection, and a notification tells you if anything was fixed. Books mixing
wrong and genuine history are deliberately left untouched and flagged; a new
per-book "clear imported history" action is the manual escape hatch.

KOSync clients pick up your Tome position. The KOSync-compatible endpoint
(stock KOReader sync, Readest, and friends) used to be an island. Now the
sync pull answers with the newer of the two positions - the client's own last
push or Tome's (web reader or TomeSync device) - and documents auto-link to
their books by file hash, no OPDS heuristic required. A "Link KOReader sync"
picker on the book page covers the rest. Pushes remain deliberately isolated:
a KOSync client never moves positions on devices running the TomeSync plugin.
Thanks @sn0opy for the request and the hash-parity verification (#156).

KOReader plugin

This release ships plugin build 37 (1.11.0) - one build since 2.0.0:
idle-capped session accounting (configurable in TomeSync settings, including
off).

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, no new env vars. One one-time behavior: on
the first start after upgrading, the server re-verifies imported KOReader
history matches (see Highlights) - it runs in the background, is idempotent,
and notifies you only if it changed anything.


Full changelog

Added

  • KOSync clients now pick up your Tome reading position (#156). The
    KOSync-compatible endpoint (stock KOReader sync, Readest, and friends)
    used to be an island: it only ever served what a KOSync client itself had
    pushed, so progress from the web reader never reached those apps. The sync
    pull now answers with the newer of the two - the last KOSync push or
    Tome's own position (web reader or TomeSync device) - at percentage
    precision, since KOSync locators and web CFIs aren't convertible. The
    bridge is strictly read-only: KOSync pushes still never move positions on
    devices running the TomeSync plugin.
  • KOSync documents auto-link by file hash. Linking a synced document to
    its Tome book no longer depends on the OPDS-download heuristic: any file
    that came from Tome is recognised by its KOReader partial-MD5 and linked
    automatically on the first push or pull. The OPDS heuristic remains as a
    fallback for files Tome has never seen.
  • Manual sync linking in the UI. When a KOSync client has synced a
    document that isn't attached to any book, the book page offers a small
    "Link KOReader sync" picker - no more calling the API by hand.
  • Imported KOReader history shows up as sessions - and single sittings can
    be deleted.
    Reading synced from KOReader's statistics (including history
    from before Tome existed) used to count toward the totals but never appear
    in Recent Sessions or the per-book session list, so a book could claim "1
    session" over an empty list and an accidental open was impossible to remove
    without wiping the book's whole imported history. The session lists now
    include imported sittings (marked "imported", grouped the same way KOReader
    groups sessions), each deletable on its own; the book page's session count
    matches the sittings that count. Imported sittings can't be trimmed -
    KOReader's own idle-capping already applies. On books with imported
    history, the plugin's live device sessions describe the same reading a
    second time, so they are excluded from the totals - but they stay in the
    list with a "not counted" label rather than disappearing. An info popover
    next to the session lists explains all of this in place.
  • Click a day in the book page's Activity chart to manage that day's
    sessions.
    Each bar opens a popup with the sittings that started on that
    day - trim or delete right there instead of scrolling the full session
    log to find the one stray entry.
  • The Habits tab's session timeline now draws imported KOReader sittings
    too, so device reading on stats-synced books appears in the ribbon
    instead of leaving those days blank. The superseded live device sessions
    are left out of the drawing - the same reading would otherwise paint
    twice.
  • Clear imported history per book. The Reading intensity panel on a book
    page grows a small trash action that removes the current user's imported
    KOReader page data for that book - the manual escape hatch for mixed cases
    the automatic repair deliberately leaves alone. Web and manual sessions are
    unaffected, and reading the book on a device again re-imports from there on.
  • Runaway reading sessions are over (KOReader plugin, build 37). A device
    that never actually sleeps - a cover that fails to suspend it, or a reader
    who fell asleep mid-chapter - used to book the whole wall-clock span as
    reading, turning a 15-minute evening into an 8-hour session (#150). The
    plugin now counts active reading the way KOReader's own statistics do:
    each gap between page turns is credited at most an idle cap (10 minutes by
    default, configurable in TomeSync settings, including off), and the session
    ends at the last page turn rather than whenever the device finally slept.
  • Trim a session instead of deleting it. Sessions that idled - real
    reading followed by hours of nothing - can now be shortened from the
    Recent Sessions list: a scissors button opens a small editor, pre-filled
    with a suggested duration computed from the session's page turns at your
    own median reading pace, so the reading stays and the idle tail goes.
    Suspicious sessions (implausibly long, or minutes per page turn) are
    marked with a warning icon and the list can sort longest-first. The same
    session list lives in two more places: the per-book time table on the
    Library stats tab expands per book, and every book page grows a
    collapsible "Sessions" section under Reading Stats - so sessions stay
    editable even on a stats dashboard with those tiles removed.
  • A heads-up when a runaway session syncs. Sessions arriving from older
    plugin builds still get sanity-checked on the server: an implausibly long
    one raises a bell notification pointing at Reading Stats, so a bad night
    never silently distorts your numbers.

Fixed

  • A seconds-long accidental open synced from KOReader history now shows up
    in the session lists and the Activity day popup so it can be deleted.
    Such blips are below the noise floor for session counting (a 7-second
    page flip is not a sitting) and were filtered out of the lists entirely -
    but their seconds still drew an Activity bar and set "last read", so the
    one entry people most want to remove was the one entry that never
    appeared, and its day popup claimed "No sessions recorded".
  • KOSync progress pushes now follow the same read-status rules as every
    other sync path: finishing requires 99% (was 95%), completion is sticky
    (a re-read no longer drags a finished book back to "reading"), and the
    finish date is recorded.
  • Imported KOReader reading history can no longer land on the wrong volume of
    a series (#152). When a volume read on the device was missing from the Tome
    library, the history importer's title matching could confidently attribute
    its entire reading log to a sibling volume - hours of sessions and page
    data on a book never opened. The matcher now treats a parsed volume number
    as authoritative: a candidate claiming a different volume is never matched,
    half-volumes (2.5) resolve exactly instead of truncating, and French-style
    "T2" tome numbering is understood. History for a volume Tome doesn't own is
    parked until the book exists rather than guessed onto a lookalike.
  • On update, previously mis-imported history heals itself: stored matches are
    re-verified against the fixed rules on startup, ghost page data whose book
    has no other import source is removed, the device re-syncs its history on
    the next connection, and a notification explains what happened. Books where
    wrong and genuine history are mixed are left untouched and flagged instead.
  • Chart tooltips on Reading Stats no longer detach from the cursor or hide
    behind neighbouring tiles (#151). The activity heatmap, the hour-by-day
    heatmap, and the timeline ribbon all rendered their hover tooltip inside
    the dashboard tile, where the grid's CSS transform re-anchored it and
    clipped it under adjacent cards; tooltips now render at the document root
    and follow the mouse everywhere.