8.1 KiB
Android plan
Where the Android client stands against the desktop app, and what to change to make it feel like a modern streaming app rather than a settings form with a player attached. Written 2026-10-03 from a source review and four screenshots (Library, Title, Shares, Settings) taken on a phone running v0.5.0.
Android last caught up with the desktop on 2026-08-10 (4ef6225); the desktop
gained about twenty features on 2026-10-02 that Android does not have.
Status (2026-10-03)
Done: section 0, every parity item, the Library, Title, Shares and Settings redesigns, Inter, and screenshot tests. Not yet verified on a device; the host gate (ktlint, lint, unit and screenshot tests) and CI's build job pass.
Open, from section 2: per-screen app bars and edge-to-edge under the status
bar, skeleton loading and generated placeholder art, a search icon that
expands, a language picker, Settings sub-pages, the Downloads page, light
theme and tablet screenshots, ListDetailPaneScaffold on tablets, shared
element transitions and predictive back, and a long-press Change match (the
title page has it).
0. CI (done)
Every Android workflow run since August failed in :app:buildRustHost:
pstr-core pulls keyring → dbus-secret-service → libdbus-sys, which needs
libdbus-1-dev on the host. Because no run ever succeeded, no cache was ever
saved, so each run started from nothing.
libdbus-1-devadded to both jobs' apt install.Swatinem/rust-cacheshares one key between the two jobs and saves on failure.android/app/build/generated/mpvis cached on the hash ofscripts/build-libmpv-android.sh; the script writes aSTAMP(revision plus its own hash) last and skips the whole libmpv build when the stamp matches.
Later runs also needed meson 1.12.1 from PyPI (noble's 1.3.2 is too old for
the pinned fontconfig), libmpv built and cached in its own steps so a later
failure keeps it, and lint's OldTargetApi made informational. A cached run
restores libmpv in under a minute.
1. Desktop parity
Ordered by value on a phone.
- Open share links from outside the app. The manifest has only the
launcher intent. Add an
ACTION_VIEWfilter fordrive.proton.me/urls/*and anACTION_SEND(text/plain) filter; both open the add-share dialog with the link filled in. Desktop:4a54af3,53a1d0a. - Streaming cache budget. Android runs on the fixed 4 GiB default
(
DiskCacheConfig::DEFAULT_BUDGET_BYTES), large for a phone. ExposeDiskCache::set_budgetthroughpstr-android, add a 1–16 GiB choice with a usage readout under Storage. Desktop:a432a93. - Hardware-decoding switch.
pstr_mpv.cpphard-codeshwdec=auto-copy-safe; a device with green frames has no way out. A Settings toggle, applied from the next file. - Episode list in the player. A bottom sheet (portrait) or side panel
(landscape) with the title's episodes, opened on the playing season and
scrolled to the playing episode. Desktop:
7e734db. - Long-press menu on tiles. Play/resume, mark watched or unwatched,
download, change match, remove from Continue watching, in a
ModalBottomSheet. Desktop:c5808a5. - Undo on snackbars for marking a title and leaving Continue watching.
AppUiState.messageis a bare string today; it needs an action. Desktop:79c3f68. - History tab. Needs a bridge call over the
pstr-core::libraryquery the desktop page uses. Desktop:e7eeaa5. - Buffered range on the seek bar from mpv's
demuxer-cache-time. - Up-next card with the next episode's still and a countdown ring instead of "Up next in 7s" text.
- Featured banner at the top of the library. Desktop:
7d03736. - Bundled Inter in
ui/theme/Type.kt, so both clients read the same. Desktop:558446b.
2. UI recommendations
Everywhere
- Colours stay the theme's. The red is the Persona theme's accent and the card tint comes from the shared palette, so the redesign changes layout and button hierarchy, not colours.
- One button hierarchy. At most one filled accent button per screen; secondary actions tonal or outlined; destructive actions behind a menu and a confirmation, never a filled red button in a list row.
- Edge-to-edge, per-screen titles. The "proton-stream" app bar on every page wastes a band of height. Library uses a collapsing large title; Title pages draw the backdrop under the status bar; other tabs use their name.
- Skeletons instead of spinners for library and title loading, and generated placeholder art (gradient from the accent plus the title's initials) instead of a black card with a play triangle (Akira).
- Pull-to-refresh (
PullToRefreshBox) replaces the top-bar refresh icon, with crawl progress shown in the indicator area. - Split
ui/ProtonStreamApp.kt(1665 lines) into one file per screen before the work below; every item touches it.
Library
- Poster grid (2:3,
posterUrl) at three columns on a phone, title under the poster with no card body. The current 210 dp cropped backdrops fit two titles per screen. - Continue watching: 16:9 still with the progress bar laid over the bottom edge of the image and "S03E11 · 12 min left" under it.
- Search becomes an icon in the app bar that expands into an M3
SearchBar, instead of a permanent field above everything. - Fix "1 episodes" (line ~507; the season header already pluralises).
Title page
- Full-bleed backdrop with a gradient scrim, poster, title and meta chips (year, score, genres) over it, collapsing as the page scrolls.
- Synopsis clamped to three lines with "More".
- One full-width primary button, "Resume S03E11" or "Play S01E01", then a row of icon actions: download, mark watched, and a ⋮ menu holding Start over, Change match and More on AniList. Today five buttons of three styles wrap over three lines.
- Drop the "Preferred tracks" form and its Save button from this page. The
player already remembers tracks by name per title (
d3c5f07); expose any override from the player's track chooser. - Season picker as a dropdown chip or tabs, not stacked accordions; a 40 episode title is one long scroll today.
- Episode rows: 16:9 still with progress overlay, "1 · Mother and Children"
(provider name, else "Episode 1") rather than the raw file name
[Judas] Oshi no Ko - S01E01.mkv, runtime or air date as supporting text, watched and download state as small trailing icons. The redS01E01label above each row goes.
Shares
ListItemrows: name, "12 titles · crawled 2 h ago" or the failure, and a ⋮ menu with Refresh, Re-enter link and Remove (confirmed). The current row wraps "Custom password stored securely" over three lines beside three differently styled actions.- "Add share" as an extended FAB, which is also where the share-link intent from parity item 1 lands.
Settings
- Grouped
ListItemrows (headline, one line of supporting text, trailing switch), with the long explanations moved into the supporting line or an info dialog. Today each toggle carries a paragraph. - Split into sub-pages once storage and decoding settings land: Playback, Downloads & storage, Appearance, Metadata, About.
- Language fields become a picker dialog over a language list, not free text.
- Storage shows a usage bar (cache, offline episodes) above the budget choice.
Robustness
- Screenshot tests (Roborazzi, JVM, no device) for each screen in light and
dark, phone and tablet, at font scale 1.0 and 1.5 — the redesign changes
every screen, and
docs/TESTING.mdhas no visual layer today. - 48 dp minimum touch targets and content descriptions on the new icon-only actions.
- Tablet:
ListDetailPaneScaffoldfor library + title, sinceNavigationSuiteScaffoldalready switches to a rail there. - Shared-element transition from a poster to its title page, and predictive back.
Suggested order
- CI green (section 0).
- Split
ProtonStreamApp.kt; add screenshot tests for the current screens. - Parity 1–3 (small, phone-specific fixes).
- Button hierarchy and Inter — every later screen inherits them.
- Title page, then Library, then Shares and Settings.
- Parity 4–10.