diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 39932f9..4f7d65d 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -10,13 +10,14 @@ Status legend: โœ… done ยท ๐Ÿšง in progress ยท โฌœ not started ## Current state (one line) -โœ… **M4 done.** Clockula has a face. Four tabs under an M3 Expressive navigation -bar that becomes a wide rail on a tablet, with the back-stack policy and the -live pill's whole decision written as pure functions rather than as composable -state; the ring screen is real, with a maths or hold challenge that always has a -way out โ€” three wrong answers or sixty seconds, whichever comes first. The tabs -themselves are still empty states: **M5** (the alarms screen โ€” list, editor, -time picker, repeat days, per-alarm overrides) is next. +โœ… **M5 done.** The Alarms tab is real: a live list that says when each alarm +will ring and marks the next one, and an editor that writes as you go โ€” the +Material time picker, a repeat-day row that starts on your locale's own first +day, a ringtone picker with the device's sounds, a file of your own and a Silent +option that still vibrates, and five per-alarm overrides each of which can say +"follow the app default" rather than silently copying it. The other three tabs +are still empty states: **M6** (timers โ€” multiple concurrent, presets, the +foreground service and expiry ringing) is next. --- @@ -202,11 +203,51 @@ plumbing. denial, and the exact-alarm and full-screen-intent grant deep links, moved wholly to M10's self-check, which is the screen with room to say why. -### โฌœ M5 โ€” Alarms screen +### โœ… M5 โ€” Alarms screen List, create, edit, delete, enable/disable. Time picker, repeat-day selector, label, ringtone picker, vibrate, snooze settings, per-alarm overrides. Next-fire line ("in 9h 12m") on each row. Built on `GroupedSurface`/`GroupedRow`. + โœ… 624 JVM tests, 144 of them new, and **still no Robolectric** โ€” kept for a + whole *form*, which is where a screen usually reaches for one. Everything a + tap decides is a pure object (`AlarmListRows`, `NextFireFormat`, + `RepeatDaysSummary`, `AlarmDefaults`, `AlarmOverrides`, `RingtonePicker`, + `AudioSourcePolicy`, `AlarmRoutes`) or a ViewModel method tested over the + **real** `AlarmEngine`; three new `ArchitectureRulesTest` rules make that a + build fact rather than a habit. + + The decisions worth knowing: the next-fire line comes from + `AlarmEngine.upcoming`, which grew a `refresh: Flow` cadence parameter + so the countdown advances without a database write and the screen re-derives + none of the engine's time arithmetic; the list is ordered by **time of day**, + not by next fire, so rows never swap under a thumb at 07:00; every per-alarm + override is an `OptionPicker` whose first row is "App default (On)", because + the stored value is ternary and a `Switch` cannot say "I have not chosen"; + silence is an explicit sentinel (`clockula://silent`) that resolves to an + empty audio-source list and therefore forces vibration, so a "silent" alarm + is still an alarm; an unreadable sound is reported, never rewritten, because + an unmounted card comes back; and every editor write is a transactional + read-modify-write, so a one-shot alarm that disabled itself underneath an open + editor is not re-enabled by the next unrelated tap. + + The correctness find: disabling or deleting a **ringing** alarm used to clear + `ringingSince` without stopping the ring service โ€” whose auto-silence backstop + then disarms itself on its own null guard โ€” so the alarm would have sounded + until the 15-minute wake-lock timeout. Both new ViewModels now dismiss through + the engine first, conditionally, so a merely snoozed alarm keeps its snooze. + + floret-kit went to **0.6.0** for one change: `CollapsingScaffold` takes a + `floatingActionButton` slot, forwarded to the underlying `Scaffold`, rather + than each app re-deriving the inset maths in a `Box`. + + Knowingly open: no hand reordering of alarms (the time order answers it, and + `alarms` has no `sort_order` column), no multi-select or bulk delete, no undo + chip after a delete (traded for a confirmation that names the alarm), no + repeat presets, and no per-alarm auto-silence โ€” still M10 at the earliest. + Editing the app-wide defaults every override row offers to follow is M10's + settings screen. The seven new instrumentation tests compile in the gate but + have **never run on hardware**, as no device was attached. + ### โฌœ M6 โ€” Timers Multiple concurrent timers, presets, labels, add/pause/reset/+1min. Foreground service with notification controls, expiry ringing reusing M3's audio path.