fix(alarms): offer the delete Undo as the family's SnackChip

The alarm and timer lists show the Undo in floret-kit's SnackChip beside the FAB instead of the stock M3 snackbar, as Agendula and Calendula do.
This commit is contained in:
makiolaj committed 2026-10-26 21:51:38 +01:00
1 parent ba1172b822
commit c2a583fda7
12 files changed
+333 -257

No files matched your search

+9 -9
View File
@@ -1725,10 +1725,10 @@ challenge. The engine re-checks under its lock (`delete(id, unlessRinging = true
so a swipe released just as the alarm fires, before the list has caught up,
deletes nothing and the card slides back. The editor's Delete passes the same
flag: with its confirmation gone, one tap there would otherwise do what the
swipe is kept from doing, so a refused tap opens the ring screen instead, where the alarm is dealt with. Each is followed by a snackbar on the list ("07:00 alarm deleted",
swipe is kept from doing, so a refused tap opens the ring screen instead, where the alarm is dealt with. Each is followed by a chip on the list ("07:00 alarm deleted",
**Undo**), as in Google Clock. v1 asked before instead, on the argument that a
mistaken delete is found at 07:00 rather than now. But a dialog catches no more
than the snackbar does: both only catch the slip noticed in the moment, and a
than the chip does: both only catch the slip noticed in the moment, and a
confirmation the user taps through out of habit catches less. The Undo does it
without taxing every delete the user meant, so the editor's dialog went too
rather than leaving two delete paths with different safety nets.
@@ -1754,13 +1754,13 @@ had not been deleted", and that alarm would have rung.
The pending deletion lives in `AlarmUndo`, a singleton, not in either
ViewModel. The editor is popped the moment its alarm is gone, so its ViewModel
is cleared before any snackbar could be answered; the list underneath reads the
deletion from the singleton and shows the snackbar (`UndoSnackbarEffect`). It
is cleared when the snackbar is answered or times out, when a newer deletion
replaces it, and when the screen is left with the snackbar unanswered (another
is cleared before any chip could be answered; the list underneath reads the
deletion from the singleton and shows the chip (`UndoChipBand`). It
is cleared when the chip is answered or times out, when a newer deletion
replaces it, and when the screen is left with the chip unanswered (another
tab, Settings, the app closed): an Undo held back and offered later would
restore a snapshot from long ago, out of any context, and over a backup that
was restored meanwhile. A rotation is the one exception and shows the snackbar
was restored meanwhile. A rotation is the one exception and shows the chip
again. A deletion offered while no list was on screen (the app sent home the
instant the editor's Delete was tapped) is dropped unshown if it is more than
30 seconds old by the time the list is back. Both lists share this as
@@ -1808,7 +1808,7 @@ already met once, and the cheapest way not to have it again is to make the wrong
call impossible to write. **Configuration** edits (`rename`, `setDuration`,
`setRingtoneUri`) stay on `TimerRepository` and the editor calls them directly.
A card's corner delete asks nothing first, and the list's snackbar offers an
A card's corner delete asks nothing first, and the list's chip offers an
**Undo**. `TimerEngine.delete` returns the row as `TimerDeletion.snapshot`
decided, and `TimerEngine.restore` puts it back under its own id and place and
resyncs. A running timer comes back with its anchors, so it has kept counting
@@ -1816,7 +1816,7 @@ while it was gone, and one whose end passed in the meantime rings, as it would
have had it never been deleted. A timer that had already finished comes back
reset: deleting it silenced it, which is a dismissal, so it does not ring a
second time (a finished transient timer offers no Undo). The pending row is
`TimersViewModel` state, since both the delete and the snackbar are on the
`TimersViewModel` state, since both the delete and the chip are on the
list; the editor's delete keeps its confirmation.
`TimerRepository` deliberately has **no generic `edit(id, transform)`** the way