feat(timers): the timers tab, and the pill that finally has something to show

Multiple concurrent timers with labels, presets, add, pause, reset and +1 min.
The setup panel is inline on an empty tab, so the first timer costs no
navigation.

The live pill has been waiting since M4 for something that could start a
timer. It now goes through the engine rather than the repository, because a
scheduler registration and a foreground service have to move with the state —
its own contract is unchanged.

Three new architecture rules keep it that way: no screen may name the
scheduler, the service or AlarmManager, and a second MediaPlayer anywhere
outside the ring path fails the build.
This commit is contained in:
2026-09-12 16:48:36 +02:00
parent 7f9219e929
commit b67142a727
24 changed files with 2733 additions and 12 deletions
+39 -1
View File
@@ -24,9 +24,47 @@
<!-- M4: the tabs' empty states -->
<string name="alarms_empty">No alarms yet</string>
<string name="timers_empty">No timers yet</string>
<string name="world_clocks_empty">No world clocks yet</string>
<!-- M6: the timers tab, its rows and the setup panel -->
<string name="timers_set_title">Set timer</string>
<string name="timers_setup_start">Start</string>
<string name="timers_setup_range_hint">Between 1 second and 24 hours</string>
<string name="timers_presets">Presets</string>
<string name="timers_preset_save">Save</string>
<string name="timers_preset_remove">Remove preset</string>
<string name="timer_keypad_backspace">Delete a digit</string>
<string name="timer_keypad_digit">Type %1$s</string>
<string name="timer_start">Start</string>
<string name="timer_pause">Pause</string>
<string name="timer_resume">Resume</string>
<string name="timer_reset">Reset</string>
<string name="timer_stop">Stop</string>
<string name="timer_add_minute">+1 min</string>
<string name="timer_finished">Finished</string>
<string name="timer_paused_at">Paused \u00b7 %1$s</string>
<string name="timer_untitled">Timer</string>
<string name="timer_row_progress">%1$s left</string>
<string name="timer_row_open">Timer settings</string>
<!-- M6: the timer editor -->
<string name="timer_editor_title">Timer</string>
<string name="timer_editor_label">Label</string>
<string name="timer_editor_duration">Length</string>
<string name="timer_editor_duration_locked">Reset the timer to change its length</string>
<string name="timer_editor_sound">Sound</string>
<string name="timer_editor_delete">Delete timer</string>
<string name="timer_editor_delete_confirm">Delete this timer?</string>
<!-- M6: the timer notification. One channel, one id, however many timers. -->
<string name="channel_timers_name">Timers</string>
<string name="channel_timers_description">The running countdown and the sound when a timer finishes. Turning this off does not silence a timer.</string>
<string name="timer_notification_title">Timer</string>
<plurals name="timer_more_active">
<item quantity="one">+%1$d more timer</item>
<item quantity="other">+%1$d more timers</item>
</plurals>
<!-- M4: the live pill -->
<string name="live_pill_pause">Pause</string>
<string name="live_pill_resume">Resume</string>