refactor(alarms): derive the alarm-set notice from the engine alone
The announcer now records only which alarm a user action set, and when. What the snackbar says is derived from upcoming() while a screen shows it, re-subscribed per announcement so the first read is from after the write. That removes the second resolve path through the engine lock (upcomingFor is gone), the publish lock, and the flash of a pre-write countdown. The engine is observed only while an announcement stands. Freshness is judged when a screen picks the announcement up, so one already showing is not cut off half-way. Consuming matches a sequence number. Latest action wins across alarms again: the sentence names no alarm, so a settling announcement must never land on top of a newer action on another one. Switching an alarm off announces nothing, and a dismissal retracts before it skips. Refs #19
This commit is contained in:
1 parent
ff49667d39
commit
9516dc1198
4 files changed
+106
-141
No files matched your search
+16
-19
@@ -1116,25 +1116,22 @@ its own writes. `reschedule()` is called explicitly: from `ClockulaApp`, from
|
||||
the receivers, and from the alarm editor. `upcoming()` runs the same resolver in
|
||||
preview mode and *discards* the state it returns; a read must not write, and a
|
||||
test asserts the store recorded nothing across a full collection.
|
||||
`upcomingFor(alarmId)` is the same read for one alarm, on demand: the list and
|
||||
the editor ask it right after a user's change to say how long until that alarm
|
||||
rings. `AlarmSetCountdown` (pure, in `domain/alarm/`) decides what that says —
|
||||
only a natural occurrence of an enabled alarm, rounded as the row's countdown
|
||||
is, never a snooze or a ring. The `AlarmClock` intents never reach it, since
|
||||
they already get the status-bar icon (#19). The editor announces a time pick
|
||||
at once, but waits for repeat-day taps to settle for a second, so Mon–Fri is
|
||||
one snackbar rather than five. `AlarmSetAnnouncer` is an app-wide singleton
|
||||
holding the notice as *state* until a screen has shown it to the end: pick →
|
||||
OK → back disposes the editor's snackbar a moment after it appears, and the
|
||||
list underneath picks the same notice up. The editor's fire-time-moving
|
||||
writes, their reschedule and the per-alarm settle all run on the application
|
||||
scope, so leaving the editor at once neither loses the announcement nor leaves
|
||||
a stored time unscheduled. A screen shows the notice only while resumed, so a
|
||||
cross-fade never shows it twice; the editor shows only notices about its own
|
||||
alarm; a notice is re-checked against the engine before it is shown, so an
|
||||
alarm switched off or deleted by any path is never announced as set. A notice
|
||||
older than ten seconds on the monotonic clock is dropped unshown rather than
|
||||
shown with a stale countdown.
|
||||
The "Alarm set for … from now" snackbar (#19) is built on `upcoming()` too.
|
||||
`AlarmSetAnnouncer`, an app-wide singleton, records only *which* alarm a user
|
||||
action in the list or the editor just set; while a resumed screen shows it,
|
||||
what it says is derived from `upcoming()`, through `AlarmSetCountdown` (pure,
|
||||
in `domain/alarm/`): only a natural occurrence of an enabled alarm, rounded as
|
||||
the row's countdown is, never a snooze or a ring. So an alarm switched off or
|
||||
deleted by any path is never announced as set, and the `AlarmClock` intents,
|
||||
which already get the status-bar icon, never reach it. The announcement is
|
||||
*state*, standing until a screen has shown it to the end: pick → OK → back
|
||||
disposes the editor's snackbar a moment after it appears, and the list
|
||||
underneath picks it up. The editor announces a time pick at once and waits a
|
||||
second for repeat-day taps to settle, so Mon–Fri is one snackbar; the settle,
|
||||
and the editor's fire-time-moving writes with their reschedule, run in tap
|
||||
order on the application scope, so leaving the editor at once neither loses
|
||||
the announcement nor leaves a stored time unscheduled. An announcement older
|
||||
than ten seconds on the monotonic clock is dropped unshown.
|
||||
|
||||
`upcoming(refresh: Flow<Unit>)` takes its **re-read cadence as a parameter**.
|
||||
The resolver needs a `now`, and `upcoming` reads one inside a `combine` of the
|
||||
|
||||
Reference in new issue
Block a user