The up-next countdown only ran over a credits chapter, so a file with no
chapters - most that are not anime - cut straight into the next episode
with no warning and no way to stay. Such a file now shows the same card
over its last ten seconds, counted on the file's own clock so it reaches
zero at the end of file, and its second button is Cancel rather than
Watch till the end.
On the phones, an episode that ends with nothing after it - the last one,
autoplay off, or cancelled - left a black screen. It now says so, with
Play next or Watch again, and Close.
Android also:
- saves the resume position from PlaybackService rather than the player
screen. With background audio on the service outlives the activity, and
a position only the screen kept stopped being saved when it went. A swipe
from Recents saves and stops instead of playing on with nothing to
return to.
- shows "Opening <episode>..." while the stream opens, where there was a
black screen for as long as the share session and block list took.
A file mpv gave up on partway ended the desktop player without a word:
the page went back to the title and the film was simply gone. It now
leaves an error toast naming where it stopped, with Retry reopening the
episode at that position.
The phone players already showed an error, but its only button was
Dismiss, so a dropped connection meant backing out and finding the
episode again. They gain Retry, which opens a fresh stream (through the
session refresh) from where the failed one stopped. A stall that lasts
twenty seconds now says so and offers the same, rather than showing
"Buffering…" for ever.
After "next episode" during the credits, the previous file keeps
playing until the new stream is open. Its chapters and position were
read against the already-advanced index, so the up-next card offered
the episode after the next one for those seconds. The card, the skip
offer and auto-skip now only act on readings of the open episode.
Metadata was only fetched after adding a share (mobile) or from the
Settings buttons (desktop), so a show or episode that turned up in an
existing share stayed bare. Every crawl is now followed by a match run
when enrichment is on; `plan` makes no requests for a library that is
already matched. A stored episode guide is fetched again when a file
newer than it has no named entry, and daily for two weeks while an
aired episode is still unnamed.
Removing a share now carries its watch state to any other share holding
the same file, `pstr remove` drops the share's catalog rows, and the app
forgets catalog rows of shares no longer configured — an older `pstr
remove` left them, and every episode showed twice.
iOS, for a slow iPad:
- swipe back on a settings page uses its own edge strip; on the whole
page it also pressed the row under the finger and opened the metadata
sheet
- "Change match" from the tile menu opens once the menu has dismissed,
not after a guessed 350 ms that a slow device missed
- the activity banner tracks each running line by itself (also Android),
so overlapping work no longer leaves it spinning forever
- buttons, tiles and rows draw their press; marking watched shows at
once; remove/repair share, sign out and deletions show the banner;
the player says "Opening…" while the stream opens
- posters are read into a reserved buffer instead of a byte at a time
The iOS client is now a screen-for-screen port of the Android app over the
same pstr-android UniFFI surface, with no Rust changes: Library, title page,
History, Shares (public links and Drive folders), Downloads and Settings,
with the same strings, undo snackbars and two-pane layout on wide screens.
- Theme from the engine's palette (Material role names, Inter, the same
type ramp and corners), repainted live from the appearance settings.
- Account sign-in with two-factor code, mailbox password and the Proton
CAPTCHA in a non-persistent WKWebView, the Drive folder browser, and
watch-history sync every five minutes, after sign-in, on player close and
when the app leaves the screen.
- Player over libmpv: resume, progress saved every 5 s, autoplay with the
up-next card, skip and auto-skip from the chapter plan, track, speed,
volume and episode pickers, landscape lock, mini transport, and
lock-screen controls with interruption and route-change handling.
- Offline downloads with the Android record format, free-space floor,
retries, transfer rate and the Wi-Fi-only policy; interrupted transfers
resume at next launch.
- Config, data and download state are excluded from backup, as Android's
allowBackup=false: a restore would bring shares back without their
Keychain secrets and give two devices one sync identity.
Picture-in-picture, the share sheet and background downloads are not
possible the same way on iOS; docs/IOS.md lists why and what replaces them.
Adds XCTest ports of the Android unit tests, a `test` command to
scripts/build-ios.sh, the app icon and its render script, and an iOS
workflow on macos-15 that runs the tests and builds the unsigned .ipa.