diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-09-26 18:25:45 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-09-26 18:25:45 +0000 |
| commit | 06939defdbf144e630b5435bba552a730461440b (patch) | |
| tree | 311267dc2109e1db24dcfc04176fab14d0b140e0 /CLAUDE.md | |
| parent | aa9c0a386f19bb58c50c81fd79d9509d2883cffe (diff) | |
Hide played episodes, and hand off to the video at the right moment
Two of Peter's asks.
Played episodes are hidden by default. An episode you have heard is done with,
and leaving it in the list buries the ones that are not. A global toggle on the
show screen brings them back, so a mis-tapped "played" can still be found --
stored in DataStore, which has been a declared dependency since phase 1 with
nothing using it. Android Auto always hides them regardless of the toggle: a
car list is scrolled blind at a traffic light.
Hand-off carries the position both ways. Out: "Watch from here" opens the video
on its own site at the point reached. In: a link shared from YouTube with a
timestamp on it was shared at that moment deliberately, so the episode starts
there rather than at the top. WatchLink does both and is pure, because an
unrecognised URL shape fails silently -- as a link that simply starts from the
beginning -- and YouTube produces a lot of shapes.
The button sits on the episode screen as well as the player. That was not the
first design, and testing changed it: the player-only version is unavailable
exactly when it is most wanted, because an episode YouTube declines to serve
never starts playing and so never reaches the player at all.
Verified on a device, round trip: youtu.be/dQw4w9WgXcQ?t=90 shared in stored a
position of 90000, the episode screen offered Watch, and tapping it fired
youtube.com/watch?v=dQw4w9WgXcQ&t=90s. Marking an episode played removed it
from the list, the toggle brought it back, and the preference survived a
restart. An ordinary podcast offers no hand-off, having no page to open.
Two things caught on the way. A crash: the episode cache was declared after the
init block that collects from a StateFlow, which emits synchronously, so it was
still null on the first emission -- caught by the launch check, now a plain
field declared with the others. And the played switch needed a contentDescription
distinct from its visible label, or it is ambiguous to pick -- the same trap the
drip switch hit.
Preferences joins the coverage exclusions: a Context, a file and a generated
Flow, deciding nothing. WatchLink is fully covered.
No permission changes, no schema change. 442 unit tests green, detekt and lint
clean, coverage steady at 90.13.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
Diffstat (limited to 'CLAUDE.md')
| -rw-r--r-- | CLAUDE.md | 11 |
1 files changed, 11 insertions, 0 deletions
@@ -234,6 +234,17 @@ out of a possibly-partial MP3, and the JSON path covers the shows that mark chap come from. Only then: a title that was shared is the one that was meant, and the probe costs a network round trip. +- **Played episodes are hidden by default**, globally, via a DataStore preference the show + screen toggles. Android Auto always hides them regardless: a car list is scrolled blind at a + traffic light, and something already heard is pure noise there. + +- **A video episode can be handed off to its own site at the current position**, and a link + shared *in* with a timestamp starts there. `WatchLink` does both, and is pure so every URL + shape is pinned -- an unrecognised one fails silently, as a link that starts from the + beginning. The button lives on the episode screen as well as the player, deliberately: an + episode that cannot be fetched never starts playing, and that is exactly when watching it + elsewhere is the point. + - **Anything entering the queue is downloaded immediately, on any network.** The hook is `QueueRepository`'s `onQueued`, fired with newly-present ids only, because the queue is the one choke point every route goes through. The one-off job deliberately has no network |
