feat(ui-lvgl): WiFi icon in the status bar

Shown while WiFi is switched on (Settings > WiFi), bright when connected
(live tiles, map download, update), dim otherwise. The switch is read
from NVS once and cached. The status icon signature buffer grew so
changes to the last icons aren't missed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-09-26 23:16:47 +02:00
co-authored by Claude Opus 5.5
parent eb201bc4fd
commit 708fde7225
4 changed files with 24 additions and 14 deletions
+2 -1
View File
@@ -257,5 +257,6 @@ User list, second batch (2026-09-26):
default; off: only the top button wakes it).
- [x] Favourites as their own screen in the menu rather than a tile: a
Home card left of the main page (six slots, unread badges).
- [ ] WiFi indicator icon in the status bar.
- [x] WiFi indicator icon in the status bar: while WiFi is switched on,
bright when connected, dim otherwise.
+16 -9
View File
@@ -140,14 +140,18 @@ static void saveWifi(const char* ssid, const char* pass) {
}
// Settings > WiFi's switch: off keeps the radio off for everything (scan, map
// download). Kept with the credentials.
static int8_t s_wifi_allowed = -1; // read once (the status bar asks every second)
static bool wifiAllowed() {
Preferences p;
if (!p.begin("mc_wifi", true)) return true;
bool on = p.getBool("on", true);
p.end();
return on;
if (s_wifi_allowed < 0) {
Preferences p;
bool on = true;
if (p.begin("mc_wifi", true)) { on = p.getBool("on", true); p.end(); }
s_wifi_allowed = on;
}
return s_wifi_allowed;
}
static void setWifiAllowed(bool on) {
s_wifi_allowed = on;
Preferences p;
if (!p.begin("mc_wifi", false)) return;
p.putBool("on", on);
@@ -316,8 +320,9 @@ static void netEnd() {
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
// One line for the download popup: link details and the internal heap (TLS,
// WiFi and BLE all compete for it).
// For the status bar: NET_UP once connected, else NET_OFF (radio off, a scan,
// still connecting).
static int netRadio() { return WiFi.getMode() != WIFI_OFF && WiFi.status() == WL_CONNECTED ? NET_UP : NET_OFF; }
// Async scan: scanStart(), then scanResults() returns -1 while running, else
// the count, filling `names` (strongest first, as the driver reports them).
static void scanStart() {
@@ -545,9 +550,11 @@ static void setWifiAllowed(bool on) { s_wifi_on = on; }
static bool s_live_tiles = true;
static bool liveTiles() { return s_live_tiles; }
static void setLiveTiles(bool on) { s_live_tiles = on; }
static void netBegin(const char*, const char*) {}
static bool s_net_on = false;
static void netBegin(const char*, const char*) { s_net_on = true; }
static int netState() { return NET_UP; }
static void netEnd() {}
static void netEnd() { s_net_on = false; }
static int netRadio() { return s_net_on ? NET_UP : NET_OFF; }
static uint32_t s_scan_at = 0;
static void scanStart() { s_scan_at = millis(); }
static int scanResults(char names[][33], int max) { // a pretend scan, for the UI
+5 -3
View File
@@ -624,14 +624,16 @@ void UITask::refreshStatusBar() {
lv_label_set_text_fmt(_status_batt, "%s%s%s", _board->isExternalPowered() ? LV_SYMBOL_CHARGE : "", batt, level);
// Status icons, as the original's status bar (ui-new): Bluetooth (bright
// when the app is connected), GPS (green with a fix), the alarm, mute, then
// when the app is connected), WiFi (when switched on), GPS (green with a fix), the alarm, mute, then
// the modes that keep running in the background -- auto-advert, trail, live
// share, repeater, arrival alert -- in the accent colour. Right to left in
// that order, next to the battery.
struct Icon { const char* sym; uint32_t col; };
Icon icons[10];
Icon icons[11];
int n = 0;
if (isSerialEnabled()) icons[n++] = { LV_SYMBOL_BLUETOOTH, hasConnection() ? theme::TEXT : theme::TEXT_MUTED };
if (lvport::wifiAllowed()) // WiFi switched on: bright while connected (map tiles, update)
icons[n++] = { LV_SYMBOL_WIFI, lvport::netRadio() == lvport::NET_UP ? theme::TEXT : theme::TEXT_MUTED };
int32_t lat, lon;
bool fix = _core->course.currentLocation(lat, lon);
if (_core->gpsEnabled() || fix) icons[n++] = { LV_SYMBOL_GPS, fix ? theme::OK : theme::TEXT_MUTED };
@@ -644,7 +646,7 @@ void UITask::refreshStatusBar() {
if (_prefs && _prefs->loc_share_enabled) icons[n++] = { UI_SYMBOL_PIN, theme::ACCENT };
if (_prefs && _prefs->client_repeat) icons[n++] = { LV_SYMBOL_LOOP, theme::ACCENT };
if (_prefs && _prefs->locator_enabled && _prefs->locator_has_target) icons[n++] = { UI_SYMBOL_FLAG, theme::ACCENT };
char sig[48];
char sig[sizeof(_status_sig)];
int o = 0;
for (int i = 0; i < n && o < (int)sizeof(sig) - 12; i++) o += snprintf(sig + o, sizeof(sig) - o, "%s%lx", icons[i].sym, (unsigned long)icons[i].col);
sig[o] = '\0';
+1 -1
View File
@@ -427,7 +427,7 @@ private:
lv_obj_t* _status_time = nullptr;
lv_obj_t* _status_icons = nullptr; // a row of icon labels, rebuilt with the state
lv_obj_t* _status_batt = nullptr;
char _status_sig[48] = ""; // what the icon row shows, to skip unchanged rebuilds
char _status_sig[128] = ""; // what the icon row shows, to skip unchanged rebuilds
lv_obj_t* _toast = nullptr;
lv_timer_t* _toast_timer = nullptr;
lv_obj_t* _home_clock = nullptr;