From bfdb8a9fd4f750b803c84a13ddc3ae380831ec0b Mon Sep 17 00:00:00 2001 From: Eiswolf-BG <37225519+Eiswolf-BG@users.noreply.github.com> Date: Wed, 12 Aug 2026 21:34:53 +0200 Subject: [PATCH] Add progress-dot feedback to Settings Backup/Restore buttons The SD-bound copy in SettingsBackup::backup()/restore() blocked noticeably with no visual feedback, making the button look frozen. Both functions now accept an optional callback invoked before each of the two file copies, which menu_screen.cpp uses to append dots to the button label in place. Co-Authored-By: Claude Sonnet 5 --- src/menu_screen.cpp | 35 +++++++++++++++++++++++++++++++++-- src/settings_backup.cpp | 8 ++++++-- src/settings_backup.h | 10 ++++++++-- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/menu_screen.cpp b/src/menu_screen.cpp index 6be85d0..b3afe32 100644 --- a/src/menu_screen.cpp +++ b/src/menu_screen.cpp @@ -126,6 +126,27 @@ namespace { String onOff(bool on) { return I18n::t(on ? StringId::ON : StringId::OFF); } + // Fortschrittspunkte-Anzeige waehrend SettingsBackup::backup()/restore() + // laufen (siehe Aufrufe unten in Page::BackupReset) - diese sind + // synchrone, SD-lastige Vorgaenge, die spuerbar dauern koennen und den + // Button vorher wie eingefroren wirken liessen. SettingsBackup ruft den + // hier uebergebenen Funktionszeiger vor jedem der beiden Kopiervorgaenge + // (erst Einstellungen, dann WLAN) auf. Namespace-globale Zeiger/Variablen + // statt Lambda-Capture, da ein einfacher C-Funktionszeiger uebergeben + // werden muss (kein std::function im Projekt). + TFT_eSPI* progressTft = nullptr; + Rect progressBtnRect; + String progressLabel; + uint8_t progressDots = 0; + + void drawProgressStep() { + if (!progressTft) return; + progressDots++; + String label = progressLabel; + for (uint8_t i = 0; i < progressDots; i++) label += "."; + drawButton(*progressTft, progressBtnRect, label); + } + String screenTimeoutLabel(uint8_t minutes) { String prefix = I18n::t(StringId::MENU_SCREEN_TIMEOUT_PREFIX); if (minutes == 0) return prefix + I18n::t(StringId::NEVER); @@ -449,12 +470,22 @@ void run(TFT_eSPI& tft) { } if (backupBtn.contains(tap.x, tap.y)) { - bool ok = SettingsBackup::backup(); + progressTft = &tft; + progressBtnRect = backupBtn; + progressLabel = I18n::t(StringId::MENU_BACKUP); + progressDots = 0; + bool ok = SettingsBackup::backup(drawProgressStep); + progressTft = nullptr; showBriefMessage(tft, I18n::t(ok ? StringId::MENU_BACKUP_SAVED : StringId::MENU_BACKUP_FAILED), ok ? TFT_GREEN : TFT_RED); } else if (restoreBtn.contains(tap.x, tap.y)) { if (SettingsBackup::hasBackup()) { - bool ok = SettingsBackup::restore(); + progressTft = &tft; + progressBtnRect = restoreBtn; + progressLabel = I18n::t(StringId::MENU_RESTORE); + progressDots = 0; + bool ok = SettingsBackup::restore(drawProgressStep); + progressTft = nullptr; showBriefMessage(tft, I18n::t(ok ? StringId::MENU_RESTORED : StringId::MENU_RESTORE_FAILED), ok ? TFT_GREEN : TFT_RED); } diff --git a/src/settings_backup.cpp b/src/settings_backup.cpp index e3b6ac0..ff9818a 100644 --- a/src/settings_backup.cpp +++ b/src/settings_backup.cpp @@ -33,20 +33,24 @@ namespace { } } -bool backup() { +bool backup(void (*onStep)()) { if (!SdStorage::isMounted()) return false; SdMutex::Guard guard; + if (onStep) onStep(); bool okSettings = copyFile(Config::SD_SETTINGS_FILE, SETTINGS_BACKUP_FILE); + if (onStep) onStep(); bool okWifi = copyFile(Config::SD_WIFI_CREDENTIALS_FILE, WIFI_BACKUP_FILE); return okSettings || okWifi; } -bool restore() { +bool restore(void (*onStep)()) { if (!SdStorage::isMounted()) return false; SdMutex::Guard guard; + if (onStep) onStep(); bool okSettings = copyFile(SETTINGS_BACKUP_FILE, Config::SD_SETTINGS_FILE); + if (onStep) onStep(); bool okWifi = copyFile(WIFI_BACKUP_FILE, Config::SD_WIFI_CREDENTIALS_FILE); return okSettings || okWifi; } diff --git a/src/settings_backup.h b/src/settings_backup.h index 75cb473..56017f0 100644 --- a/src/settings_backup.h +++ b/src/settings_backup.h @@ -2,8 +2,14 @@ #include namespace SettingsBackup { - bool backup(); - bool restore(); + // onStep (falls angegeben) wird bei jedem der beiden Kopiervorgaenge + // (erst Einstellungen, dann WLAN-Zugangsdaten) direkt VOR dem + // jeweiligen Kopieren aufgerufen - der aufrufende Screen + // (menu_screen.cpp) nutzt das, um waehrend des SD-bedingt spuerbar + // langsamen Sicherns/Wiederherstellens Fortschrittspunkte auf dem + // Button anzuzeigen, statt dass der Button eingefroren wirkt. + bool backup(void (*onStep)() = nullptr); + bool restore(void (*onStep)() = nullptr); bool hasBackup(); // Loescht den kompletten Flightradar-Ordner von der SD-Karte und