v2.3.2: Add info button to WiFi Manager screen explaining multi-network support
This commit is contained in:
@@ -145,6 +145,10 @@ enum class StringId : uint8_t {
|
|||||||
WIFI_NETWORKS_TITLE,
|
WIFI_NETWORKS_TITLE,
|
||||||
WIFI_ADD_NETWORK,
|
WIFI_ADD_NETWORK,
|
||||||
WIFI_EMPTY_SLOT,
|
WIFI_EMPTY_SLOT,
|
||||||
|
WIFI_INFO_TITLE,
|
||||||
|
WIFI_INFO_PARA1,
|
||||||
|
WIFI_INFO_PARA2,
|
||||||
|
WIFI_INFO_PARA3,
|
||||||
|
|
||||||
COUNT
|
COUNT
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -145,6 +145,11 @@ static const char* const I18N_DE[] = {
|
|||||||
"WLAN-Netzwerke",
|
"WLAN-Netzwerke",
|
||||||
"Netzwerk hinzufügen",
|
"Netzwerk hinzufügen",
|
||||||
"(leer)",
|
"(leer)",
|
||||||
|
|
||||||
|
"Wie WLAN-Netzwerke funktionieren",
|
||||||
|
"Du kannst bis zu 3 WLAN-Netzwerke speichern. Beim Start verbindet sich das Gerät automatisch mit dem, das gerade erreichbar ist.",
|
||||||
|
"Praktisch für unterwegs (Büro, Freunde, Ferienhaus), für Gast- und Haupt-WLAN am selben Router, oder wenn du mehrere Access Points im Haus hast.",
|
||||||
|
"Über das rote 'X' kannst du ein gespeichertes Netzwerk jederzeit wieder entfernen, um Platz für ein neues zu schaffen.",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_DE) / sizeof(I18N_DE[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_DE) / sizeof(I18N_DE[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -146,6 +146,11 @@ static const char* const I18N_EN[] = {
|
|||||||
"WiFi networks",
|
"WiFi networks",
|
||||||
"Add network",
|
"Add network",
|
||||||
"(empty)",
|
"(empty)",
|
||||||
|
|
||||||
|
"How WiFi networks work",
|
||||||
|
"You can save up to 3 WiFi networks. On boot, the device automatically connects to whichever one it can currently reach.",
|
||||||
|
"Handy for portable use (office, friends, holiday home), for guest + main WiFi on the same router, or if you have multiple access points around the house.",
|
||||||
|
"Remove a saved network anytime via the red 'X' to free up a slot for a new one.",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_EN) / sizeof(I18N_EN[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_EN) / sizeof(I18N_EN[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -145,6 +145,11 @@ static const char* const I18N_ES[] = {
|
|||||||
"Redes WiFi",
|
"Redes WiFi",
|
||||||
"Añadir red",
|
"Añadir red",
|
||||||
"(vacío)",
|
"(vacío)",
|
||||||
|
|
||||||
|
"Cómo funcionan las redes WiFi",
|
||||||
|
"Puede guardar hasta 3 redes WiFi. Al iniciar, el dispositivo se conecta automáticamente a la que pueda alcanzar en ese momento.",
|
||||||
|
"Útil para uso móvil (oficina, amigos, casa de vacaciones), para WiFi de invitados + principal en el mismo router, o si tiene varios puntos de acceso en casa.",
|
||||||
|
"Elimine una red guardada en cualquier momento con la 'X' roja para liberar un espacio para una nueva.",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_ES) / sizeof(I18N_ES[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_ES) / sizeof(I18N_ES[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -145,6 +145,11 @@ static const char* const I18N_FR[] = {
|
|||||||
"Réseaux WiFi",
|
"Réseaux WiFi",
|
||||||
"Ajouter un réseau",
|
"Ajouter un réseau",
|
||||||
"(vide)",
|
"(vide)",
|
||||||
|
|
||||||
|
"Comment marchent les réseaux WiFi",
|
||||||
|
"Vous pouvez enregistrer jusqu'à 3 réseaux WiFi. Au démarrage, l'appareil se connecte automatiquement à celui qu'il peut atteindre.",
|
||||||
|
"Pratique en déplacement (bureau, amis, maison de vacances), pour un WiFi invité + principal sur le même routeur, ou si vous avez plusieurs points d'accès.",
|
||||||
|
"Supprimez un réseau enregistré à tout moment via le 'X' rouge pour libérer une place pour un nouveau.",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_FR) / sizeof(I18N_FR[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_FR) / sizeof(I18N_FR[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -145,6 +145,11 @@ static const char* const I18N_IT[] = {
|
|||||||
"Reti WiFi",
|
"Reti WiFi",
|
||||||
"Aggiungi rete",
|
"Aggiungi rete",
|
||||||
"(vuoto)",
|
"(vuoto)",
|
||||||
|
|
||||||
|
"Come funzionano le reti WiFi",
|
||||||
|
"Puoi salvare fino a 3 reti WiFi. All'avvio, il dispositivo si connette automaticamente a quella che riesce a raggiungere in quel momento.",
|
||||||
|
"Utile per l'uso portatile (ufficio, amici, casa vacanze), per WiFi ospiti + principale sullo stesso router, o se hai più punti di accesso in casa.",
|
||||||
|
"Rimuovi una rete salvata in qualsiasi momento tramite la 'X' rossa per liberare uno slot per una nuova.",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_IT) / sizeof(I18N_IT[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_IT) / sizeof(I18N_IT[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -145,6 +145,11 @@ static const char* const I18N_TR[] = {
|
|||||||
"WiFi ağları",
|
"WiFi ağları",
|
||||||
"Ağ ekle",
|
"Ağ ekle",
|
||||||
"(boş)",
|
"(boş)",
|
||||||
|
|
||||||
|
"WiFi ağları nasıl çalışır",
|
||||||
|
"3 adete kadar WiFi ağı kaydedebilirsiniz. Başlangıçta cihaz, o an erişebildiği ağa otomatik olarak bağlanır.",
|
||||||
|
"Taşınabilir kullanım için kullanışlıdır (ofis, arkadaşlar, tatil evi), aynı yönlendiricide misafir + ana WiFi için, veya evde birden fazla erişim noktanız varsa.",
|
||||||
|
"Kayıtlı bir ağı istediğiniz zaman kırmızı 'X' ile kaldırarak yeni bir ağ için yer açabilirsiniz.",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_TR) / sizeof(I18N_TR[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_TR) / sizeof(I18N_TR[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -25,6 +25,104 @@ namespace {
|
|||||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||||
tft.setTextDatum(TL_DATUM);
|
tft.setTextDatum(TL_DATUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t layoutWrapped(TFT_eSPI& tft, int16_t x, int16_t startY, int16_t maxWidth,
|
||||||
|
int16_t lineHeight, const String& text, int16_t scrollY,
|
||||||
|
int16_t viewTop, int16_t viewBottom, bool draw) {
|
||||||
|
int16_t y = startY;
|
||||||
|
int32_t start = 0;
|
||||||
|
int32_t len = text.length();
|
||||||
|
while (start < len) {
|
||||||
|
while (start < len && text[start] == ' ') start++;
|
||||||
|
if (start >= len) break;
|
||||||
|
|
||||||
|
String line = text.substring(start, len);
|
||||||
|
while (tft.textWidth(line) > maxWidth) {
|
||||||
|
int32_t lastSpace = line.lastIndexOf(' ');
|
||||||
|
if (lastSpace <= 0) break;
|
||||||
|
line = line.substring(0, lastSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (draw) {
|
||||||
|
int16_t screenY = y - scrollY;
|
||||||
|
if (screenY >= viewTop && screenY <= viewBottom) {
|
||||||
|
tft.setCursor(x, screenY);
|
||||||
|
tft.print(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y += lineHeight;
|
||||||
|
start += line.length();
|
||||||
|
}
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void runInfoScreen(TFT_eSPI& tft) {
|
||||||
|
MenuStars::reset();
|
||||||
|
|
||||||
|
constexpr int16_t textMaxWidth = Config::SCREEN_WIDTH - 20;
|
||||||
|
constexpr int16_t LINE_H = 16;
|
||||||
|
constexpr int16_t VIEW_TOP = 40;
|
||||||
|
Rect backBtn = {10, (int16_t)(Config::SCREEN_HEIGHT - 50), (int16_t)(Config::SCREEN_WIDTH - 20), 40};
|
||||||
|
constexpr int16_t VIEW_BOTTOM = Config::SCREEN_HEIGHT - 60;
|
||||||
|
|
||||||
|
int16_t totalH = VIEW_TOP;
|
||||||
|
totalH = layoutWrapped(tft, 10, totalH, textMaxWidth, LINE_H, I18n::t(StringId::WIFI_INFO_PARA1), 0, 0, 0, false);
|
||||||
|
totalH += 8;
|
||||||
|
totalH = layoutWrapped(tft, 10, totalH, textMaxWidth, LINE_H, I18n::t(StringId::WIFI_INFO_PARA2), 0, 0, 0, false);
|
||||||
|
totalH += 8;
|
||||||
|
totalH = layoutWrapped(tft, 10, totalH, textMaxWidth, LINE_H, I18n::t(StringId::WIFI_INFO_PARA3), 0, 0, 0, false);
|
||||||
|
|
||||||
|
int16_t maxScroll = totalH - VIEW_BOTTOM;
|
||||||
|
if (maxScroll < 0) maxScroll = 0;
|
||||||
|
bool scrollable = maxScroll > 0;
|
||||||
|
int16_t scrollY = 0;
|
||||||
|
|
||||||
|
Rect upBtn = {(int16_t)(Config::SCREEN_WIDTH - 34), 4, 30, 24};
|
||||||
|
Rect downBtn = {(int16_t)(Config::SCREEN_WIDTH - 34), 30, 30, 24};
|
||||||
|
constexpr int16_t SCROLL_STEP = 48;
|
||||||
|
|
||||||
|
auto redraw = [&]() {
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||||
|
tft.setCursor(10, 14);
|
||||||
|
tft.println(I18n::t(StringId::WIFI_INFO_TITLE));
|
||||||
|
|
||||||
|
if (scrollable) {
|
||||||
|
drawButton(tft, upBtn, "^");
|
||||||
|
drawButton(tft, downBtn, "v");
|
||||||
|
}
|
||||||
|
|
||||||
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||||
|
int16_t y = VIEW_TOP;
|
||||||
|
y = layoutWrapped(tft, 10, y, textMaxWidth, LINE_H, I18n::t(StringId::WIFI_INFO_PARA1), scrollY, VIEW_TOP, VIEW_BOTTOM, true);
|
||||||
|
y += 8;
|
||||||
|
y = layoutWrapped(tft, 10, y, textMaxWidth, LINE_H, I18n::t(StringId::WIFI_INFO_PARA2), scrollY, VIEW_TOP, VIEW_BOTTOM, true);
|
||||||
|
y += 8;
|
||||||
|
layoutWrapped(tft, 10, y, textMaxWidth, LINE_H, I18n::t(StringId::WIFI_INFO_PARA3), scrollY, VIEW_TOP, VIEW_BOTTOM, true);
|
||||||
|
|
||||||
|
drawButton(tft, backBtn, I18n::t(StringId::BACK));
|
||||||
|
};
|
||||||
|
|
||||||
|
redraw();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
TouchInput::Point tap;
|
||||||
|
if (TouchInput::wasTapped(tap)) {
|
||||||
|
if (backBtn.contains(tap.x, tap.y)) return;
|
||||||
|
if (scrollable && upBtn.contains(tap.x, tap.y) && scrollY > 0) {
|
||||||
|
scrollY -= SCROLL_STEP;
|
||||||
|
if (scrollY < 0) scrollY = 0;
|
||||||
|
redraw();
|
||||||
|
} else if (scrollable && downBtn.contains(tap.x, tap.y) && scrollY < maxScroll) {
|
||||||
|
scrollY += SCROLL_STEP;
|
||||||
|
if (scrollY > maxScroll) scrollY = maxScroll;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuStars::update(tft);
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(TFT_eSPI& tft) {
|
void run(TFT_eSPI& tft) {
|
||||||
@@ -40,6 +138,9 @@ void run(TFT_eSPI& tft) {
|
|||||||
tft.setCursor(10, 14);
|
tft.setCursor(10, 14);
|
||||||
tft.println(I18n::t(StringId::WIFI_NETWORKS_TITLE));
|
tft.println(I18n::t(StringId::WIFI_NETWORKS_TITLE));
|
||||||
|
|
||||||
|
Rect infoBtn = {(int16_t)(Config::SCREEN_WIDTH - 40), 2, 30, 24};
|
||||||
|
drawButton(tft, infoBtn, "?");
|
||||||
|
|
||||||
uint8_t count = WifiMgr::networkCount();
|
uint8_t count = WifiMgr::networkCount();
|
||||||
int16_t y = 40;
|
int16_t y = 40;
|
||||||
|
|
||||||
@@ -84,6 +185,10 @@ void run(TFT_eSPI& tft) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
if (infoBtn.contains(tap.x, tap.y)) {
|
||||||
|
runInfoScreen(tft);
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
for (uint8_t i = 0; i < count && !handled; i++) {
|
for (uint8_t i = 0; i < count && !handled; i++) {
|
||||||
if (removeRects[i].contains(tap.x, tap.y)) {
|
if (removeRects[i].contains(tap.x, tap.y)) {
|
||||||
WifiMgr::removeNetwork(i);
|
WifiMgr::removeNetwork(i);
|
||||||
|
|||||||
Reference in New Issue
Block a user