v3.3.0: Welcome screen, factory reset, calibration/touch fixes, flash partition fix

## New
- "Welcome" screen shown on first-time setup (before touch
  calibration), with the splash screen's animated radar graphic and a
  Start button.
- The "Setup complete" screen now counts down 7 seconds with a button
  matching the Welcome screen's style, then automatically continues
  into the app (previously required a tap).
- System menu "Backup & Reset" page (Backup, Restore, and a new
  "Reset settings" option that wipes the on-device data and re-runs
  first-time setup - useful for testing or handing the device to
  someone else).
- Touch calibration targets are now green mini radar reticles instead
  of red crosshairs.

## Improved
- The SD card's data folder is now only created after tapping Start
  on the Welcome screen, instead of on every boot regardless.
- Flash partition layout changed to free up roughly 850 KB of
  firmware space (no OTA update slot needed, since firmware is always
  flashed via cable/USB) - lowers flash usage from ~95% to ~59%.

## Fixed
- The Start button and the WiFi scanning screen now show a loading
  indicator instead of appearing frozen during SD-card/WiFi
  operations.
- A touch-input bug during first-time setup that could corrupt touch
  calibration and cause taps to land on the wrong on-screen element
  afterward (most noticeable in the WiFi network selection list).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Eiswolf-BG
2026-08-12 06:57:48 +02:00
parent ba1c062ef1
commit a7f14b3125
10 changed files with 394 additions and 84 deletions

View File

@@ -185,6 +185,26 @@ namespace {
void drawCancelButton(TFT_eSPI& tft) {
drawButton(tft, cancelBtn, "X");
}
// Small loading indicator ("."/".."/"...") during the WiFi scan (which
// can take several seconds) - without visible feedback the screen
// looked "frozen" during that time and people tapped impatiently,
// which (see comment at the end of the Scanning->PickSsid transition
// below) could cause mistaps in the freshly shown network list.
uint8_t scanDotPhase = 0;
uint32_t lastScanDotMs = 0;
constexpr uint32_t SCAN_DOT_INTERVAL_MS = 350;
void updateScanningDots(TFT_eSPI& tft) {
uint32_t now = millis();
if (now - lastScanDotMs < SCAN_DOT_INTERVAL_MS) return;
lastScanDotMs = now;
scanDotPhase = (uint8_t)((scanDotPhase + 1) % 4);
tft.fillRect(10, 26, 40, 12, TFT_BLACK);
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.setCursor(10, 26);
for (uint8_t i = 0; i < scanDotPhase; i++) tft.print(".");
}
}
bool run(TFT_eSPI& tft) {
@@ -197,6 +217,8 @@ bool run(TFT_eSPI& tft) {
scrollOffset = 0;
resetKeyboardState();
needsRedraw = true;
scanDotPhase = 0;
lastScanDotMs = 0;
WifiMgr::beginScan();
@@ -227,6 +249,16 @@ bool run(TFT_eSPI& tft) {
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.println(ssidCount == 0 ? I18n::t(StringId::WIFI_NO_NETWORKS) : I18n::t(StringId::WIFI_SELECT));
drawCancelButton(tft);
// "tapped"/"tap" were captured for the previous state
// (Stage::Scanning) - without discarding it, a tap that
// happened to land exactly in the frame the scan finished
// would immediately be evaluated below against the
// BRAND-NEW (and, to the user, not yet visible) network list
// - at a position the user never intentionally tapped. That
// is what let impatient repeated tapping during the scan
// eventually pick a "random" wrong network.
tapped = false;
}
if (stage == Stage::Connecting) {
@@ -268,6 +300,15 @@ bool run(TFT_eSPI& tft) {
resetKeyboardState();
stage = Stage::EnterPassword;
needsRedraw = true;
// Prevents this same tap (on a network name) from
// also being evaluated against the password
// keyboard further down in the same pass - "stage"
// is already EnterPassword at this point, and the
// network list rows and keyboard key rows
// partially overlap in Y, so without this a
// network selection could immediately also type a
// stray character.
tapped = false;
}
}
if (ssidCount > VISIBLE_ITEMS) {
@@ -334,6 +375,7 @@ bool run(TFT_eSPI& tft) {
}
if (!needsRedraw) {
if (stage == Stage::Scanning) updateScanningDots(tft);
MenuStars::update(tft);
delay(20);
continue;