summaryrefslogtreecommitdiff
path: root/CLAUDE.md
diff options
context:
space:
mode:
Diffstat (limited to 'CLAUDE.md')
-rw-r--r--CLAUDE.md28
1 files changed, 23 insertions, 5 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index 65655be..3e41672 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -240,11 +240,13 @@ out of a possibly-partial MP3, and the JSON path covers the shows that mark chap
slow drip on or off" rather than "Slow drip", because a description identical to the heading
beside it makes the tap ambiguous.
-- **`connectedDebugAndroidTest` can wipe the app's data.** A run cleared `listen.db` on the
- emulator mid-session. It is the test harness's install path, not a migration: a real v2
- database seeded with a subscription, an episode at position 424242 and a rule was upgraded in
- place by launching the v3 build, and all three survived with drip defaulting to off. Do not
- read an empty database after an instrumented run as a migration failure -- but do check.
+- **`connectedDebugAndroidTest` uninstalls the app when it finishes**, taking the database with
+ it. Isolated on the emulator: a plain `adb install -r` left four episodes in place, and the
+ very next instrumented run left `run-as: unknown package`. So an empty or missing database
+ after an instrumented run is the harness, not a migration -- and any device state you want to
+ keep has to be re-seeded afterwards. Migrations were separately proven safe by seeding a real
+ v2 database (a subscription, an episode at position 424242, a rule) and upgrading it in place
+ by launching the v3 build: all three survived, with drip defaulting to off.
- **The drip released-set is a query parameter, not stored state.** `observeVisible`/`getVisible`
take `dripEnabled` and hide unreleased episodes only when it is true, so switching drip off
@@ -252,6 +254,22 @@ out of a possibly-partial MP3, and the JSON path covers the shows that mark chap
left off. `getForSubscription` deliberately still returns everything: feed reconciliation must
see held-back episodes or it re-inserts them on every refresh.
+- **Completion belongs to the service, not to a view model.** Marking an episode played,
+ advancing the queue, the outro offset and ad-chapter skipping all live in `PlaybackService`
+ via `PlaybackAdvancer` and `PlayheadPolicy`. They used to live in `PlayerViewModel`, which is
+ scoped to the activity and releases its MediaController in `onCleared` -- so with the activity
+ gone the audio played on from the foreground service while nothing marked anything played or
+ moved the queue on. Background listening is the normal case for this app. Verified with
+ "don't keep activities" on: with no activity alive, an episode reached its outro line, was
+ marked played, and the next one started.
+
+ `PlayerConnection` deliberately no longer handles `STATE_ENDED`, and `PlayerViewModel` no
+ longer has an `onFinished`. Putting either back means the queue advances twice.
+
+- **Where an episode starts is decided in exactly one place**, `PlaybackAdvancer.start`, used by
+ both the service (queue advance) and the view model (a tap on Play). Two copies of the resume
+ rules would drift.
+
- **A start position belongs to `setMediaItem`, not a `seekTo` after `prepare()`.** Seeking
afterwards is silently dropped across the MediaController-to-service boundary. This was found
wiring up the intro offset -- an episode set to start sixty seconds in began at zero -- and it