mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-03 16:41:26 +01:00
Every Android run since August failed in :app:buildRustHost: the host build of pstr-android reaches libdbus-sys through keyring's Secret Service store, and the runner had no libdbus-1-dev. With no successful run, nothing was ever cached, so each run rebuilt from nothing. - libdbus-1-dev in both jobs - one shared, save-on-failure Rust cache for both jobs - the staged libmpv tree cached on the build script's hash; the script stamps its output with the revision and its own hash and skips the libmpv build when the stamp matches PLAN.md records the Android parity and UI work that follows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
151 lines
7.4 KiB
Markdown
151 lines
7.4 KiB
Markdown
# 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.
|
||
|
||
## 0. CI (done, unverified)
|
||
|
||
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-dev` added to both jobs' apt install.
|
||
- `Swatinem/rust-cache` shares one key between the two jobs and saves on failure.
|
||
- `android/app/build/generated/mpv` is cached on the hash of
|
||
`scripts/build-libmpv-android.sh`; the script writes a `STAMP` (revision plus
|
||
its own hash) last and skips the whole libmpv build when the stamp matches.
|
||
|
||
Verify with `gh workflow run android.yml -f signed_release=true`, then run it a
|
||
second time and check that the libmpv step finishes in seconds.
|
||
|
||
## 1. Desktop parity
|
||
|
||
Ordered by value on a phone.
|
||
|
||
1. **Open share links from outside the app.** The manifest has only the
|
||
launcher intent. Add an `ACTION_VIEW` filter for `drive.proton.me/urls/*` and
|
||
an `ACTION_SEND` (`text/plain`) filter; both open the add-share dialog with
|
||
the link filled in. Desktop: `4a54af3`, `53a1d0a`.
|
||
2. **Streaming cache budget.** Android runs on the fixed 4 GiB default
|
||
(`DiskCacheConfig::DEFAULT_BUDGET_BYTES`), large for a phone. Expose
|
||
`DiskCache::set_budget` through `pstr-android`, add a 1–16 GiB choice with a
|
||
usage readout under Storage. Desktop: `a432a93`.
|
||
3. **Hardware-decoding switch.** `pstr_mpv.cpp` hard-codes
|
||
`hwdec=auto-copy-safe`; a device with green frames has no way out. A
|
||
Settings toggle, applied from the next file.
|
||
4. **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`.
|
||
5. **Long-press menu on tiles.** Play/resume, mark watched or unwatched,
|
||
download, change match, remove from Continue watching, in a
|
||
`ModalBottomSheet`. Desktop: `c5808a5`.
|
||
6. **Undo on snackbars** for marking a title and leaving Continue watching.
|
||
`AppUiState.message` is a bare string today; it needs an action. Desktop:
|
||
`79c3f68`.
|
||
7. **History tab.** Needs a bridge call over the `pstr-core::library` query
|
||
the desktop page uses. Desktop: `e7eeaa5`.
|
||
8. **Buffered range on the seek bar** from mpv's `demuxer-cache-time`.
|
||
9. **Up-next card** with the next episode's still and a countdown ring instead
|
||
of "Up next in 7s" text.
|
||
10. **Featured banner** at the top of the library. Desktop: `7d03736`.
|
||
11. **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 red `S01E01` label
|
||
above each row goes.
|
||
|
||
### Shares
|
||
|
||
- `ListItem` rows: 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 `ListItem` rows (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.md` has no visual layer today.
|
||
- 48 dp minimum touch targets and content descriptions on the new icon-only
|
||
actions.
|
||
- Tablet: `ListDetailPaneScaffold` for library + title, since
|
||
`NavigationSuiteScaffold` already switches to a rail there.
|
||
- Shared-element transition from a poster to its title page, and predictive
|
||
back.
|
||
|
||
## Suggested order
|
||
|
||
1. CI green (section 0).
|
||
2. Split `ProtonStreamApp.kt`; add screenshot tests for the current screens.
|
||
3. Parity 1–3 (small, phone-specific fixes).
|
||
4. Button hierarchy and Inter — every later screen inherits them.
|
||
5. Title page, then Library, then Shares and Settings.
|
||
6. Parity 4–10.
|