mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-01 10:21:59 +00:00
fix(ui-lvgl): smooth WiFi/Bluetooth switches; retry 404 tiles
- The WiFi and Bluetooth rows rebuilt the whole Settings page to update their hint, cutting the switch's animation short; the hint is now rewritten in place (rowHintSet). The "Bluetooth on" echo toast is gone. - Map download: a 404 gets the same one retry as other errors (OpenTopoMap sends the odd 404 for a tile not rendered yet), and a download that ends with gaps says "Done, N missing - download again". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -46,8 +46,18 @@ static void onQuickEditPh(lv_event_t* e) { s_ui->quickEditInsert((int)(uintptr_
|
||||
static void onQuickEditKb(lv_event_t* e) { s_ui->quickEditDone(lv_event_get_code(e) == LV_EVENT_READY); }
|
||||
static void onQuickList(lv_event_t* e) { (void)e; s_ui->showQuickMsgs(); }
|
||||
static void onAdvertGo(lv_event_t* e) { s_ui->advertSend((uintptr_t)lv_event_get_user_data(e) != 0); }
|
||||
static void bluetoothHint(char* sub, size_t n) {
|
||||
if (!s_ui->isSerialEnabled()) snprintf(sub, n, "Off");
|
||||
else if (s_ui->hasConnection()) snprintf(sub, n, "App connected");
|
||||
else if (the_mesh.getBLEPin()) snprintf(sub, n, "PIN %06lu", (unsigned long)the_mesh.getBLEPin());
|
||||
else snprintf(sub, n, "Waiting for the app");
|
||||
}
|
||||
static void onBtSwitch(lv_event_t* e) {
|
||||
s_ui->setBluetooth(lv_obj_has_state((lv_obj_t*)lv_event_get_target(e), LV_STATE_CHECKED));
|
||||
lv_obj_t* sw = (lv_obj_t*)lv_event_get_target(e);
|
||||
s_ui->setBluetooth(lv_obj_has_state(sw, LV_STATE_CHECKED));
|
||||
char sub[48];
|
||||
bluetoothHint(sub, sizeof(sub));
|
||||
rowHintSet(lv_obj_get_parent(sw), sub);
|
||||
}
|
||||
|
||||
} // namespace qview
|
||||
@@ -210,25 +220,15 @@ void UITask::advertSend(bool flood) {
|
||||
|
||||
static void bluetoothRow(lv_obj_t* body) {
|
||||
char sub[48];
|
||||
bool on = s_ui->isSerialEnabled();
|
||||
if (!on) snprintf(sub, sizeof(sub), "Off");
|
||||
else if (s_ui->hasConnection()) snprintf(sub, sizeof(sub), "App connected");
|
||||
else if (the_mesh.getBLEPin()) snprintf(sub, sizeof(sub), "PIN %06lu", (unsigned long)the_mesh.getBLEPin());
|
||||
else snprintf(sub, sizeof(sub), "Waiting for the app");
|
||||
qview::bluetoothHint(sub, sizeof(sub));
|
||||
lv_obj_t* sw = switchRow(body, LV_SYMBOL_BLUETOOTH " Bluetooth", sub, nullptr);
|
||||
if (on) lv_obj_add_state(sw, LV_STATE_CHECKED);
|
||||
if (s_ui->isSerialEnabled()) lv_obj_add_state(sw, LV_STATE_CHECKED);
|
||||
lv_obj_add_event_cb(sw, qview::onBtSwitch, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
}
|
||||
|
||||
void UITask::setBluetooth(bool on) {
|
||||
if (on) enableSerial(); else disableSerial();
|
||||
showToast(on ? "Bluetooth on" : "Bluetooth off - USB still works", 1500);
|
||||
if (_screen == SCR_SETTINGS) { // the row's subtitle
|
||||
lv_obj_t* body = _body;
|
||||
int32_t y = body ? lv_obj_get_scroll_y(body) : 0;
|
||||
buildSettings();
|
||||
if (_body) { lv_obj_update_layout(_body); lv_obj_scroll_to_y(_body, y, LV_ANIM_OFF); }
|
||||
}
|
||||
if (!on) showToast("Bluetooth off - USB still works", 1500);
|
||||
refreshStatusBar();
|
||||
}
|
||||
|
||||
|
||||
@@ -373,6 +373,13 @@ static lv_obj_t* groupText(lv_obj_t* row, const char* text, const char* hint, ui
|
||||
// The title label of a settingRow() / listRow(), to recolour or rename it.
|
||||
static lv_obj_t* rowTitle(lv_obj_t* row) { return (lv_obj_t*)lv_obj_get_user_data(row); }
|
||||
|
||||
// Rewrites the hint under a row's title in place (the label made right after
|
||||
// it) -- a rebuild would cut short the animation of the switch just tapped.
|
||||
static void rowHintSet(lv_obj_t* row, const char* hint) {
|
||||
lv_obj_t* h = lv_obj_get_sibling(rowTitle(row), 1);
|
||||
if (h && lv_obj_check_type(h, &lv_label_class)) lv_label_set_text(h, hint);
|
||||
}
|
||||
|
||||
// A settings row: the label left (a muted hint under it, cut at `hint_w`),
|
||||
// room on the right for a switch / dropdown / slider.
|
||||
static lv_obj_t* settingRow(lv_obj_t* parent, const char* text, const char* hint, int hint_w = 150) {
|
||||
@@ -2983,8 +2990,7 @@ void UITask::refreshThread() {
|
||||
if (n == 0 && _thread_skip > 0) { // the page went away (history trimmed)
|
||||
_thread_skip = 0;
|
||||
n = loadThreadPage(total);
|
||||
}
|
||||
if (total > _thread_skip + n) {
|
||||
} if (total > _thread_skip + n) {
|
||||
char t[40];
|
||||
snprintf(t, sizeof(t), LV_SYMBOL_UP " Older messages (%d)", total - _thread_skip - n);
|
||||
pageButton(_thread_list, t, 1);
|
||||
|
||||
@@ -33,8 +33,19 @@ static void onWifiForget(lv_event_t* e) {
|
||||
s_wifi_forget_btn = nullptr;
|
||||
s_ui->wifiForget((int)(uintptr_t)lv_event_get_user_data(e));
|
||||
}
|
||||
static void wifiHint(char* sub, size_t n) {
|
||||
int saved = lvport::wifiSavedCount();
|
||||
if (!lvport::wifiAllowed()) snprintf(sub, n, "Off");
|
||||
else if (saved == 1) snprintf(sub, n, "%s", lvport::wifiSaved(0)->ssid);
|
||||
else if (saved > 1) snprintf(sub, n, "%d saved networks", saved);
|
||||
else snprintf(sub, n, "Tap to pick a network");
|
||||
}
|
||||
static void onWifiAllowed(lv_event_t* e) {
|
||||
s_ui->wifiSetAllowed(lv_obj_has_state((lv_obj_t*)lv_event_get_target(e), LV_STATE_CHECKED));
|
||||
lv_obj_t* sw = (lv_obj_t*)lv_event_get_target(e);
|
||||
s_ui->wifiSetAllowed(lv_obj_has_state(sw, LV_STATE_CHECKED));
|
||||
char sub[48];
|
||||
wifiHint(sub, sizeof(sub));
|
||||
rowHintSet(lv_obj_get_parent(sw), sub);
|
||||
}
|
||||
static void onWifiField(lv_event_t* e) { s_ui->wifiEdit((lv_obj_t*)lv_event_get_target(e)); }
|
||||
static void onWifiKb(lv_event_t* e) {
|
||||
@@ -165,14 +176,9 @@ void UITask::wifiKeyboardHide() {
|
||||
// on / off, the row opens the network settings.
|
||||
static void wifiRow(lv_obj_t* body) {
|
||||
char sub[48];
|
||||
int n = lvport::wifiSavedCount();
|
||||
bool on = lvport::wifiAllowed();
|
||||
if (!on) snprintf(sub, sizeof(sub), "Off");
|
||||
else if (n == 1) snprintf(sub, sizeof(sub), "%s", lvport::wifiSaved(0)->ssid);
|
||||
else if (n > 1) snprintf(sub, sizeof(sub), "%d saved networks", n);
|
||||
else snprintf(sub, sizeof(sub), "Tap to pick a network");
|
||||
wifiHint(sub, sizeof(sub));
|
||||
lv_obj_t* sw = switchRow(body, LV_SYMBOL_WIFI " WiFi", sub, nullptr);
|
||||
if (on) lv_obj_add_state(sw, LV_STATE_CHECKED);
|
||||
if (lvport::wifiAllowed()) lv_obj_add_state(sw, LV_STATE_CHECKED);
|
||||
lv_obj_add_event_cb(sw, onWifiAllowed, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
lv_obj_t* row = lv_obj_get_parent(sw);
|
||||
lv_obj_add_flag(row, LV_OBJ_FLAG_CLICKABLE);
|
||||
@@ -189,12 +195,6 @@ void UITask::wifiSetAllowed(bool on) {
|
||||
if (mapview::s_dl.active()) mapDownloadStop();
|
||||
if (_wifi_scanning) { _wifi_scanning = false; lvport::netEnd(); }
|
||||
}
|
||||
if (_screen == SCR_SETTINGS) { // the row's subtitle
|
||||
lv_obj_t* body = _body;
|
||||
int32_t y = body ? lv_obj_get_scroll_y(body) : 0;
|
||||
buildSettings();
|
||||
if (_body) { lv_obj_update_layout(_body); lv_obj_scroll_to_y(_body, y, LV_ANIM_OFF); }
|
||||
}
|
||||
}
|
||||
|
||||
void UITask::wifiScan() {
|
||||
|
||||
@@ -228,9 +228,11 @@ public:
|
||||
else if (isPlaceholder(data, len)) { lvport::fetchRelease(); finish(FAILED, "Server sends a placeholder (blocked / key?)"); return; }
|
||||
else if (!writeTile(_z, _x, _y, data, len)) { lvport::fetchRelease(); finish(FAILED, "Can't write to the SD card"); return; }
|
||||
else { _done++; _consec_fail = 0; }
|
||||
} else if (!_retried && r != -403 && r != -401 && r != -404) {
|
||||
} else if (!_retried && r != -403 && r != -401) {
|
||||
// One more try after a pause: a dropped keep-alive connection or a
|
||||
// busy server usually answers the second time.
|
||||
// busy server usually answers the second time. A 404 too: both tile
|
||||
// servers answer every tile of the world, and OpenTopoMap sends the
|
||||
// odd 404 for a tile it hasn't rendered yet.
|
||||
lvport::fetchRelease();
|
||||
_retried = true;
|
||||
_last_start = millis() + 1000;
|
||||
@@ -247,7 +249,13 @@ public:
|
||||
|
||||
// Skip tiles already on the card (a few stat()s per pass), then start the next GET.
|
||||
for (int i = 0; i < 16 && _state == RUNNING; i++) {
|
||||
if (_z > _area.zmax) { finish(DONE, "Done"); return; }
|
||||
if (_z > _area.zmax) {
|
||||
// Tiles on the card are skipped, so the same download again fetches just the missing ones.
|
||||
char m[48];
|
||||
if (_failed) snprintf(m, sizeof(m), "Done, %lu missing - download again", (unsigned long)_failed);
|
||||
finish(DONE, _failed ? m : "Done");
|
||||
return;
|
||||
}
|
||||
char path[96];
|
||||
tilePath(path, sizeof(path), _z, _x, _y, _layer);
|
||||
struct stat st;
|
||||
|
||||
Reference in New Issue
Block a user