fix(sos): one click on a locked L1 no longer starts and cancels an SOS; the hold always works; the contact picker doesn't stall

The Back hold started at millis() | 2, up to 2 ms ahead of the clock. With the
screen off the loop comes round in under that, the unsigned difference wrapped
and read as 3 s held: the countdown started and the release cancelled it. The
same "| 1" sentinel ahead of millis() is fixed in the other places it was used
(L1 status screen, L2 prefs flush, WiFi test, live tiles, home edge flip, SD
retry).

A lock sequence left half done by a long Back hold (no click on release) kept
the SOS hold off until the next click: cleared 500 ms after Back is let go.

Picking an SOS contact no longer saves prefs on the way there and back (a flash
write stalls the L1); leaving the SOS screen saves it with the rest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-11-02 12:54:08 +01:00
co-authored by Claude Opus 5.5
parent ada5b8e545
commit 9bbaedccce
10 changed files with 30 additions and 15 deletions
+1 -1
View File
@@ -1257,7 +1257,7 @@ static void fmtDate(char* b, size_t n, const struct tm& ti) {
// itself changes at once; shutdown() saves whatever is pending.
static uint32_t s_prefs_dirty_ms = 0; // when the first unsaved change came (0: none)
static uint32_t s_prefs_save_at = 0; // the screen was left: save from then (0: not yet)
static void prefsSave() { if (!s_prefs_dirty_ms) s_prefs_dirty_ms = millis() | 1; }
static void prefsSave() { if (!s_prefs_dirty_ms) s_prefs_dirty_ms = (millis() - 1) | 1; } // never 0, never ahead of millis()
static void prefsSaveSoon(uint32_t delay_ms) {
if (s_prefs_dirty_ms && !s_prefs_save_at) s_prefs_save_at = (millis() + delay_ms) | 1;
}