refactor(companion): shared shutdown steps, SD channel key by secret, fetch race, small UI fixes

- UITaskBase holds what both UIs' shutdown() and low-battery check share:
  the saves before the goodbye sound, the power-down (GPS through its
  provider) and the battery EMA and threshold.
- L2 SD archive: a channel's file is keyed by its secret only, so renaming
  keeps the history; old files are renamed once at boot.
- L2 fetch: abandoning a request and the task finishing it are one critical
  section (it could stay DONE for good); TileCache gets the read-side barrier.
- Text from a repeater or sensor no longer rings on the device (nothing to
  open); a settings switch reads any non-zero value as on; the message
  toast never cuts a letter in half; ui-new's GPS helpers ask UiCore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-10-12 18:08:31 +02:00
co-authored by Claude Opus 5.5
parent 28d8291e33
commit 01a068be7d
8 changed files with 82 additions and 65 deletions
+4 -17
View File
@@ -382,9 +382,7 @@ uint32_t UITask::idleMillis(uint32_t lv_next) {
void UITask::shutdown(bool restart) {
s_prefs_dirty_ms = s_prefs_save_at = 0;
the_mesh.savePrefs();
the_mesh.saveRTCTime();
the_mesh.flushDirtyContacts();
saveBeforeShutdown();
if (!trailJournalTick(true)) _core->trail.onShutdown(); // no card: the internal slot, if enabled
#ifdef PIN_BUZZER
_buzzer.shutdown(); // the goodbye sound, unless muted
@@ -392,17 +390,7 @@ void UITask::shutdown(bool restart) {
for (uint32_t t0 = millis(); _buzzer.isPlaying() && millis() - t0 < 2500; ) { _buzzer.loop(); delay(10); }
#endif
#endif
if (restart) {
_board->reboot();
} else {
if (_display) _display->turnOff();
radio_driver.powerOff();
if (_sensors) {
LocationProvider* loc = _sensors->getLocationProvider();
if (loc) loc->stop();
}
_board->powerOff();
}
powerDown(restart, _display, _sensors);
}
// Settings > Power > Battery shutdown (NodePrefs::low_batt_mv), as
@@ -411,9 +399,8 @@ void UITask::checkLowBattery() {
if ((int32_t)(millis() - _next_batt_ms) < 0) return;
_next_batt_ms = millis() + 8000;
uint16_t raw = getBattMilliVolts();
if (raw > 0) _batt_mv = _batt_mv == 0 ? raw : (uint16_t)((_batt_mv * 4u + raw) / 5u); // EMA, alpha 0.2
uint16_t low = _prefs ? _prefs->low_batt_mv : 0;
if (low == 0 || _batt_mv == 0 || _batt_mv >= low || _board->isExternalPowered()) return;
if (raw > 0) _batt_mv = battEma(_batt_mv, raw);
if (!lowBatteryShutdownDue(_batt_mv, _prefs)) return;
wake();
showToast("Low battery - shutting down", 3000);
lv_timer_handler();