refactor(ui-core): move clock tools into ClockEngine; add Core event queue

Alarm / countdown / ring logic moves from UITask to ui-core/ClockEngine.h
unchanged. New ui-core/UiEvents.h: fixed-size Core -> frontend event
queue; UITask::tickCore() runs UiCore::loop() and reacts to ClockAlert /
ClockRingEnded (wake, alert overlay, melody). ClockToolsScreen API unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-09-24 23:03:57 +02:00
co-authored by Claude Opus 5.5
parent 3b7aa28ff9
commit dd826a447e
7 changed files with 253 additions and 131 deletions
@@ -3,12 +3,13 @@
// Entered with Enter on the home CLOCK page. A small top menu picks one of the
// three tools; Cancel backs out a level (tool → menu → home).
//
// This screen is pure UI. The time-critical machinery lives in UITask, which
// drives it every loop regardless of the current screen:
// • Alarm — UITask schedules an absolute fire instant from NodePrefs'
// This screen is pure UI. The time-critical machinery lives in the UI Core's
// ClockEngine (ui-core/ClockEngine.h), which UITask drives every loop
// regardless of the current screen:
// • Alarm — the engine schedules an absolute fire instant from NodePrefs'
// alarm_hour/min (robust to RTC re-syncs) and rings. Here we just edit the
// persisted fields and call onAlarmChanged() to re-schedule.
// • Timer — UITask owns the running countdown (startTimer / stopTimer /
// • Timer — the engine owns the running countdown (startTimer / stopTimer /
// isTimerRunning / timerRemainingMs). It rings even when off-screen.
// • Stopwatch — purely a display utility with no background action, so its
// millis() state lives here; it keeps counting while you're elsewhere.