Skip to content

v1.1.2

Latest

Choose a tag to compare

@github-actions github-actions released this 21 Sep 09:21
· 2 commits to main since this release
Immutable release. Only release title and notes can be modified.

A hardening release: no new features, one deep pass over the failure modes a stable app still has. A four-way audit of the codebase (async safety, malformed data, arithmetic edge cases, races) turned up the fixes below; none of them were crashes anyone had reported, because most of them fail silently — which is exactly why they got a release to themselves.

Changed

  • Every tab now has an honest answer when your server is out of reach. 1.1.1 taught Home to open offline — but one tab over, Browse still spun through a timeout and landed on an error view, and Authors and Collections did the same: screens that looked broken on a plane while Home, beside them, worked. Now Browse shows what's actually playable — your downloaded books, read from the same records as Home's shelves — and nothing more: a book merely in progress streams from the server, and a cover that can't play has no place on an offline shelf. Collections shows your real collections, because they're made in the app and live on the phone; they never needed the server to exist, only to show their books. Every book the phone has records for — downloaded, or simply opened before — appears in its place, and a line counts the ones that genuinely need the server rather than letting an eight-book collection quietly read as three. Authors is the one tab whose content really does live on the server, and it now says so plainly instead of spinning. All of it carries Home's quiet "server isn't reachable" line, and all of it recovers by itself the moment the connection returns. This works whether or not you've ever picked a library in Settings: a picked library used to count as "the server answered" all by itself, which handed the multi-library case — the people who used the picker — the old error screens. None of it guesses at your connection: Android's word on whether the network is real is famously unreliable (an idle VPN or a captive portal both look "online"), so the tabs answer from what actually happened when the server was last asked.
  • The next book in a series now keeps your speed. A book you've never opened has no speed of its own, so rolling into it — by auto-play or the finished panel's next-book button — started it at the default: a series listened to at 1.25× dropped back to 1× on every handoff. The next book now inherits the speed of the book it followed, once, the first time it starts that way. Setting its own speed still wins permanently, books that simply ride the global default keep following that setting, and nothing changes for books opened from anywhere else — the carry-over only happens inside a collection, where the next book usually shares the narrator.

Fixed

  • The auto-play countdown now actually starts when you're watching it. Before arming its five-second countdown, auto-play next book checks that you haven't already pressed play to hear the finished book again. That check read the player's play intent — which stays raised through the moment a book completes and only drops when the stop that follows lands, a race the check reliably lost whenever the next-book lookup answered from warm caches instead of the network. Warm caches and a watched screen arrive together, so the countdown died silently in exactly the case where you were staring at the finished page waiting for it: next book named, nothing happening. The check is gone; everything it guarded against (dismissing the panel, starting another book, replaying the finished one) was already covered by the checks beside it.
  • The lock screen and bluetooth controls can no longer go dead while a book plays. Android is free to shut Saga's playback service down and rebuild it mid-listen; 1.1.0 taught the rebuilt one what's playing again (the "Saga is running" lock screen), but nothing re-told it that it's playing — and that half turns out to matter more. Android answers a button press by asking the session whether it's playing: a rebuilt session that believes it's paused turns every headset press and every lock-screen button into "play", which does nothing to a book already playing. So the controls looked dead everywhere at once, and only the buttons inside the app worked. The player now re-sends the session's whole state — what's playing and whether it's playing — on every play and pause and every ten seconds while a book runs, so a rebuilt session corrects itself within seconds instead of waiting for the app to be reopened. Streaming was never affected, which is why this hid for so long: a streaming book keeps the session's state fresh as a side effect of buffering, a downloaded one can go a whole chapter without a word.
  • Casting now hands your listening position back however the session ends — written down as it goes, and filed under the right book. Disconnecting from the cast sheet always did; but switch the TV off, lose Wi-Fi, or let someone else cast over you after the sheet was closed, and the position from hours of listening on the TV was simply gone — Continue Listening offered the moment casting started. The position now comes back on every way a session can end. Three things make that stick. It's saved to the bookmark every ten seconds during the cast, not remembered until the end — so an app Android kills mid-cast, or a phone that reboots, loses at most ten seconds instead of the whole evening. It's filed under the book that was actually handed to the TV: the old writeback seeked whatever book the phone happened to hold at that moment, so casting one book and browsing into another could stamp the TV's position onto the wrong book. And the machinery listening for the session's end now exists from app launch, not from the first time the cast sheet is opened — the Cast SDK quietly resumes a live session across an app restart, and until now the session's end was invisible unless the sheet had been opened again.
  • Skipping forward near the end no longer finishes the book. Pressing +30 s with twenty seconds left used to land exactly on the end, which counts as finishing: completion recorded, the finished panel up, the next book queued — mid-sentence. Every seek (skip buttons, the scrubber, chapter taps) now stops one second short of the end; a book finishes by playing its last second, never by jumping past it. The same clamp covers a subtler case: a file replaced server-side with a shorter re-encode kept its old cached chapter list, and tapping a late chapter marked the book finished the same way.
  • Switching books mid-listen can no longer file one book's position under the other's name. There was a narrow window during every book switch where the periodic ten-second save could write the outgoing book's position onto the incoming book's bookmark — improbable per switch, inevitable eventually, and it destroyed the new book's saved place when it hit. Saves now pause for the switch, and the outgoing book gets one final save before the new one takes over (which also closes a small always-there gap: up to ten seconds of the old book's progress used to be dropped on every switch).
  • The sleep timer no longer quietly cancels itself. Any book load — the automatic advance to the next book, tapping a chapter, even the app recovering from a network blip — silently killed an armed timer, and the book played to the end overnight: the one thing the feature exists to prevent. The timer now survives all of it — including the handoff itself: when a book finishes and the next one starts, the countdown freezes with the finished book and picks back up when playback resumes, pausing the new book right on schedule. It ends only when a finish leads nowhere within half a minute, or when you stop the session. The countdown under the player's moon button also now holds still while you're paused: the timer itself always froze correctly, but the label kept falling on wall-clock — and could read "Sleep" over a timer that was armed all along — because it was computed from the end time instead of asked from the timer. Three smaller holes in the same area are closed: a pause that fails mid-fade can no longer strand the volume near-silent, an end-of-chapter timer shorter than the fade no longer starts with an audible volume drop, and a timer that runs out in the same instant playback pauses now does its job on the next play instead of evaporating with the moon still claiming it's armed.
  • Auto-play can no longer restart a book you're midway through — or wipe its place. The advance played the next collection entry from the beginning, started or not: finish book one with book two half-listened, and book two restarted from zero — and the first automatic save then overwrote its real position. The advance now resumes a started next book at its saved place (an unstarted one still starts at the beginning, and finished entries are skipped), so the unattended case can never destroy a position. And because an old position isn't always wanted — a book sampled long ago, or opened once from a search — the finished panel now shows the choice when there is one: Resume from 1:02:13 or Start over, the same two-button shape a sync conflict will need when cross-device sync lands. The countdown takes the resume; both buttons also settle the countdown, so a tap can no longer race it into starting the same book twice. A series listened to anew flows the same way it did the first time: a completed next book is offered again — the panel says Read again and the advance starts it from the beginning, never from the end-of-book position its earlier finish left behind (which would replay the final second, count another completion, and chain straight through every finished book after it). The speed carry-over from earlier in this release also now stamps the next book only when it actually starts; a failed advance used to mark a never-opened book as having a speed of its own, quietly unhooking it from the default forever.
  • Pressing play on a finished book now replays it — instead of "finishing" it again. The finished panel's play control promised a replay and delivered the last second: it resumed at the saved end-of-book position, played that second, and counted a whole new completion — every press adding one to "times listened". Play on a just-finished book now starts it from the beginning, which is what the button always claimed to do.
  • Opening the player just to look no longer moves your place. Tapping Home's hero card opens the player without starting audio — but that view-only open applied the smart resume rewind anyway, and backgrounding the app saved it: up to a minute walked backward per look, without a second played. The rewind now happens when you actually press play, using the same curve, measured from when you last listened.
  • Changing the default speed leaves a book with its own speed alone. Adjusting Settings → Default speed mid-listen audibly dropped the current book to the new default even when that book had its own saved speed — which survived in storage, so the next open snapped back, and the session and the setting disagreed until then. The default now applies live only to books riding the default.
  • Restoring a backup is now all-or-nothing. A malformed backup file — hand-edited, truncated, or from a corrupted export — used to be discovered midway through the restore: positions and completions already overwritten, history half-merged, and then "Import failed" on screen with no way back. The whole file is now checked before a single value is written, so a bad backup fails cleanly and touches nothing. Positions inside a backup are also sanity-checked — a negative one used to make that book silently refuse to play at all.
  • A corrupt audiobook file can no longer take the whole app down. The chapter reader trusts the file to say how big each chapter title is; a half-written download or damaged file can claim gigabytes, and the reader would obligingly try to load that in one piece — Android kills the app on the spot. Claimed sizes are now capped (a real chapter title is tens of bytes), and a file that lies about them keeps its correctly-timed chapters under fallback names instead of crashing anything. Streaming chapter reads also now refuse a server that answers a small request with the whole file.
  • One odd library entry no longer empties a whole screen. A single malformed record from Plex — a section, author, book, tag or server connection missing a field the app assumed — used to fail the entire list it appeared in: one weird entry, no libraries at all. Every list now drops the entry it can't read, notes it in the diagnostics log, and shows the rest. Sign-in got the same treatment: a captive portal answering for plex.tv used to end the sign-in poll with a raw error.
  • Choosing a server can no longer freeze the app behind its spinner. The switching dialog can't be dismissed by design; if anything failed behind it — a storage write, the network — it was never taken down either, and the only way out was force-quitting. A failure now closes the spinner, says what happened, and leaves the list usable.
  • Downloads interrupted by a process death are cleaned up. A download killed partway through (low memory, force stop) left a half-file on disk with no record of it anywhere — invisible to the storage manager, uncounted in "Downloaded books", unremovable except by clearing all app data, hundreds of megabytes at a time. Downloads now write to a temporary name and only take their real name when complete, and leftovers are swept at startup. Double-tapping a download button could also start the same download twice into the same file; the second tap is now ignored.
  • Resuming a stopped book now rewinds the same way, however the app got there. Saga's smart rewind — the little step back that restores context after time away — applied when resuming a pause and when the app came back from being fully closed, but not in the case between: a book stopped (finished, or stopped from a Bluetooth device) while the app stayed in memory. Resuming hours later picked up exactly where it stopped, mid-word, at whatever speed the previous book used. That path now runs through the same resume logic as every other, so the rewind and the book's own speed always apply. (A 2026-08-08 backlog entry, held back then because it touched the play path late in a release cycle — this release is a play-path release, so it rode along.)
  • Assorted smaller guards, all from the same audit. Double-tapping a book can no longer stack two player screens; marking a book completed (or want-to-read) and immediately pressing back no longer silently drops the update; the same for collection dialogs interrupted by a connection change; and three layout calculations that crashed in very narrow windows (freeform / split screen) now clamp instead.