fix(timers): settle timer vibration outside the store's init and resume a ramp
The DataStore migration ran its write inside the store's initialisation, so a failed write (a full disk) would have failed every preference read, the alarm path's included. The timer-vibrate key is now nullable instead: unsettled reads as the alarm default, which is what timers did before, and ClockulaApp settles it once at the head of its startup pass, off only for a never-updated package with an empty store. A failed settle leaves the fallback in place. A timer ring restarted mid-session (handed to a second expired timer, back after an alarm held it, a recreated service) now picks its ramp up from the session's elapsed time instead of either ramping again from a whisper or jumping straight to full volume. RingAudioPlayer takes the offset; alarms pass none. The Vibrate row's switch is display-only, so a screen reader stops on the row once. Refs #22
This commit is contained in:
1 parent
8910ab7fbf
commit
84d31fe7f8
16 files changed
+223
-236
No files matched your search
+14
-6
@@ -1910,12 +1910,20 @@ Vibration is `ClockDefaults.timerVibrate`, never the alarms' `vibrate`: an
|
||||
alarm that should buzz the bed and a kitchen timer that should only beep are
|
||||
different questions. A fresh install has it **off**. An install from before
|
||||
the setting existed had its timers vibrate exactly when the alarm default did,
|
||||
so `TimerVibrateMigration` (a DataStore migration, run before the first read)
|
||||
writes that value once rather than silently changing what its timers do. Only
|
||||
a package never updated since install *and* an empty store count as fresh;
|
||||
anything else (an update, an Auto Backup restore, a store replaced after
|
||||
corruption) keeps the old behaviour. A ring that hands over from one expired
|
||||
timer to another mid-ring does not start the ramp again. Silent with vibration off is still not silence:
|
||||
and keeps that. The key is nullable: absent reads as the alarm default, and
|
||||
`SettingsPrefs.settleTimerVibrate` writes a value of its own once, at the head
|
||||
of `ClockulaApp`'s startup pass (before the boot gate writes the store). Only a
|
||||
package never updated since install *and* an empty store count as fresh and
|
||||
get `false`; anything else (an update, an Auto Backup restore, a store replaced
|
||||
after corruption) gets the alarm default copied. It is deliberately not a
|
||||
DataStore migration: a migration's write runs inside the store's
|
||||
initialisation, and a failed one would fail every read, the alarm path's
|
||||
included. A failed settle only leaves the fallback in place.
|
||||
|
||||
A ring restarted mid-session (handed to a second expired timer, back after an
|
||||
alarm held it, a recreated service) picks its ramp up where the session is,
|
||||
`TimerRing.rampElapsed` from the window's remaining time, rather than ramping
|
||||
again from a whisper. Silent with vibration off is still not silence:
|
||||
`AudioSourcePolicy` gives Silent no sources, and the player's `onSilenced`
|
||||
starts the vibrator regardless of the setting.
|
||||
|
||||
|
||||
Reference in new issue
Block a user