Repository navigation
Releases
Theorem 1.6.1
Fixed
- Shelf actions on phones — Align Add, view and More actions to the right so the shelf dropdown stays on screen and its actions remain reachable.
- Settings help on phones — Add a Help tab for diagnostics, release downloads and issue reporting; show desktop update checking only where it works. Preserve ZIP bytes when log export uses Tauri's byte-array response fallback.
- Edited covers and metadata stay edited after sync — Merge book details and reading position independently, version cover replacements and removals, and publish the first cover edit after sync starts. Stale peer copies cannot restore an older cover or a cleared author, rating or series. Keep the search index aligned with retained metadata.
- Delete automatic copies — Remove individual automatic database backups from Data & Storage after confirming the date and size, without changing the current library or other copies.
Features & Enhancements
-
Android reminder broadcast validation — Reschedule reminders only for the five supported system actions; ignore missing, unknown and lookalike broadcast actions before accessing alarms or preferences.
-
Android security analysis — Compile our maintained Kotlin plugins for CodeQL using the locked Tauri API, without a native build or APK packaging; stop excluding plugin sources as vendored code.
-
Release cache isolation — Remove persistent Cargo/pnpm caches from signed release builds, reject tags outside main, and remove the separate release dry-run workflow.
-
Reliable local option clicks — Keep native select controls clear of reading-reminder toasts during release verification, retaining the real click and persistence assertions.
-
Local E2E release verification — Run the complete native E2E suite locally before tagging. GitHub keeps unit tests, lint, typechecks, security scans and release builds without hosted E2E jobs, nightly schedules or native test-binary builds.
-
ZIP maintenance patch — Update to zip 9.2.1, including its writer cleanup and getrandom build fix.
-
Follow-up dependency updates — Update translation rendering, icons, logging, Unicode widths and ZIP parsing.
-
Sync dependency compatibility — Keep docs and blobs versions aligned until their coordinated upgrade is available.
-
Workflow efficiency — Run automatic CI once on main, select relevant gates without losing coverage after cancellations, share verified frontend assets with native checks, and share one frontend/icon build across release platforms. Workflow and helper shell checks protect job selection; release jobs require installers and signatures before publication. Manual releases use the exact requested tag; patch releases are marked prereleases. Docs-only updates no longer redeploy the product landing page.
-
Release branch maintenance — Pull requests and manual CI check
1.6.1, and Dependabot targets the active release branch. -
Dependency maintenance — Update the JavaScript, Rust and CI dependencies, preserve hotspot discovery in the mDNS upgrade, and adapt neural speech to the new ONNX environment API while retaining compatibility with installed runtimes.
-
Updated screenshots and user guides — Fresh public-domain books and cultural feeds illustrate the current desktop and phone layouts, with a placement guide, reading rhythm, attached notes and optional navigation.
-
Optional Discover and Feeds tabs (#173) — Settings → General can hide either destination from the phone bottom bar and desktop sidebar on each device. Remaining tabs fill the space; restoring a tab retains its data and keyboard shortcuts keep their existing numbers.
-
Audiobook media controls — Supported system controls show artwork, playback state and position, and can move between chapters.
-
Generated audiobook metadata — Opus files embed book and chapter tags, including large chapter lists, with atomic cancellation-safe finalization.
-
Terminal chapter names — The TUI reads EPUB 3 navigation or EPUB 2 NCX chapter titles in spine order and retains numbered fallbacks.
-
Statistics share footer — Share cards are branded “Theorem”; recently read covers stay within a three-column footprint so the footer remains visible with fewer books.
-
Daily Review stays dismissed — Dismissal now survives app restarts for the local day; completion updates immediately and remains complete after annotation changes. The fullscreen overlay renders outside Library scrolling/containment, preventing clipping and stray scrollbar tracks, and a fresh day resets it while the app stays open.
-
Cover images from URLs — Desktop and mobile download and validate cover images in Rust, avoiding WebView CORS restrictions. The editor blocks Save while loading, ignores stale results, and preserves the previous cover after failure.
-
Readable one-time onboarding — Reading setup and the optional guide share a responsive layout with explicit page-width tokens, app illustrations, and persistent footer actions. Sidebar and Library control icons share 16px Lucide glyphs and bare-button styling.
-
Existing reading history and XP — Existing readers receive daily XP from retained reading activity, including profiles that already enabled a rhythm. Fractional minutes are supported and repeated backfills preserve awards. Library view and filter icons are larger and use bare icon controls, with rows and funnel glyphs. Statistics has equal-sized level badges, a weekly completion check and explicit scheduled goal changes, brighter earned achievements, and icons in place of emoji.
-
Reading rhythm and levels — Choose a flexible weekly reading goal, see a compact read-only level journey in Statistics, and earn lasting XP and numbered levels. Weekly goals are edited in Settings. Goals start with a suggested four days per week; five reading minutes qualify a day. Daily goals and streaks stay separate. Upgraded devices merge reading contributions and awards without duplication; older statistics remain compatible.
-
Reading-first setup — A short optional-goal setup leads to Library or Discover, with the full feature guide available on demand. Completed steps survive restart. Mobile navigation keeps its labels and shared destination order. Reading-day selectors use the app dropdown. Library retains its earlier action toolbar; selection starts in the book context menu and folder management lives in Settings. The first selected book is retained when entering selection mode.
-
Accurate reading intervals — Short sessions retain fractional minutes, midnight sessions count toward the correct local dates, hidden readers do not start a timer, and clock corrections no longer change elapsed reading time. Failed native records persist for safe retry. Fractional durations display without long decimals, and successfully opening a book adds a continue-reading cue to its existing card before a page turn.
-
Replay-safe reading records — Added an immutable native reading-chunk API so retrying a recorded interval cannot add its minutes twice. The legacy additive session command remains supported.
-
Daily Review Card Stack in Library — Upgraded the static Daily Highlight banner into an interactive physical 3D card deck embedded at the top of the Library feed. Controlled by
settings.showDailyHighlight("Daily Review"), the deck resurfaces daily reflections with stacked card layers, tap-to-advance, drag-tilt, fling gestures, source jumping, and session dismiss. Once reviewed or dismissed, it collapses cleanly to leave the book grid unencumbered. -
Swipe Actions on RSS Articles — On touch screens, swiping an article row right marks it read and swiping left deletes it with an Undo toast (
SwipeableArticleItem), for one-handed triage in Feeds. -
Bookmark Ribbon Cards and a Physical Card Deck — Bookmarks in the Workbench are shown as ribbon cards with their page or position instead of empty quote blocks, and the review deck now looks like a physical card deck with visible layers underneath.
-
Refocused Workbench Workspace — Workbench is refocused exclusively on deep search, filtering, and browsing across Highlights, Notes, Vocabulary, and Bookmarks without daily takeover interruptions, while retaining an on-demand deck Card View toggle (
viewMode === "cards"). -
Library List View Details (#159) — Enhanced the library list view row cards with dedicated format badges, series and volume index annotations, compact progress bar visualization, and relative date indicators for last read and added dates, maintaining a fixed 96px virtualized row height.
-
CLI Scripting & Headless Follow-ups (#162):
- Added
--data-dir <path>global option andTHEOREM_DATA_DIRenvironment variable support to run headless commands against arbitrary libraries, external drives, or testing sandboxes without modifying default application data paths. - Added
theorem highlights export [--format md|json|csv] [--book <id>] [--since <date>] [--out <path>]for scripted Obsidian markdown, JSON, or CSV highlights and notes extraction suitable for external cron jobs and PKM tools. - Added
theorem highlights card [<id>] [--book <id>] [--theme dark|sepia|tinted|light] [--format square|story] [--out <path>] [--out-dir <dir>] [--no-note]for scripted headless Bauhaus highlight share card generation as standalone PNG or vector SVG images with automatic typography fallbacks and design tokens. - Added
theorem feeds import <file.opml>andtheorem feeds export [--out <file.opml>]for importing and exporting RSS/Atom subscriptions via standard OPML format.
- Added
-
Connected Library Folders Management — Added a dedicated Library Folders section in Settings (
Settings → Storage → Library Folders) to connect, rescan, and manage external folder roots on desktop and mobile. Integrated folder filtering and book counts directly into the Library filter panel with safe folder disconnect workflows.
##...
Theorem 1.6.0
Smart Shelves & Sub-Shelves
- Smart Shelves (#132) — Introduced dynamic, automated smart shelves powered by native filter rules (reading status, tags, series, authors, and formats). Smart shelves dynamically recompute membership on library changes without manual bookkeeping, preserving upstream layout and custom shelf sorting.
- Hierarchical Sub-Shelves (#138) — Added one-level nested sub-shelves to organize large libraries hierarchically. Create and navigate sub-shelves with breadcrumbs, dedicated parent-child navigation, and unified shelf action controls.
Library & Organization
- Preserve Source Folder Structure (#133) — Ingesting folders now preserves folder hierarchy with an integrated Source Folder browser chip strip. Users can toggle between preserving directory hierarchy or flat importing, filter the library view by source folder, and keep library organizations in sync with external storage trees.
- Bulk Selection UX Overhaul (#134) — Completely redesigned filtered bulk selection. "Select All" now selects all filtered items across virtualized rows; selections automatically clear on filter shifts to prevent accidental batch operations. Features a solid full-width bottom toolbar with explicit icon+label buttons, mobile-optimized single-row control layout, Esc key dismissal, and 1-click Undo toast protection on batch mark read/unread.
- Dynamic Read/Unread Toggles — Replaced dual "Mark Read" and "Mark Unread" buttons with an intelligent, dynamic toggle across both the bulk selection toolbar and right-click book context menus. If all selected items are completed, the action displays "Mark Unread"; otherwise "Mark Read".
- Bookmarks Are a Workbench Tab — Bookmarks now open inside the Workbench like Highlights, Notes and Words: same title, same tab row with the source and sort menus beside it, and no jump to a separate Bookmarks page.
Ctrl+7still opens the Bookmarks tab directly. - Shelves Layout & Header Unification — Standardized Shelves page layout, header spacing, and toolbar button styling (
TOOLBAR_BUTTON_PRIMARY,TOOLBAR_BUTTON_BASE,TOOLBAR_ICON_BUTTON) with Library viewport standards. Action buttons, search, and back navigation remain permanently accessible across empty and populated states.
Reader & Comics
- Continuous Strip Comic Reading (#135) — Added an optional continuous vertical strip view for CBZ/CBR comic books with bounded DOM image virtualization and adaptive preloading, eliminating page-turn friction for webtoons and vertical-scrolling comics.
- Streamed Native Comic Ingestion (#136) — Streaming archive decompression in native Rust avoids whole-archive memory buffers, dramatically speeding up multi-gigabyte comic imports and preserving CBR binary responses.
Shell, Stability & Remote Announcements
- Log files & Export Logs — Theorem now keeps a rotating log file (
theorem.login the platform log folder, at most ~10 MB) with native errors, every Rust panic (location and message, quoted text redacted) and errors caught by the app's error screens. Settings → About → Export Logs saves them as a zip with the app version and platform to attach to a bug report; the home folder is written as~, and no books, notes or device keys are included. - No web inspector in release builds — Shipped builds no longer include the webview developer tools;
pnpm dev:*and debug Android builds still have them (cargo featuredevtools). - Fewer native crashes — A panic on one sync or dictionary thread no longer leaves its lock poisoned and crashes every later sync and lookup; the app recovers the lock and carries on. A system without a usable TLS backend now gets a "could not start the network client" error on feeds, articles and catalogs instead of a crash.
- Android Crash Prevention & Memory Management (#137) — Resolved startup crash loops and out-of-memory crashes on Android by deduplicating native runtime initialization, adding aggressive webview memory trimming on backgrounding, and safely validating book files before reopening last-read state.
- Remote Announcements Banner — Added a non-intrusive, zero-HTML remote announcement system (
src/ui/AnnouncementBar.tsx) delivering project updates, advisories, and release notes to all installations from a dedicated edge Cloudflare Worker (announcements.fundaments.work). Announcements are fetched asynchronously with a 24-hour local cache, fail-open resiliency, persistent local dismissal, and responsive mobile/desktop layout with severity badges (Notice,Advisory,Alert). - Zero-HTML AST Parser & Linkifier — Pure AST linkification (
src/core/lib/announcements.ts) that strictly validateshttps://URLs without credentials, trims balanced punctuation and parentheses, and converts**bold**markdown syntax into React elements without touchingdangerouslySetInnerHTML. - Reader Isolation — Announcement banners are strictly isolated from the reading view (
ReaderPage), preserving a distraction-free, zero-chrome reading experience.
Monetization & Creator Support
- Buy Me Momo Integration — Added a native support link for Nepal's creator-funding platform Buy Me Momo (
https://buymemomo.com/usefundaments), allowing domestic (eSewa, Khalti, Connect IPS) and international supporters to fund Theorem's development. - Monthly Cadence Engine — A recurring 30-day cadence model (
src/core/lib/support-prompt.ts) keeps the support prompt gentle and unobtrusive: visible on first run, dismissed or clicked prompts hide for 30 days locally without polluting P2P sync CRDT state. - Support Placements — Added an authentic crescent-dumpling
MomoIconto the desktop sidebar footer (both expanded and collapsed layouts), the mobile titlebar header cluster, and a permanent entry in Settings → Links. - Safe External Opener — Unified external link launching (
src/core/lib/open-external-url.ts) dynamically invoking@tauri-apps/plugin-openeron native desktop/mobile platforms with fallback towindow.openin browser environments.
Backup & Data Safety
- Startup integrity guard — Once a day, and on every app update before migrations run, Theorem checks its database with
PRAGMA quick_checkand keeps a rolling copy of it (db-snapshots/, the two newest). A damaged database or a failed migration is no longer only logged while the app starts with an empty library: it is reported to the app, which can put a snapshot back. The check costs about 0.4 ms per MB of database (25 ms for a 56 MB library, 210 ms for 566 MB, warm cache). After an update the copy is made before migrations, as their rollback point; on the daily check it is made in the background once the window is open, so it no longer delays that start (0.7–3 s on a 400 MB library). - Streaming backups — Backups are now one
.theorem-backupfile (a zip: manifest, a consistent SQLite snapshot, book files, generated audiobooks and, optionally, dictionaries) written entry by entry in Rust, so large libraries no longer run out of memory. A backup never carries this device's sync identity (device id, paired devices and their sync tickets) or OPDS catalog passwords. On Android the file is streamed into Downloads/Theorem. - Backup & Restore in Settings — Settings → Data & Storage now has Create Backup File (with an option to include dictionaries), Restore from Backup (shows when the backup was made and what it holds, then asks before replacing the library; the previous database is kept as
theorem.db.pre-restore) and the automatic copies with a Restore button each. The old JSON "backup bundle", which loaded every book into memory and could never be restored, is removed. - Recovery screen — When the startup check finds the database damaged or an update cannot migrate it, Theorem opens a recovery screen (restore an automatic copy, restore a backup file, or continue anyway) with all writes paused, instead of starting with an empty library.
Discover & OPDS Catalogs
- A new Discover page, curated on our server — Discover is now a front page fed by our own OPDS catalog (
catalog.fundaments.work), so its shelves, subjects and search change without an app update: a large search over all ~78,000 Gutenberg books (your language first) with recent searches kept on this device, the newest Standard Ebooks editions as hero cards, hand-picked shelves, subjects as tiles with their book counts, and a "Bring your library" card. The page is kept on the device for offline use; catalogs you add are never stored. - Your catalogs as tabs — Catalogs you add (your school, university or library, or your own Calibre, Kavita or Komga) appear as tabs next to Discover; with none added there are no tabs at all. The in-app storefront and the built-in Project Gutenberg and Standard Ebooks tabs are gone (their books are on the Discover page); one you had signed in to is kept.
- Browse any OPDS catalog — Discover is now one row of sources: the curated storefront, Project Gutenberg, Standard Ebooks and every catalog you add. Catalogs added in earlier versions were saved but never browsable (the full browser was unmounted); they all work now. Sections, shelves with See all, a trail with Back, server search with a local-filter fallback, sort/language/format filters, series and covers, and books that load as you scroll on a virtualized grid.
- OPDS 2.0 and real-world Atom — A single Rust parser (
theorem-core::opds) reads OPDS 1.0–1.2 Atom, OPDS 2.0 JSON, OpenSearch descriptions, HTML pages that advertise a feed, facets, indirect acquisition, prices and authentication documents. It runs natively on desktop and Android and through WebAssembly in the web build, so every platform behaves the same. Tested on real Gutenberg, Standard Ebooks and OPDS 2.0 reference documents plus Calibre, Komga/Kavita and Feedbooks-style output. - Sign in to private catalogs — HTTP Basic sign-in using the server's own...
Theorem 1.5.9
Comics & CBR
- Pure-Rust CBR support (#121) — Comic Book Archives are now handled natively in
src-tauri/src/cbr.rs, with no externalunrarbinary required.rars::ArchiveReaderstreams the RAR container straight into an in-memory ZIP (stored, no recompression), so a CBR opens on every platform we ship, including Android. Title and author fall back to filename parsing, andComicInfo.xmlis read when present to pick up series name, volume number, and the rest of the comic metadata. - Full CBR import parity (#121) — The RAR-to-CBZ path is wired through batch ingest, folder scanning (including the Android
FolderScanPlugin), and the reader, so CBR files behave like any other comic: cover extraction, page order, and read progress all work. The previous JavaScript/external-tool path inlib.rswas removed in favour of the single native implementation. - CBZ ComicInfo & cover extraction tests — Native coverage for
ComicInfo.xmlmetadata parsing and cover downsampling inbatch_ingest.rs.
Library & Series
- Book series metadata (#125) — Books can now carry a
seriesname and aseriesIndexvolume position (fractional values such as2.5are supported). Series are read from EPUB metadata on ingest and fromComicInfo.xmlfor comics, and are editable from the book edit modal and a dedicated Assign Series modal.seriesis a first-class sort option in the library. - Series grouping & shelf layout (#125) — Shelves can group books by series, showing each series as a labelled, ordered row with its volume numbers and combined progress. Filters and sorting were extended to respect series, and a
groupBySeriestoggle is available on the library. - Next-in-series prompt (#125) — Finishing a book that belongs to a series surfaces a toast naming the next unread volume, with a Read Next action that routes straight into it. Volumes are ordered by
seriesIndex, with a sensible fallback to reading order when a series is unnumbered.
RSS & Articles
- SQLite-backed article storage (#123) — RSS articles now live in SQLite rather than a serialized JSON blob, with a dedicated table, indices, and a new set of commands on the background pool. Store state is derived from SQLite instead of being rehydrated from a giant
kv_storepayload. - Configurable retention & offline saves (#123) — Settings → RSS & Articles Retention adds an Article Retention Period (Keep Forever / 15 / 30 / 60 / 90 days, default 30) that auto-prunes read, non-favorited articles and their cached content. A separate Keep Unread Articles toggle protects unread items regardless of age, and articles saved offline via the new
isSavedflag are always preserved from cleanup.
Vault & Export
- Chapter-wise highlight organization (#126) — Obsidian and Markdown export can now group highlights By Chapter (Hierarchical) — the default — or as a flat chronological list. Chapter title and index ride along on each annotation, so exported notes mirror the book's structure instead of dumping highlights into one undifferentiated list. New
VaultHighlightGroupingsetting in Settings, with golden-file preset tests.
Fixed
- RSS article highlights & bookmarks resolve (#124) — Highlights and bookmarks taken in an RSS article previously showed up detached in the Library, without article title, feed, or a working jump target. Annotation sources now resolve article metadata correctly, and clicking one restores the reader's scroll position instead of landing at the top.
- Batch ingest materializes books on disk (#library) — Ingested books were registered in SQLite without their files being written to the library directory, leaving them unopenable. Books are now materialized on ingest, and legacy directories are cleaned up on startup.
- Non-destructive sync merge (#library) —
sqlite_merge_sync_entries_with_dirverifies that a peer's book actually exists on disk before clearing itssyncedWithoutFileflag and adopting a local path. A merge can no longer leave a book marked as present-but-missing, and local file paths are preserved across merges. - Legacy annotation chapter metadata backfill (#reader) — Annotations created before chapter metadata existed are backfilled automatically when the book is opened, restoring correct chapter grouping in exports and the annotations panel.
- Dictionary MDX fallback scan (#dictionary) — MDX dictionaries whose key blocks overlap in case (e.g. an uppercase entry adjacent to a lowercase one) could fail to resolve. The fallback scan now handles case-overlapping key blocks correctly.
- Mobile page-end scrolling & grid (#mobile) — Pages now scroll fully to their end, the scrollbar rail is hidden, and the library grid starts with the correct column count instead of snapping to a wrong layout on first paint.
- Release CI (#122) — Fixed desktop release asset links and made the release workflow build all Android ABIs instead of a subset.
Documentation
- Replaced the README screenshot set with a current, organized gallery (desktop and mobile), and pointed the web demo link at
read.fundaments.work. - Added an RFC evaluating a native PDFium engine for PDF rendering.
Download & install
| Platform | Download |
|---|---|
| Windows (x64) | Theorem_1.5.9_x64-setup.exe |
| macOS (Apple Silicon) | Theorem_1.5.9_aarch64.dmg |
| macOS (Intel) | Theorem_1.5.9_x64.dmg |
| Linux (Debian/Ubuntu) | Theorem_1.5.9_amd64.deb |
| Linux (any) | Theorem_1.5.9_amd64.AppImage |
| Android (arm64, most phones) | app-arm64-release.apk |
| Android (32-bit arm) | app-arm-release.apk |
| Android (x86_64 emulator) | app-x86_64-release.apk |
| Android (x86 emulator) | app-x86-release.apk |
Linux one-liner: curl -fsSL https://raw.githubusercontent.com/Fundaments-Work/Theorem/main/scripts/install-linux.sh | bash
Desktop builds auto-update in place (Settings → About → Check for Updates). Android updates are manual unless installed via F-Droid.
Theorem v1.5.8
⚠️ Breaking Changes & Migration Notice
Important
Database, Highlight Migration & Breaking Changes:
- Self-Healing Highlights & CFI Re-Anchoring: Older annotations created on prior builds or shifted EPUB spine formats (such as outdated DOM
[w_...]assertions) will now automatically be re-anchored on access via high-speed in-document text scanning, smoothly navigating to the target passage and writing healed canonical CFIs back to local SQLite storage. - Hydration & Tombstone Integrity: Fixed an asynchronous startup race condition that previously caused book annotations to be quarantined as orphaned before book metadata finished hydrating. Sync merge now strictly enforces local and remote deletion tombstones, preventing purged books and annotations from resurrecting.
- Virtualizer Layout Cache Invalidation: Grid, List, and Compact view mode caches are now decoupled; previous display issues with overlapping book cards or clipped titles on view switch are automatically cleared.
- Desktop Dev Process: Development window closing has been separated from release behavior;
pnpm dev:taurinow terminates cleanly on window close without hanging background watch processes.
Reading System & Highlights
- Resilient highlight re-anchoring & self-healing — Highlights pointing to stale, modified, or migrated EPUB locations (such as outdated word-level
[w_...]assertions or shifted spine chapters) now automatically fall back to microsecond DOM text search across the document, smoothly scroll to the exact passage, draw the highlight, and self-heal by writing the clean, valid CFI back to the library store and SQLite database. - In-reader annotation navigation — Unified annotation clicks directly with native location routing and forced overlayer redraws, eliminating stale text-range selection jump failures.
- Deleted highlights persistence — Fixed native sync merge re-inserting annotations and books from stale doc entries after applying tombstones; local tombstones are now transmitted and respected across all merge operations.
- Highlights hydration race condition — Prevented startup from treating annotations as orphaned when annotations loaded before book records, ensuring zero highlight loss on startup.
Library & UI/UX
- Library & Shelves view mode switching — Fixed virtualizer row height cache invalidation when toggling between Grid, List, and Compact views, eliminating card overlaps, clipped titles, and broken spacing. Aligned Shelves grid column layout with the virtualizer column detection to prevent accidental row item wrapping.
- Workbench & Bookmarks card redesign — Cards adaptively fit content with uniform gaps and text-measured heights; long passages collapse with "Show more", menus close on outside click or Escape, article highlights are listed properly, and Bookmarks shares the redesigned toolbar and layout.
- Desktop dev watcher — Scoped Tauri window close prevention strictly to release builds, ensuring
pnpm dev:tauricloses and restarts cleanly without hanging background processes.
Web & Performance Parity
- Edge Immutable Caching (W1) — Configured
public/_headersspecifyingmax-age=31536000, immutablefor/assets/*,*.wasm,/wasm/*,/pdfjs/wasm/*, and/fonts/*, withmax-age=0, must-revalidatefor/index.html(0ms repeat load from browser disk/memory cache). - Active Client WASM Hookup (W2) — Connected
theorem-core.wasminto the web client so browser-mode searches use SIMDwasm_fuzzy_rank(nucleo-matcher) andwasm_markdown_to_html(pulldown-cmark) instead of JS regex fallbacks. - Web Worker Task Offloading (W3) — Offloaded WASM fuzzy ranking, Markdown rendering, and background EPUB unzipping to a dedicated Web Worker (
core-worker.ts) using transferableArrayBuffers, keeping the main UI thread at 120fps during inflation and search. - Origin Private File System (OPFS) (W4) — Streamed large book binaries directly into OPFS (
navigator.storage.getDirectory()), avoiding IndexedDB clone overhead with zero-copy reads and transparent IDB fallback.
Reading System
- PDF links and Theorem Lens — Citations, footnotes, TOC links and URLs in PDFs are clickable. Hovering an internal link shows a borderless preview of the destination rendered from the page; clicking it jumps to the exact spot, even on pages not loaded yet. Back/forward history (Alt+←/→, mouse buttons 4/5, Android back).
- PDF smoothness — Wheel and pinch zoom preview with a transform and re-render once, anchored under the cursor; the initial fit no longer opens a third of a page down. Rendered pages live in a bounded LRU (6 pages / 24 MP on desktop, 3 / 8 MP on Android). Canvas and text layer render separately, so text selection survives scrolling and no longer blinks. On WebKitGTK the time blocked during a zoom dropped from 1483 ms to 136 ms.
- PDF features — Page thumbnails (Navigation → Pages, rendered only when the viewer is idle), Present mode (F5: full screen, one page at a time), Print (Ctrl+P, desktop), embedded attachments listed in Book Info with Save, Define/Copy for selected text (same dictionary as EPUB), logical page labels (
xii (12), go toA-3), match-case / whole-word search with F3 cycling, and document properties (producer, PDF version, page size, correctly parsed creation dates). Pages are always shown as the file draws them: the old dark/sepia filters, which also recoloured photos, are gone. The tool palette and View panel use the reader's square style. JPX, JBIG2 and CCITT images now decode; the pdf.js cmaps, fonts and wasm decoders ship at the right paths (they were missing from builds), with a post-build check. - EPUB — Selections highlight glyphs only, like PDF, instead of flooding margins. Only the visible chapter's highlights are drawn (one call instead of about 1,000 on open). Books are read by byte range, and every chapter and image is decompressed in Rust (
epub_read_entry) instead of zip.js on the UI thread. - Fast scrolling — A fling or scrollbar drag renders entering pages at low resolution first (instead of leaving them white), then sharp when scrolling stops.
- No UI-thread blocking from native calls — 64 Tauri commands (SQLite, PDF/EPUB reads, file reads, RSS and article fetches, metadata parsing) used to run on the window's main thread; they now run on a background pool. SQLite calls keep their order through a FIFO queue.
- theorem-core WASM & Native Crate (R9) — Extracted pure computational algorithms (pulldown-cmark Markdown rendering, nucleo-matcher SIMD fuzzy matching, deterministic speech text normalization, and PKM note vault formatting) into an independent workspace crate
theorem-coresupporting both native compilation and wasm32.
Fixed
- In-book search — Finds the literal text, every occurrence on every page, instead of "fuzzy" results made of scattered letters; PDF search uses the text pdf.js decodes. EPUB match positions stay correct around characters whose lowercase has a different length (e.g. "İ").
- Library search — No more unrelated titles matched by scattered letters (only compact matches or word-start acronyms like "lotr"). Shelves use the same native search as the Library, results no longer flash, a failed search falls back instead of showing nothing, and deleted or renamed books no longer linger in the search index.
- Rotated PDF pages — Pages a PDF marks as rotated (common in scans) were drawn sideways.
- No lost data on quit — Pending writes (library, progress, reading time) are flushed to SQLite before the window closes, the app quits from the tray, or it goes to the background.
- Sync after page turns — Reading progress syncs at most every 30 s instead of starting a full sync round two seconds after each page turn (a source of periodic stutters).
- Statistics in local time — Reading days, streaks, goals and the daily reminder used UTC dates.
- Reading speed — Measured over the whole time on a page instead of counting each page twice.
- Vocabulary and annotation storage — Replaced the dual-write to JSON blobs with SQLite as the single source of truth on native platforms. State serialization drops full arrays from
kv_store, eliminating JSON stringification overhead and preventing resurrected items during rehydration. - Sync merge in Rust —
sqlite_merge_sync_entriesdirectly applies incoming gossip updates and deletion tombstones for books, annotations, vocabulary, and RSS articles within an atomic SQLite transaction, returning granular diff reports of changed entity IDs so in-memory stores update incrementally without full-collection re-stringifications or IPC roundtrips. - Relational library store — Decoupled book metadata persistence from giant JSON blobs in
kv_storeon native platforms into individualbook_metadatarows in SQLite.partializeexcludes books from Zustand persistence payload, andupdateProgresssaves reading state directly viasqlite_update_book_progresswithout re-serializing the library or triggering FTS re-indexing on every page turn. - Vocabulary sync — Merges write only changed terms and propagate deletions.
- RSS — Favorites are never aged out; other articles are kept for 30 days, newest 500. Feeds refresh four at a time. All Markdown is rendered by
pulldown-cmarkin Rust, with raw HTML andjavascript:links neutralised. - Vault export — Only changed notes are rewritten; notes for removed books are deleted unless you edited them. Obsidian, Logseq, Minimalist, and Custom (Knap) presets with an integrated live template editor, syntax validation, and wikilink/callout filters; the native and fallback exporters write byte-identical notes and file names (shared golden tests).
- Covers — Stored as raw image bytes (a third smaller than base64; converted on first start) and served from SQLite via
theorem-cover://without decoding, in...
Theorem v1.5.7
Fixed
- Mobile EPUB Navigation & Image Rendering Stabilization — Restored immediate, fluid page turns and eliminated blank pages across illustrated and media-rich EPUBs:
- In
foliate-js-runtime/paginator.js, eliminated the blocking pre-layout image decoding wait and 200msvisibility: hiddenblanking, restoring immediate synchronous layout rendering and zero-latency#turnPageresolution. - Fixed CSS multi-column fragmentation: removed
break-inside: avoidand-webkit-column-break-inside: avoidon parent<p>,<div>, and<figure>containers that caused the browser column formatter to abandon columns and generate blank pages before images. - Removed
display: blockandheight: auto !importantoverrides onimgelements, preserving natural aspect ratios and fluid column fitting withobject-fit: contain. - Calibrated touch gesture axis locking to 10px with natural horizontal dominance, preventing swipe drops on diagonal thumb arcs.
- Preserved chapter blob URLs during active reading sessions to prevent broken image assets on previous-chapter navigation.
- Fixed iframe initial visibility transition ensuring content is immediately rendered visible upon load completion.
- In
- Ghost Book Elimination on P2P Sync Deletions — Fixed ghost book cards remaining in the library when a book was deleted on a paired peer:
- In
src-tauri/src/file_transfer.rs, added checks againstdeletion_tombstonesanddeletedAtmetadata, returning an explicitPEER_BOOK_DELETEDstatus if a requested book has been deleted. - In
src/core/lib/sync-orchestrator.ts, immediately merged incomingdeletion_tombstonesover Iroh gossip and purged deleted book cards from local state without delay. - In
src/features/reader/Reader.tsx, handledPEER_BOOK_DELETEDby pruning the local ghost card, displaying an informative toast ("This book was deleted on the source device."), and routing to the Library.
- In
- Android Hardware Back Button Navigation Stack — Intercepted Tauri
onCloseRequested/ hardware back button events insrc/App.tsx:- Dismisses active overlays, sheets, and reader panels in LIFO order via
dispatchBackAction(). - Navigates from Reader view back to Library before closing.
- Minimizes or exits the app only when on the root Library route with no active overlays.
- Dismisses active overlays, sheets, and reader panels in LIFO order via
Improved & Performance
- Note Export Clean Typography & Knap AST Templating —
- In
src-tauri/src/vault_export.rsandsrc/core/lib/vault-sync.ts, cleaned YAML frontmatter to include only essential properties (title,author,type: "theorem-book-highlights", singletotal_highlights: N, andtags: [theorem, highlights]), removing internal paths, formats, and redundant duplicate counts. - Overhauled Markdown body formatting: removed artificial numbered headings (
### 1. Highlight), redundant color labels, timestamps, and divider lines. Quotes are formatted cleanly as> ==quote==with user notes placed directly underneath. - Integrated
@obsidianmd/knapAST template engine in frontend export settings for safe, custom Markdown templates with 0 bytes added to the native Rust binary.
- In
- SQLite Memory Reclaim & Low-Memory OS Trimming —
- Enhanced native
trim_memorycommand insrc-tauri/src/database.rsandlib.rsto runPRAGMA shrink_memory;andPRAGMA wal_checkpoint(PASSIVE);on SQLite connections alongsidelibc::malloc_trim(0)on Linux and Android Bionicmallopt(-101, 0)(M_PURGE). - Wired
document.visibilityState === 'hidden'insrc/App.tsxto automatically triggertrim_memorywhenever Theorem is minimized or backgrounded, preventing background process termination by the Android OS Low Memory Killer (LMK).
- Enhanced native
- Native Rust Readability Engine — Integrated Mozilla's Readability port in Rust (
readabilitycrate) with full DOM scoring intosrc-tauri/src/article_extractor.rs, parsing and scoring article HTML in Rust in <3ms. - Store & Build Modernization —
- Declared explicit ESM module type (
"type": "module") inpackage.jsonfor full Vite 8 native configuration loader compliance. - Optimized O(1) library store lookups in
libraryStore.tsvia direct iterator access, eliminating transient array allocations during large library hydration.
- Declared explicit ESM module type (
Download & install
| Platform | Download |
|---|---|
| Windows (x64) | Theorem_1.5.7_x64-setup.exe |
| macOS (Apple Silicon) | Theorem_1.5.7_aarch64.dmg |
| macOS (Intel) | Theorem_1.5.7_x64.dmg |
| Linux (Debian/Ubuntu) | Theorem_1.5.7_amd64.deb |
| Linux (any) | Theorem_1.5.7_amd64.AppImage |
| Android (arm64, most phones) | app-arm64-release.apk |
| Android (32-bit arm) | app-arm-release.apk |
| Android (x86_64 emulator) | app-x86_64-release.apk |
| Android (x86 emulator) | app-x86-release.apk |
Linux one-liner: curl -fsSL https://raw.githubusercontent.com/Fundaments-Work/Theorem/main/scripts/install-linux.sh | bash
Desktop builds auto-update in place (Settings → About → Check for Updates). Android updates are manual unless installed via F-Droid.
Theorem v1.5.6
Fixed
- Memory & CPU Spike on Book Opening — Eliminated excessive ~1.3GB memory consumption and CPU pegging when opening books:
- In
src/features/reader/Reader.tsx, decoupledtts_engine_preloadfrom unconditional book open hooks so neural ONNX models are compiled only when Immersion Reading is actively enabled. - Added an unmount hook that triggers
tts_engine_unloadand a new nativetrim_memorycommand callinglibc::malloc_trim(0), releasing dormant glibc thread arenas back to the OS kernel. - Reaped Linux
spd-sayandkillallchild processes insrc-tauri/src/tts_linux.rsvia detached wait threads, preventing<defunct>zombie process accumulation.
- In
- P2P Device Sync PDF & Non-Materialized On-Demand File Transfers — Fixed persistent "Book File Not Available" errors when attempting to open or download PDFs and EPUBs synced from paired devices:
- SQLite Persistence Key Alignment: Fixed
find_in_dbinsrc-tauri/src/file_transfer.rsqueryingpersist:theorem-library. Theorem stores state underzustand:theorem-libraryviaSQLITE_PERSIST_KEY_PREFIX. Updated queries to checkzustand:theorem-library(and fallback variations) to accurately extract desktop-imported book file paths (filePath,storagePath). - File Path Normalization & Percent-Decoding: Added
normalize_candidate_pathinfile_transfer.rshandlingfile://scheme prefixes, percent-encoded spaces and symbols (percent_decode_str), and Windows drive formats (/C:/...->C:/...). - Direct LAN IP/Port Connection Fallback: Configured
EndpointAddrwithlast_ipandlast_portsocket addresses inconnect_and_requestto ensure reliable direct peer connections on local networks when relays are delayed or unreachable. Refreshes and persists verified socket addresses upon successful transfers. - Two-Way Pairing Address Capture: Updated
PairingProtocolHandler::acceptinsrc-tauri/src/iroh_sync.rsto extract remote IP and port fromconn.paths()and record them inPairedDevice, establishing direct LAN addressing immediately upon pairing. - Atomic Safe Downloads: Updated
download_book_fileto stream incoming bytes into a.download.tmptemporary file before atomically renaming to.book, cleaning up incomplete artifacts on network timeout or failure. - Immediate Progress & Reload Flow: Emitted an initial
0.0%event immediately upon connection infile_transfer.rsand attached the progress listener on mount inReader.tsx. ClearedloadedBookIdRef.currentupon transfer completion so the reader seamlessly mounts the newly acquired book without stalling on "Book File Not Available".
- SQLite Persistence Key Alignment: Fixed
- Mobile EPUB Navigation & Touch Gesture Handling — Restored smooth EPUB navigation and thumb gesture ergonomics:
- In
foliate-js-runtime/paginator.js, restored GPU-promoted 300ms CSS transform slide transitions for page turns and snap releases while keeping transitions cleanly disabled during finger drags and frame-by-frame JS interpolation. - Refined gesture axis arbitration (
absDx > 16 && absDx > absDy * 1.3) so natural curved thumb swipes reliably turn pages without locking into vertical scroll. - Set
touchAction: 'none'on paginated viewport containers inReaderViewport.tsx, eliminating mobile WebView gesture arbitration delays.
- In
- Download Failure UI Polish — Removed the extraneous "Go to Sync Settings" button from the reader download failure modal, establishing a clean, unified two-button action group (Back to Library and Try Again).
Improved & Performance
- Dependency Modernization —
- Removed deprecated
@types/dompurifyand@types/uuid(types are now bundled upstream). - Updated frontend dependencies to latest versions, including
vitest&@vitest/coverage-v85.0.1,@tanstack/react-virtual3.14.13,zod4.6.5,react-i18next17.0.14,lucide-react1.47.0, andjsdom30.1.0. - Updated 44 Rust crates via
cargo updateto latest compatible releases.
- Removed deprecated
- Dynamic Deferred Sentry Loading — Refactored
src/core/lib/sentry.tsandsrc/main.tsxto dynamically import@sentry/reactonly when a valid Sentry DSN is resolved at runtime. Sheds 270 KB (88 KB gzip) from the synchronous critical startup path for local, offline, and dev instances. - React Re-render Isolation & Fine-Grained Selectors —
- In
Library.tsx, extracted<DailyHighlightBanner />as an isolated memoized component, removing theannotationsarray subscription fromLibraryPage. Prevents full library re-renders (1,000+ cards) when annotations are created, updated, or synced. - In
Sidebar.tsx, replaced whole-objectstatssubscriptions with primitivecurrentStreakselectors, preventing sidebar thrashing during background reading progress flushes. - In
Reader.tsx, decoupled thefeedsarray subscription from the active book reader and isolated reader-specific settings via shallow derivation, ensuring background RSS feed refreshes and non-reader settings modifications never trigger reader viewport re-renders.
- In
- SQLite Composite Query Indexes — Added
idx_rss_articles_feed_fetched ON rss_articles(feed_id, fetched_at DESC),idx_rss_articles_fetched_at ON rss_articles(fetched_at DESC), andidx_reading_sessions_date_created ON reading_sessions(session_date DESC, created_at DESC)insrc-tauri/src/database.rs, converting in-memory sort scans into instant index lookups. - Zero-Allocation Rust Search & Clone Elimination —
- Replaced allocating string-lowercasing search in
src-tauri/src/epub_rewriter.rs(find_ci) with zero-allocation byte window scanning (windows(len).position(|w| w.eq_ignore_ascii_case(...))), saving tens of 100KB–500KB OPF string allocations per metadata write. - In
src-tauri/src/epub_parser.rs(prefetch_sync), moved ownedEpubMetafields directly, eliminating redundant heap string clones and pre-inflated chapter map duplication. - In
src-tauri/src/batch_ingest.rs, moved base64 cover strings directly intoNativeBookRecordwithout cloning.
- Replaced allocating string-lowercasing search in
- Cloudflare DTO Data Layouts — Applied
Box<str>andBox<[T]>across Rust DTOs (book_search.rs,opds_parser.rs,article_extractor.rs,mobi_parser.rs,audiobook.rs,mdict.rs,stardict.rs), shedding 8 bytes of excess allocator capacity per field.
Download & install
| Platform | Download |
|---|---|
| Windows (x64) | Theorem_1.5.6_x64-setup.exe |
| macOS (Apple Silicon) | Theorem_1.5.6_aarch64.dmg |
| macOS (Intel) | Theorem_1.5.6_x64.dmg |
| Linux (Debian/Ubuntu) | Theorem_1.5.6_amd64.deb |
| Linux (any) | Theorem_1.5.6_amd64.AppImage |
| Android (arm64, most phones) | app-arm64-release.apk |
| Android (32-bit arm) | app-arm-release.apk |
| Android (x86_64 emulator) | app-x86_64-release.apk |
| Android (x86 emulator) | app-x86-release.apk |
Linux one-liner: curl -fsSL https://raw.githubusercontent.com/Fundaments-Work/Theorem/main/scripts/install-linux.sh | bash
Desktop builds auto-update in place (Settings → About → Check for Updates). Android updates are manual unless installed via F-Droid.
Theorem v1.5.5
Fixed
- P2P Device Sync PDF On-Demand Downloads (Issue #89) — Fixed on-demand book download failures from paired devices for books imported on desktop. Enhanced
FileTransferHandler::locate_bookinsrc-tauri/src/file_transfer.rsto locate books across all local storage targets: materializedbook-cache/{id}.bookandbook-cache/{id}, SQLitebooks.dataBLOBs,book_metadatatable entries (filePath,file_path,storagePath,storage_path), and the Zustand library state stored in SQLitekv_store(persist:theorem-library). Replaced in-memory whole-file buffering with zero-RAM-spike streaming from filesystemFilehandles to QUIC send streams viatokio::io::copy. - Cross-Page Text Highlighting in PDF and EPUB Readers (Issue #90) — In
PDFAnnotationLayer.tsx, implemented sub-range clipping totextLayerNodewith boundary point comparison so selections spanning across pages isolate text belonging strictly to each respective page. Filtered client rects to the page layer's physical bounding box (layerRect), preventing inverted coordinates on previous pages. Replaced immediateselection.removeAllRanges()with a deferred cleanup (80ms) to allow multiple intersecting page layers to capture their segment of a multi-page selection. InReader.tsx, updatedresolvePickerPosition()to anchor using the last client rect fromRange.getClientRects()rather thangetBoundingClientRect(), preventing popover menu offset across CSS multi-column paginated layouts. - Mobile Immersion Reading and Text-to-Speech on Android (Issue #91) — Handled
nullvoice lists returned by Android'sTextToSpeech.getVoices()inTtsAudioPlugin.kt(doSpeak,getVoices,synthesizeToFile) withcurrentTts.voices?.let { ... }, eliminating unhandled KotlinNullPointerExceptioncrashes whendefaultTtsSettings.voiceis set. Enabled TTS by default insettingsStore.ts(defaultTtsSettings.enabled: true) and ensuredonToggleImmersionis always available for non-PDF books inReader.tsx, automatically enabling TTS when toggled. Allowed mobile users to access the voice and speed settings popup inReaderNavbar.tsxon Android ((neuralReady || isAndroid())) to adjust narration speed (0.75×–1.5×). - Sync Gossip and Reading Progress Propagation (Issue #92) — Fixed a premature bailout in
provisionToIrohDocs()(src/core/lib/sync-orchestrator.ts) whereneedsProvisionevaluated tofalseafter the first application launch, causing subsequent reading progress mutations and last read timestamps to skipdocsSetEntry(). Removed the premature bailout so that per-key diffing against_provisionedValuesruns on every sync round, correctly pushing modifiedprogress,currentLocation, andlastReadAttimestamps toiroh-docsand triggeringiroh-gossippropagation across connected peers. UpdateddefaultDeviceSyncSettingsinsettingsStore.tsto defaultautoSyncEnabled: trueandsyncOnConnect: true, migrating legacy configurations to schema version 12.
Download & install
| Platform | Download |
|---|---|
| Windows (x64) | Theorem_1.5.5_x64-setup.exe |
| macOS (Apple Silicon) | Theorem_1.5.5_aarch64.dmg |
| macOS (Intel) | Theorem_1.5.5_x64.dmg |
| Linux (Debian/Ubuntu) | Theorem_1.5.5_amd64.deb |
| Linux (any) | Theorem_1.5.5_amd64.AppImage |
| Android (arm64, most phones) | app-arm64-release.apk |
| Android (32-bit arm) | app-arm-release.apk |
| Android (x86_64 emulator) | app-x86_64-release.apk |
| Android (x86 emulator) | app-x86-release.apk |
Linux one-liner: curl -fsSL https://raw.githubusercontent.com/Fundaments-Work/Theorem/main/scripts/install-linux.sh | bash
Desktop builds auto-update in place (Settings → About → Check for Updates). Android updates are manual unless installed via F-Droid.
Theorem v1.5.4
Added
- Pitch-Preserving Audio Time-Stretching (WSOLA) — Integrated high-fidelity Waveform Similarity Overlap-Add (WSOLA) time-domain algorithm into native Rust playback (
src-tauri/src/audio_player.rs) with normalized cross-correlation phase alignment and Hann window crossfading. Enables smooth narration playback speed control (0.5×–3.0×) without pitch shifting or robotic frequency distortion across both mono and stereo channels. - Native Audio Volume & Speed Controls — Exposed Tauri commands
tts_audio_set_speed,tts_audio_get_speed,tts_audio_set_volume, andtts_audio_get_volumecontrolling the native Rodio sink and WSOLA buffer stretching directly in Rust, wired dynamically throughImmersionPlayer.ts. - Native PDF In-Book Search Engine — Implemented a streaming, zero-allocation PDF content search engine in native Rust (
src-tauri/src/book_search.rs). Parses indirect PDF object streams, decompresses Flate/Deflate content streams, parses PDF text operators (Tj,TJ,',", hex strings, and glyph kerning offsets), and runs Rayon parallel page searches with UTF-8 byte-slice context snippet extraction. - Instant Native PDF Search Fast-Path — Integrated the native PDF search engine directly into the reader viewport (
src/features/reader/engines/pdfjs-engine.tsx). In Tauri desktop/mobile environments, queries execute in parallel in Rust (~15ms) and stream directly into the search panel with instantpdf:page:Njump coordinates, falling back cleanly to the JS worker in pure web browsers. - Native Readability Article Extractor — Added
extract_article_from_html_nativeinsrc-tauri/src/article_extractor.rs, executing fast HTML cleaning, article candidate scoring, and metadata extraction viaquick-xmldirectly in Rust. - Dynamic Frontend Readability Code-Splitting — Code-split
@mozilla/readabilityanddompurifyinArticleExtractorService.ts, dynamically loading them only when parsing web articles in browser environments. This sheds over 120KB of minified parser code from the initial frontend chunk. - Direct In-Rust SQLite P2P Sync Merging — Added
sqlite_merge_sync_entriesinsrc-tauri/src/database.rs, merging incoming Iroh-gossip documents directly inside an atomic SQLite transaction. Directly updatesbook_metadata,book_annotations,books_fts, andkv_storewhile cascadingdeletion_tombstones, eliminating double-hop IPC serialization and preventing Last-Write-Wins collisions. - Relational SQLite Vocabulary Storage Subsystem — Added a dedicated normalized
vocabularytable insrc-tauri/src/database.rswith indexed lookup by(normalized_term, language)andcreated_at. Automatic idempotent zero-data-loss database migration (run_v154_database_migrations) unpacks existing terms fromzustand:theorem-vocabularyinto the relational store inside an atomic transaction while preserving the originalkv_storeblob as an immutable backup. - Native EPUB Table of Contents (TOC) Pre-Parsing — Implemented zero-copy streaming pre-parsing for both EPUB 3 Navigation documents (
<nav epub:type="toc">/<nav role="doc-toc">) and EPUB 2 NCX files (<navMap><navPoint>...) insrc-tauri/src/epub_parser.rsusingquick-xml. Parses nested chapter hierarchies, resolves intra-book relative hrefs with URL fragments, unescapes entities, and packages the result into compactBox<str>/Option<Box<[TocItemDto]>>Cloudflare data layouts insideprefetch_zip_metadata. - Instant Foliate Reader Table of Contents Display — Wired the pre-parsed TOC directly into the EPUB bridge (
src/core/lib/tauri-epub-bridge.ts) and reader runtime (src/features/reader/foliate-js-runtime/view.jsandepub.js), allowing the webview reader to immediately populate chapters and landmarks without blocking on DOMParser XML parsing on the main thread. - Direct Library Annotation Navigation — Added interactive "Open in book" navigation directly from cards and context menus in
src/features/library/Annotations.tsx, instantly opening the book and jumping to the precise highlight or note location. - SQLite Vocabulary Persistence & Sync Integration — Connected
saveVocabularyTerm,deleteVocabularyTerm, andonRehydrateStorageinvocabularyStore.tsandsync-orchestrator.tsto SQLite relational CRUD operations (sqlite_get_vocabulary_terms,sqlite_save_vocabulary_term,sqlite_delete_vocabulary_term). Automatically reconciles relational SQLite terms on app startup and synchronizes mutations.
Fixed
- Reader Page Turn Component Thrashing — Eliminated full 2,800-line React component tree re-renders on every page turn in
src/features/reader/Reader.tsx. Decoupled thestatssubscription from the active component tree and deferred visible word count extraction torequestIdleCallbackafter a 1,000ms reading dwell timeout, ensuring buttery 60fps page turns. - Instant Intra-Section Navigation & Deadlocks — Removed artificial
await wait(100)delay during intra-section page turns insrc/features/reader/foliate-js-runtime/paginator.js. Ensured the#lockedflag is released in afinallyblock so failed or aborted section loads can never wedge the page turning pipeline. - Bounded Section Navigation & Spine Error Suppression — Added
#canGoToIndex()boundary checks prior to#goTocalls inpaginator.js, preventing spuriousFailed to load sectionwarnings and blank screen states when swiping past the boundaries of the book. - Event Listener Leak in Reader Iframe — Guarded iframe selection listener attachments with
(doc).__theorem_selection_attachedidempotency flag insrc/features/reader/engines/foliate-engine.ts, eliminating runaway event listener accumulation and duplicated tap triggers across chapter transitions. - Controls Tap-to-Toggle Latency — Removed the artificial 120ms tap-suppression delay in
foliate-engine.tsand accelerated chrome toggle transitions from 300ms to 150msease-out, restoring instant responsive chrome toggling. - Mobile Swipe Sensitivity & Axis Disambiguation — Calibrated mobile touch swipe thresholds in
paginator.js(20% width displacement, 0.2 px/ms velocity) and removed the 180ms hold timer lock, allowing diagonal and hesitant thumb swipes to complete naturally without false-positive selection locks. - PDF Continuous Scroll Blanks & Height Collapse — Expanded
PAGE_PROXY_KEEP_WINDOWto 50 insrc/features/reader/engines/pdfjs-engine.tsx(retaining up to 80 loaded page proxies), keeping page placeholders sized accurately and preventing DOM collapse, scroll jumping, and blank renders during rapid scrolling. - Cross-Device Goal & Reminder Duplication — Synchronized
lastGoalNotifiedDateandlastDailyReminderDateinsrc/core/store/settingsStore.tsandsrc/core/lib/sync-import.ts. Flushes reading stats silently on book close and suppresses foreground OS notifications when the application window is focused. - Paginator Uncollapse Non-Object Anchor Error — Fixed an unhandled promise rejection in
paginator.jswhere('collapsed' in range)was evaluated on numeric anchors (1,0, fractions) during settings re-renders and column layout updates. - Highlight Recovery via Text Walker — Added
findRangeByTextfallback insrc/features/reader/foliate-js-runtime/view.jsto reliably render highlights even when DOM restructuring invalidates serialized CFI character offsets.
Improved & Performance
-
Complete Elimination of
fuse.js— Removed thefuse.jsruntime dependency frompackage.jsonand replaced it insrc/core/lib/search/fuzzy.tswith a lightweight, zero-dependency fuzzy matching engine. Provides exact prefix, word-boundary, substring, and subsequence compactness scoring while reducing bundle overhead to 2KB. -
High-Velocity PDF Edge Prefetching — Increased PDF continuous scroll edge prefetch lookahead to
$2.0 \times \text{viewport}$ and expanded concurrent batch loading to 8 pages for seamless continuous scrolling. -
Testing Integrity & Boundary Hardening — Expanded
tests/reading-time-adaptive.test.tsandtests/paginator-navigation.test.tswith rigorous edge-case and outlier suites (0 words, negative words, 100,000 words, exact 5.0s/180.0s dwell boundaries, corrupt fractions, lock safety, and gesture classification). All 348 Vitest tests and Rust unit tests pass cleanly.
Download & install
| Platform | Download |
|---|---|
| Windows (x64) | Theorem_1.5.4_x64-setup.exe |
| macOS (Apple Silicon) | Theorem_1.5.4_aarch64.dmg |
| macOS (Intel) | Theorem_1.5.4_x64.dmg |
| Linux (Debian/Ubuntu) | Theorem_1.5.4_amd64.deb |
| Linux (any) | Theorem_1.5.4_amd64.AppImage |
| Android (arm64, most phones) | app-arm64-release.apk |
| Android (32-bit arm) | app-arm-release.apk |
| Android (x86_64 emulator) | app-x86_64-release.apk |
| Android (x86 emulator) | app-x86-release.apk |
Linux one-liner: curl -fsSL https://raw.githubusercontent.com/Fundaments-Work/Theorem/main/scripts/install-linux.sh | bash
Desktop builds auto-update in place (Settings → Abou...
Theorem v1.5.3
Added
- Hybrid Two-Tier Search Engine (
SQLite FTS5+nucleo-matcher) — Completely replaced JavaScriptfuse.jsin desktop and mobile environments with a native Rust two-tier search architecture (src-tauri/src/fuzzy_search.rs). Tier 1 leverages SQLitebooks_ftsFTS5 index to prune large libraries on disk down to candidate sets in ~1ms without heap allocation. Tier 2 uses SIMD-accelerated Smith-Waterman matching (nucleo-matcher, powering Helix editor) to rank candidates, recover typos, and compute exact matching UTF-32 character indices in ~0.1ms. - UI Match Character Highlighting (
<HighlightMatch />) — Reusable, high-performance UI letter highlighting component (src/ui/HighlightMatch.tsx) that visually accentuates matched character segments in book titles, authors, annotations, and bookmarks across grid, compact, and list views as the user types. Grouping contiguous matched characters minimizes React DOM nodes for zero-lag 60fps typing. - Native Standards-Compliant Article EPUB Packaging — Offloaded EPUB packaging directly to Rust using the
zipcrate (src-tauri/src/article_epub.rs), eliminating JavaScriptfflate(zipSync) on the main thread and preventing UI thread stutters when opening web articles and RSS entries. - Morphological Lemmatizer & Irregular Inflection Stemmer — Native Rust stemmer (
src-tauri/src/stemmer.rs) integrated into MDict (mdict.rs) and StarDict (stardict.rs) dictionary engines. Provides automatic inflection, irregular verb, and plural normalization for near-100% dictionary hit rates without network fallbacks. - Zero-Data-Loss Relational Migration Subsystem — Added dedicated SQLite relational tables for
rss_feeds,rss_articles,rss_article_content(separating heavy article bodies from metadata), andreading_sessions(time-series analytics) insrc-tauri/src/database.rs. Automatically and idempotently migrates legacy JSON blobs fromkv_storeinto normalized tables inside an atomic transaction while preserving the originalkv_storevalues as immutable backups. - Decoupled Relational RSS & KV Store Footprint Reduction — Decoupled full HTML content from Zustand persistence, shrinking
zustand:theorem-rssfrom 25MB+ down to <50KB and eliminating 150ms V8 GC stalls on feed mutations. - Full Relational Storage & Session Telemetry API — Exposed native Tauri commands and typed TypeScript wrappers for RSS feed/article/content CRUD and reading session recording. Reading time hook flushes active session telemetry directly to relational tables while feeding daily goal reminders.
- Atomic P2P Annotation Sync — Hardened Iroh Docs P2P synchronization with atomic item-level keys (
anno:<bookId>:<annotationId>) to prevent overwrite collisions and ensure rapid delta replication across paired devices. - Windowed Library Query API — Added
sqlite_query_books_windowTauri command with native limit/offset cursor queries to support large library virtualization.
Improved & Performance
- Off-Thread Cover Downsampling Across All Ingestion Paths — Fully wired native Rayon cover downsampling (
downsample_cover) intocover-extractor.tsandstorage.ts, eliminating DOM<canvas>image resizing on desktop and mobile Tauri runtimes. - Eliminated JS
Fuse.jsOverhead — Removed runtimeFuseobject instantiation and heap-allocated searchable item caches infiltering.ts, dropping library filtering memory pressure and query latency to near-zero. - Robust Cross-Platform Search Fallbacks — Seamlessly falls back to token matching in pure browser and mock environments while running native two-tier search in desktop and mobile Tauri runtimes.
Download & install
| Platform | Download |
|---|---|
| Windows (x64) | Theorem_1.5.3_x64-setup.exe |
| macOS (Apple Silicon) | Theorem_1.5.3_aarch64.dmg |
| macOS (Intel) | Theorem_1.5.3_x64.dmg |
| Linux (Debian/Ubuntu) | Theorem_1.5.3_amd64.deb |
| Linux (any) | Theorem_1.5.3_amd64.AppImage |
| Android (arm64, most phones) | app-arm64-release.apk |
| Android (32-bit arm) | app-arm-release.apk |
| Android (x86_64 emulator) | app-x86_64-release.apk |
| Android (x86 emulator) | app-x86-release.apk |
Linux one-liner: curl -fsSL https://raw.githubusercontent.com/Fundaments-Work/Theorem/main/scripts/install-linux.sh | bash
Desktop builds auto-update in place (Settings → About → Check for Updates). Android updates are manual unless installed via F-Droid.
Theorem v1.5.2
Added
- Native Speech Text Normalizer — High-performance deterministic rule-based expansion of numbers, dates, 4-digit years, Roman numerals, currencies, percentages, fractions, units, and abbreviations in native Rust (
src-tauri/src/text_normalizer.rs). Shared across Supertonic neural TTS runtime, desktop platform narration, and offline companion audiobook generation. - Single-Shot Rayon Obsidian Vault Exporter — Rayon multi-threaded native batch export for Obsidian book highlight notes and Lemma SRS flashcard decks (
src-tauri/src/vault_export.rs). Replaces sequential IPC file-write loops with a single concurrent native filesystem export (<5ms). - Native quick-xml Streaming RSS Parser — Zero-copy SAX feed parsing over byte slices (
src-tauri/src/rss_parser.rs), cutting feed ingestion from 150ms–400ms down to 2ms–5ms. Adopts Cloudflare data layouts (Box<str>andBox<[T]>) to eliminate heap capacity slack. - Off-Thread Cover Processing & Dominant Color Extraction — Offloads cover downsampling and WebP encoding to a background thread pool via the native
imagecrate (src-tauri/src/image_ops.rs), accompanied by fast 32x32 histogram dominant color palette quantization (<0.2ms) without main-thread DOM<canvas>overhead. - EPUB CFI Range Parsing & Spatial Ordering — Added native Rust parsing and spatial ordering for EPUB CFI ranges (
src-tauri/src/epubcfi.rs), enabling exact start-anchor resolution across reflowable chapters.
Improved & Performance
- Zero-Allocation In-Book Search Snippets — Refactored snippet context slicing (
src-tauri/src/book_search.rs) to usetext.char_indices()byte slicing, eliminating transientVec<char>heap allocations for 10× faster search throughput. - Cross-Column & Cross-Page Highlight Engine — Precision refactoring of Foliate's Overlayer (
foliate-js-runtime/overlayer.js) to render individual line fragments viaRange.getClientRects(), strictly filtering zero-dimension rects across column gutters and multi-column pagination spreads. - Foliate Paginator Anchor Stabilization — Locked non-collapsed range anchors to
startContainerinpaginator.js, completely eliminating page-flipping oscillations when highlights span column or viewport page boundaries. - Mobile Touch Disambiguation Barrier — Introduced a 120ms tap-suppression barrier in
foliate-engine.ts, establishing a strict gesture hierarchy that eliminates false-positive page turns during mobile selection and drag gestures.
Download & install
| Platform | Download |
|---|---|
| Windows (x64) | Theorem_1.5.2_x64-setup.exe |
| macOS (Apple Silicon) | Theorem_1.5.2_aarch64.dmg |
| macOS (Intel) | Theorem_1.5.2_x64.dmg |
| Linux (Debian/Ubuntu) | Theorem_1.5.2_amd64.deb |
| Linux (any) | Theorem_1.5.2_amd64.AppImage |
| Android (arm64, most phones) | app-arm64-release.apk |
| Android (32-bit arm) | app-arm-release.apk |
| Android (x86_64 emulator) | app-x86_64-release.apk |
| Android (x86 emulator) | app-x86-release.apk |
Linux one-liner: curl -fsSL https://raw.githubusercontent.com/Fundaments-Work/Theorem/main/scripts/install-linux.sh | bash
Desktop builds auto-update in place (Settings → About → Check for Updates). Android updates are manual unless installed via F-Droid.