Refactor Overlay Banner

This commit is contained in:
Jonathan Bennett 2025-06-30 19:29:46 -05:00
parent 43044cbaf2
commit 2dfa18f382
11 changed files with 264 additions and 130 deletions

View File

@ -137,23 +137,33 @@ extern bool hasUnreadMessage;
// Displays a temporary centered banner message (e.g., warning, status, etc.) // Displays a temporary centered banner message (e.g., warning, status, etc.)
// The banner appears in the center of the screen and disappears after the specified duration // The banner appears in the center of the screen and disappears after the specified duration
void Screen::showSimpleBanner(const char *message, uint32_t durationMs)
{
BannerOverlayOptions options;
options.message = message;
options.durationMs = durationMs;
options.notificationType = notificationTypeEnum::text_banner;
showOverlayBanner(options);
}
// Called to trigger a banner with custom message and duration // Called to trigger a banner with custom message and duration
void Screen::showOverlayBanner(const char *message, uint32_t durationMs, const char **optionsArrayPtr, uint8_t options, void Screen::showOverlayBanner(BannerOverlayOptions banner_overlay_options)
std::function<void(int)> bannerCallback, int8_t InitialSelected)
{ {
#ifdef USE_EINK #ifdef USE_EINK
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Skip full refresh for all overlay menus EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Skip full refresh for all overlay menus
#endif #endif
// Store the message and set the expiration timestamp // Store the message and set the expiration timestamp
strncpy(NotificationRenderer::alertBannerMessage, message, 255); strncpy(NotificationRenderer::alertBannerMessage, banner_overlay_options.message, 255);
NotificationRenderer::alertBannerMessage[255] = '\0'; // Ensure null termination NotificationRenderer::alertBannerMessage[255] = '\0'; // Ensure null termination
NotificationRenderer::alertBannerUntil = (durationMs == 0) ? 0 : millis() + durationMs; NotificationRenderer::alertBannerUntil =
NotificationRenderer::optionsArrayPtr = optionsArrayPtr; (banner_overlay_options.durationMs == 0) ? 0 : millis() + banner_overlay_options.durationMs;
NotificationRenderer::alertBannerOptions = options; NotificationRenderer::optionsArrayPtr = banner_overlay_options.optionsArrayPtr;
NotificationRenderer::alertBannerCallback = bannerCallback; NotificationRenderer::alertBannerOptions = banner_overlay_options.optionsCount;
NotificationRenderer::curSelected = InitialSelected; NotificationRenderer::alertBannerCallback = banner_overlay_options.bannerCallback;
NotificationRenderer::curSelected = banner_overlay_options.InitialSelected;
NotificationRenderer::pauseBanner = false; NotificationRenderer::pauseBanner = false;
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawAlertBannerOverlay}; NotificationRenderer::current_notification_type = notificationTypeEnum::selection_picker;
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawBannercallback};
ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0])); ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0]));
setFastFramerate(); // Draw ASAP setFastFramerate(); // Draw ASAP
ui->update(); ui->update();
@ -171,7 +181,9 @@ void Screen::showNodePicker(const char *message, uint32_t durationMs, std::funct
NotificationRenderer::alertBannerUntil = (durationMs == 0) ? 0 : millis() + durationMs; NotificationRenderer::alertBannerUntil = (durationMs == 0) ? 0 : millis() + durationMs;
NotificationRenderer::alertBannerCallback = bannerCallback; NotificationRenderer::alertBannerCallback = bannerCallback;
NotificationRenderer::pauseBanner = false; NotificationRenderer::pauseBanner = false;
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawAlertBannerOverlay}; NotificationRenderer::current_notification_type = notificationTypeEnum::node_picker;
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawBannercallback};
ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0])); ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0]));
setFastFramerate(); // Draw ASAP setFastFramerate(); // Draw ASAP
ui->update(); ui->update();
@ -615,7 +627,7 @@ int32_t Screen::runOnce()
} }
#endif #endif
if (!NotificationRenderer::isOverlayBannerShowing() && rebootAtMsec != 0) { if (!NotificationRenderer::isOverlayBannerShowing() && rebootAtMsec != 0) {
showOverlayBanner("Rebooting...", 0); showSimpleBanner("Rebooting...", 0);
} }
// Process incoming commands. // Process incoming commands.
@ -929,7 +941,7 @@ void Screen::setFrames(FrameFocus focus)
ui->disableAllIndicators(); ui->disableAllIndicators();
// Add overlays: frame icons and alert banner) // Add overlays: frame icons and alert banner)
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawAlertBannerOverlay}; static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawBannercallback};
ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0])); ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0]));
prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list
@ -1203,7 +1215,7 @@ int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
} }
} }
screen->showOverlayBanner(banner, 3000); screen->showSimpleBanner(banner, 3000);
} }
} }
@ -1243,8 +1255,7 @@ int Screen::handleInputEvent(const InputEvent *event)
#endif #endif
if (NotificationRenderer::isOverlayBannerShowing()) { if (NotificationRenderer::isOverlayBannerShowing()) {
NotificationRenderer::inEvent = event->inputEvent; NotificationRenderer::inEvent = event->inputEvent;
static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawBannercallback};
NotificationRenderer::drawAlertBannerOverlay};
ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0])); ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0]));
setFastFramerate(); // Draw ASAP setFastFramerate(); // Draw ASAP
ui->update(); ui->update();

View File

@ -5,10 +5,25 @@
#include "detect/ScanI2C.h" #include "detect/ScanI2C.h"
#include "mesh/generated/meshtastic/config.pb.h" #include "mesh/generated/meshtastic/config.pb.h"
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#include <functional>
#include <string> #include <string>
#include <vector> #include <vector>
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2) #define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
namespace graphics
{
enum notificationTypeEnum { none, text_banner, selection_picker, node_picker, number_picker };
struct BannerOverlayOptions {
const char *message;
uint32_t durationMs = 30000;
const char **optionsArrayPtr = nullptr;
uint8_t optionsCount = 0;
std::function<void(int)> bannerCallback = nullptr;
int8_t InitialSelected = 0;
notificationTypeEnum notificationType = notificationTypeEnum::text_banner;
};
} // namespace graphics
#if !HAS_SCREEN #if !HAS_SCREEN
#include "power.h" #include "power.h"
@ -40,10 +55,8 @@ class Screen
void setFunctionSymbol(std::string) {} void setFunctionSymbol(std::string) {}
void removeFunctionSymbol(std::string) {} void removeFunctionSymbol(std::string) {}
void startAlert(const char *) {} void startAlert(const char *) {}
void showOverlayBanner(const char *message, uint32_t durationMs = 3000, const char **optionsArrayPtr = nullptr, void showSimpleBanner(const char *message, uint32_t durationMs = 0) {}
uint8_t options = 0, std::function<void(int)> bannerCallback = NULL, int8_t InitialSelected = 0) void showOverlayBanner(BannerOverlayOptions) {}
{
}
void setFrames(FrameFocus focus) {} void setFrames(FrameFocus focus) {}
void endAlert() {} void endAlert() {}
}; };
@ -293,8 +306,8 @@ class Screen : public concurrency::OSThread
enqueueCmd(cmd); enqueueCmd(cmd);
} }
void showOverlayBanner(const char *message, uint32_t durationMs = 3000, const char **optionsArrayPtr = nullptr, void showSimpleBanner(const char *message, uint32_t durationMs = 0);
uint8_t options = 0, std::function<void(int)> bannerCallback = NULL, int8_t InitialSelected = 0); void showOverlayBanner(BannerOverlayOptions);
void showNodePicker(const char *message, uint32_t durationMs, std::function<void(int)> bannerCallback); void showNodePicker(const char *message, uint32_t durationMs, std::function<void(int)> bannerCallback);

View File

@ -46,47 +46,55 @@ void menuHandler::LoraRegionPicker(uint32_t duration)
"PH_868", "PH_868",
"PH_915", "PH_915",
"ANZ_433"}; "ANZ_433"};
screen->showOverlayBanner( BannerOverlayOptions bannerOptions;
"Set the LoRa region", duration, optionsArray, 23, bannerOptions.message = "Set the LoRa region";
[](int selected) -> void { bannerOptions.durationMs = duration;
if (selected != 0 && config.lora.region != _meshtastic_Config_LoRaConfig_RegionCode(selected)) { bannerOptions.optionsArrayPtr = optionsArray;
config.lora.region = _meshtastic_Config_LoRaConfig_RegionCode(selected); bannerOptions.optionsCount = 23;
// This is needed as we wait til picking the LoRa region to generate keys for the first time. bannerOptions.InitialSelected = 0;
if (!owner.is_licensed) { bannerOptions.bannerCallback = [](int selected) -> void {
bool keygenSuccess = false; if (selected != 0 && config.lora.region != _meshtastic_Config_LoRaConfig_RegionCode(selected)) {
if (config.security.private_key.size == 32) { config.lora.region = _meshtastic_Config_LoRaConfig_RegionCode(selected);
// public key is derived from private, so this will always have the same result. // This is needed as we wait til picking the LoRa region to generate keys for the first time.
if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) { if (!owner.is_licensed) {
keygenSuccess = true; bool keygenSuccess = false;
} if (config.security.private_key.size == 32) {
} else { // public key is derived from private, so this will always have the same result.
LOG_INFO("Generate new PKI keys"); if (crypto->regeneratePublicKey(config.security.public_key.bytes, config.security.private_key.bytes)) {
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
keygenSuccess = true; keygenSuccess = true;
} }
if (keygenSuccess) { } else {
config.security.public_key.size = 32; LOG_INFO("Generate new PKI keys");
config.security.private_key.size = 32; crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
owner.public_key.size = 32; keygenSuccess = true;
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
}
} }
config.lora.tx_enabled = true; if (keygenSuccess) {
initRegion(); config.security.public_key.size = 32;
if (myRegion->dutyCycle < 100) { config.security.private_key.size = 32;
config.lora.ignore_mqtt = true; // Ignore MQTT by default if region has a duty cycle limit owner.public_key.size = 32;
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
} }
service->reloadConfig(SEGMENT_CONFIG);
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
} }
}, config.lora.tx_enabled = true;
0); initRegion();
if (myRegion->dutyCycle < 100) {
config.lora.ignore_mqtt = true; // Ignore MQTT by default if region has a duty cycle limit
}
service->reloadConfig(SEGMENT_CONFIG);
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
}
};
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::TwelveHourPicker() void menuHandler::TwelveHourPicker()
{ {
static const char *optionsArray[] = {"Back", "12-hour", "24-hour"}; static const char *optionsArray[] = {"Back", "12-hour", "24-hour"};
screen->showOverlayBanner("Time Format", 30000, optionsArray, 3, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Time Format";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 3;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 0) { if (selected == 0) {
menuHandler::menuQueue = menuHandler::clock_menu; menuHandler::menuQueue = menuHandler::clock_menu;
} else if (selected == 1) { } else if (selected == 1) {
@ -95,13 +103,18 @@ void menuHandler::TwelveHourPicker()
config.display.use_12h_clock = false; config.display.use_12h_clock = false;
} }
service->reloadConfig(SEGMENT_CONFIG); service->reloadConfig(SEGMENT_CONFIG);
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::ClockFacePicker() void menuHandler::ClockFacePicker()
{ {
static const char *optionsArray[] = {"Back", "Digital", "Analog"}; static const char *optionsArray[] = {"Back", "Digital", "Analog"};
screen->showOverlayBanner("Which Face?", 30000, optionsArray, 3, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Which Face?";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 3;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 0) { if (selected == 0) {
menuHandler::menuQueue = menuHandler::clock_menu; menuHandler::menuQueue = menuHandler::clock_menu;
} else if (selected == 1) { } else if (selected == 1) {
@ -111,7 +124,8 @@ void menuHandler::ClockFacePicker()
graphics::ClockRenderer::digitalWatchFace = false; graphics::ClockRenderer::digitalWatchFace = false;
screen->setFrames(Screen::FOCUS_CLOCK); screen->setFrames(Screen::FOCUS_CLOCK);
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::TZPicker() void menuHandler::TZPicker()
@ -135,7 +149,11 @@ void menuHandler::TZPicker()
"AU/ACST", "AU/ACST",
"AU/AEST", "AU/AEST",
"Pacific/NZ"}; "Pacific/NZ"};
screen->showOverlayBanner("Pick Timezone", 30000, optionsArray, 17, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Pick Timezone";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 17;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 0) { if (selected == 0) {
menuHandler::menuQueue = menuHandler::clock_menu; menuHandler::menuQueue = menuHandler::clock_menu;
} else if (selected == 1) { // Hawaii } else if (selected == 1) { // Hawaii
@ -177,13 +195,18 @@ void menuHandler::TZPicker()
setenv("TZ", config.device.tzdef, 1); setenv("TZ", config.device.tzdef, 1);
service->reloadConfig(SEGMENT_CONFIG); service->reloadConfig(SEGMENT_CONFIG);
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::clockMenu() void menuHandler::clockMenu()
{ {
static const char *optionsArray[] = {"Back", "Clock Face", "Time Format", "Timezone"}; static const char *optionsArray[] = {"Back", "Clock Face", "Time Format", "Timezone"};
screen->showOverlayBanner("Clock Action", 30000, optionsArray, 4, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Clock Action";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 4;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
menuHandler::menuQueue = menuHandler::clock_face_picker; menuHandler::menuQueue = menuHandler::clock_face_picker;
screen->setInterval(0); screen->setInterval(0);
@ -197,7 +220,8 @@ void menuHandler::clockMenu()
screen->setInterval(0); screen->setInterval(0);
runASAP = true; runASAP = true;
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::messageResponseMenu() void menuHandler::messageResponseMenu()
@ -219,7 +243,11 @@ void menuHandler::messageResponseMenu()
optionsArrayPtr = optionsArray; optionsArrayPtr = optionsArray;
options = 5; options = 5;
#endif #endif
screen->showOverlayBanner("Message Action", 30000, optionsArrayPtr, options, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Message Action";
bannerOptions.optionsArrayPtr = optionsArrayPtr;
bannerOptions.optionsCount = options;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
screen->dismissCurrentFrame(); screen->dismissCurrentFrame();
} else if (selected == 2) { } else if (selected == 2) {
@ -243,7 +271,8 @@ void menuHandler::messageResponseMenu()
audioThread->readAloud(msg); audioThread->readAloud(msg);
} }
#endif #endif
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::homeBaseMenu() void menuHandler::homeBaseMenu()
@ -270,7 +299,11 @@ void menuHandler::homeBaseMenu()
optionsArrayPtr = optionsArray; optionsArrayPtr = optionsArray;
options = 5; options = 5;
} }
screen->showOverlayBanner("Home Action", 30000, optionsArrayPtr, options, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Home Action";
bannerOptions.optionsArrayPtr = optionsArrayPtr;
bannerOptions.optionsCount = options;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
#ifdef PIN_EINK_EN #ifdef PIN_EINK_EN
if (digitalRead(PIN_EINK_EN) == HIGH) { if (digitalRead(PIN_EINK_EN) == HIGH) {
@ -282,7 +315,7 @@ void menuHandler::homeBaseMenu()
screen->setOn(false); screen->setOn(false);
#endif #endif
} else if (selected == 2) { } else if (selected == 2) {
InputEvent event = {.inputEvent = (input_broker_event)175, .kbchar = 175, .touchX = 0, .touchY = 0}; InputEvent event = {.inputEvent = (input_broker_event)INPUT_BROKER_SEND_PING, .kbchar = 0, .touchX = 0, .touchY = 0};
inputBroker->injectInputEvent(&event); inputBroker->injectInputEvent(&event);
} else if (selected == 3) { } else if (selected == 3) {
cannedMessageModule->LaunchWithDestination(NODENUM_BROADCAST); cannedMessageModule->LaunchWithDestination(NODENUM_BROADCAST);
@ -297,7 +330,8 @@ void menuHandler::homeBaseMenu()
InputEvent event = {.inputEvent = (input_broker_event)170, .kbchar = 170, .touchX = 0, .touchY = 0}; InputEvent event = {.inputEvent = (input_broker_event)170, .kbchar = 170, .touchX = 0, .touchY = 0};
inputBroker->injectInputEvent(&event); inputBroker->injectInputEvent(&event);
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::systemBaseMenu() void menuHandler::systemBaseMenu()
@ -317,7 +351,11 @@ void menuHandler::systemBaseMenu()
options = 3; options = 3;
#endif #endif
optionsArrayPtr = optionsArray; optionsArrayPtr = optionsArray;
screen->showOverlayBanner("System Action", 30000, optionsArrayPtr, options, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "System Action";
bannerOptions.optionsArrayPtr = optionsArrayPtr;
bannerOptions.optionsCount = options;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
menuHandler::menuQueue = menuHandler::buzzermodemenupicker; menuHandler::menuQueue = menuHandler::buzzermodemenupicker;
screen->setInterval(0); screen->setInterval(0);
@ -336,7 +374,8 @@ void menuHandler::systemBaseMenu()
screen->setInterval(0); screen->setInterval(0);
runASAP = true; runASAP = true;
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::favoriteBaseMenu() void menuHandler::favoriteBaseMenu()
@ -353,13 +392,18 @@ void menuHandler::favoriteBaseMenu()
optionsArrayPtr = optionsArray; optionsArrayPtr = optionsArray;
options = 2; options = 2;
} }
screen->showOverlayBanner("Favorites Action", 30000, optionsArrayPtr, options, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Favorites Action";
bannerOptions.optionsArrayPtr = optionsArrayPtr;
bannerOptions.optionsCount = options;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
cannedMessageModule->LaunchWithDestination(graphics::UIRenderer::currentFavoriteNodeNum); cannedMessageModule->LaunchWithDestination(graphics::UIRenderer::currentFavoriteNodeNum);
} else if (selected == 2) { } else if (selected == 2) {
cannedMessageModule->LaunchFreetextWithDestination(graphics::UIRenderer::currentFavoriteNodeNum); cannedMessageModule->LaunchFreetextWithDestination(graphics::UIRenderer::currentFavoriteNodeNum);
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::positionBaseMenu() void menuHandler::positionBaseMenu()
@ -376,7 +420,11 @@ void menuHandler::positionBaseMenu()
optionsArrayPtr = optionsArray; optionsArrayPtr = optionsArray;
options = 3; options = 3;
} }
screen->showOverlayBanner("Position Action", 30000, optionsArrayPtr, options, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Position Action";
bannerOptions.optionsArrayPtr = optionsArrayPtr;
bannerOptions.optionsCount = options;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
menuQueue = gps_toggle_menu; menuQueue = gps_toggle_menu;
} else if (selected == 2) { } else if (selected == 2) {
@ -384,36 +432,51 @@ void menuHandler::positionBaseMenu()
} else if (selected == 3) { } else if (selected == 3) {
accelerometerThread->calibrate(30); accelerometerThread->calibrate(30);
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::nodeListMenu() void menuHandler::nodeListMenu()
{ {
static const char *optionsArray[] = {"Back", "Reset NodeDB"}; static const char *optionsArray[] = {"Back", "Reset NodeDB"};
screen->showOverlayBanner("Node Action", 30000, optionsArray, 2, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Node Action";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 2;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
menuQueue = reset_node_db_menu; menuQueue = reset_node_db_menu;
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::resetNodeDBMenu() void menuHandler::resetNodeDBMenu()
{ {
static const char *optionsArray[] = {"Back", "Confirm"}; static const char *optionsArray[] = {"Back", "Confirm"};
screen->showOverlayBanner("Confirm Reset NodeDB", 30000, optionsArray, 2, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Confirm Reset NodeDB";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 2;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
disableBluetooth(); disableBluetooth();
LOG_INFO("Initiate node-db reset"); LOG_INFO("Initiate node-db reset");
nodeDB->resetNodes(); nodeDB->resetNodes();
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000); rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::compassNorthMenu() void menuHandler::compassNorthMenu()
{ {
static const char *optionsArray[] = {"Back", "Dynamic", "Fixed Ring", "Freeze Heading"}; static const char *optionsArray[] = {"Back", "Dynamic", "Fixed Ring", "Freeze Heading"};
screen->showOverlayBanner("North Directions?", 30000, optionsArray, 4, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "North Directions?";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 4;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
if (config.display.compass_north_top != false) { if (config.display.compass_north_top != false) {
config.display.compass_north_top = false; config.display.compass_north_top = false;
@ -438,62 +501,78 @@ void menuHandler::compassNorthMenu()
} else if (selected == 0) { } else if (selected == 0) {
menuQueue = position_base_menu; menuQueue = position_base_menu;
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::GPSToggleMenu() void menuHandler::GPSToggleMenu()
{ {
static const char *optionsArray[] = {"Back", "Enabled", "Disabled"}; static const char *optionsArray[] = {"Back", "Enabled", "Disabled"};
screen->showOverlayBanner( BannerOverlayOptions bannerOptions;
"Toggle GPS", 30000, optionsArray, 3, bannerOptions.message = "Toggle GPS";
[](int selected) -> void { bannerOptions.optionsArrayPtr = optionsArray;
if (selected == 1) { bannerOptions.optionsCount = 3;
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED; bannerOptions.bannerCallback = [](int selected) -> void {
playGPSEnableBeep(); if (selected == 1) {
gps->enable(); config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
service->reloadConfig(SEGMENT_CONFIG); playGPSEnableBeep();
} else if (selected == 2) { gps->enable();
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED; service->reloadConfig(SEGMENT_CONFIG);
playGPSDisableBeep(); } else if (selected == 2) {
gps->disable(); config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED;
service->reloadConfig(SEGMENT_CONFIG); playGPSDisableBeep();
} else { gps->disable();
menuQueue = position_base_menu; service->reloadConfig(SEGMENT_CONFIG);
} } else {
}, menuQueue = position_base_menu;
config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED ? 1 : 2); // set inital selection }
};
bannerOptions.InitialSelected = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED ? 1 : 2;
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::BuzzerModeMenu() void menuHandler::BuzzerModeMenu()
{ {
static const char *optionsArray[] = {"All Enabled", "Disabled", "Notifications", "System Only"}; static const char *optionsArray[] = {"All Enabled", "Disabled", "Notifications", "System Only"};
screen->showOverlayBanner( BannerOverlayOptions bannerOptions;
"Beep Action", 30000, optionsArray, 4, bannerOptions.message = "Beep Action";
[](int selected) -> void { bannerOptions.optionsArrayPtr = optionsArray;
config.device.buzzer_mode = (meshtastic_Config_DeviceConfig_BuzzerMode)selected; bannerOptions.optionsCount = 4;
service->reloadConfig(SEGMENT_CONFIG); bannerOptions.bannerCallback = [](int selected) -> void {
}, config.device.buzzer_mode = (meshtastic_Config_DeviceConfig_BuzzerMode)selected;
config.device.buzzer_mode); service->reloadConfig(SEGMENT_CONFIG);
};
bannerOptions.InitialSelected = config.device.buzzer_mode;
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::switchToMUIMenu() void menuHandler::switchToMUIMenu()
{ {
static const char *optionsArray[] = {"Yes", "No"}; static const char *optionsArray[] = {"Yes", "No"};
screen->showOverlayBanner("Switch to MUI?", 30000, optionsArray, 2, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Switch to MUI?";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 2;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 0) { if (selected == 0) {
config.display.displaymode = meshtastic_Config_DisplayConfig_DisplayMode_COLOR; config.display.displaymode = meshtastic_Config_DisplayConfig_DisplayMode_COLOR;
config.bluetooth.enabled = false; config.bluetooth.enabled = false;
service->reloadConfig(SEGMENT_CONFIG); service->reloadConfig(SEGMENT_CONFIG);
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000); rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::TFTColorPickerMenu() void menuHandler::TFTColorPickerMenu()
{ {
static const char *optionsArray[] = {"Back", "Default", "Meshtastic Green", "Yellow", "Red", "Orange", "Purple", "Teal", static const char *optionsArray[] = {"Back", "Default", "Meshtastic Green", "Yellow", "Red", "Orange", "Purple", "Teal",
"Pink", "White"}; "Pink", "White"};
screen->showOverlayBanner("Select Screen Color", 30000, optionsArray, 10, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Select Screen Color";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 10;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 1) { if (selected == 1) {
LOG_INFO("Setting color to system default or defined variant"); LOG_INFO("Setting color to system default or defined variant");
// Insert unset protobuf code here // Insert unset protobuf code here
@ -529,22 +608,29 @@ void menuHandler::TFTColorPickerMenu()
static_cast<ST7789Spi *>(screen->getDisplayDevice())->setRGB(TFT_MESH); static_cast<ST7789Spi *>(screen->getDisplayDevice())->setRGB(TFT_MESH);
screen->setFrames(graphics::Screen::FOCUS_SYSTEM); screen->setFrames(graphics::Screen::FOCUS_SYSTEM);
// I think we need a saveToDisk to commit a protobuf change? // I think we need a saveToDisk to commit a protobuf change?
// There isn't a protobuf for this setting yet, so no save
// nodeDB->saveToDisk(SEGMENT_CONFIG); // nodeDB->saveToDisk(SEGMENT_CONFIG);
} }
#endif #endif
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::rebootMenu() void menuHandler::rebootMenu()
{ {
static const char *optionsArray[] = {"Yes", "No"}; static const char *optionsArray[] = {"Yes", "No"};
screen->showOverlayBanner("Reboot Device?", 30000, optionsArray, 2, [](int selected) -> void { BannerOverlayOptions bannerOptions;
bannerOptions.message = "Reboot Device?";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 2;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == 0) { if (selected == 0) {
IF_SCREEN(screen->showOverlayBanner("Rebooting...", 0)); IF_SCREEN(screen->showSimpleBanner("Rebooting...", 0));
nodeDB->saveToDisk(); nodeDB->saveToDisk();
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000; rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000;
} }
}); };
screen->showOverlayBanner(bannerOptions);
} }
void menuHandler::handleMenuSwitch() void menuHandler::handleMenuSwitch()

View File

@ -34,6 +34,7 @@ uint8_t NotificationRenderer::alertBannerOptions = 0; // last x lines are seelct
const char **NotificationRenderer::optionsArrayPtr = nullptr; const char **NotificationRenderer::optionsArrayPtr = nullptr;
std::function<void(int)> NotificationRenderer::alertBannerCallback = NULL; std::function<void(int)> NotificationRenderer::alertBannerCallback = NULL;
bool NotificationRenderer::pauseBanner = false; bool NotificationRenderer::pauseBanner = false;
notificationTypeEnum NotificationRenderer::current_notification_type = notificationTypeEnum::none;
// Used on boot when a certificate is being created // Used on boot when a certificate is being created
void NotificationRenderer::drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void NotificationRenderer::drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
@ -55,6 +56,17 @@ void NotificationRenderer::drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiStat
} }
} }
void NotificationRenderer::resetBanner()
{
alertBannerMessage[0] = '\0';
current_notification_type = notificationTypeEnum::none;
}
void NotificationRenderer::drawBannercallback(OLEDDisplay *display, OLEDDisplayUiState *state)
{
drawAlertBannerOverlay(display, state);
}
void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisplayUiState *state) void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
{ {
if (!isOverlayBannerShowing() || pauseBanner) if (!isOverlayBannerShowing() || pauseBanner)
@ -108,9 +120,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
curSelected++; curSelected++;
} else if (inEvent == INPUT_BROKER_SELECT) { } else if (inEvent == INPUT_BROKER_SELECT) {
alertBannerCallback(curSelected); alertBannerCallback(curSelected);
alertBannerMessage[0] = '\0'; resetBanner();
} else if ((inEvent == INPUT_BROKER_CANCEL || inEvent == INPUT_BROKER_ALT_LONG) && alertBannerUntil != 0) { } else if ((inEvent == INPUT_BROKER_CANCEL || inEvent == INPUT_BROKER_ALT_LONG) && alertBannerUntil != 0) {
alertBannerMessage[0] = '\0'; resetBanner();
} }
if (curSelected == -1) if (curSelected == -1)
@ -119,7 +131,7 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
curSelected = 0; curSelected = 0;
} else { } else {
if (inEvent == INPUT_BROKER_SELECT || inEvent == INPUT_BROKER_ALT_LONG || inEvent == INPUT_BROKER_CANCEL) { if (inEvent == INPUT_BROKER_SELECT || inEvent == INPUT_BROKER_ALT_LONG || inEvent == INPUT_BROKER_CANCEL) {
alertBannerMessage[0] = '\0'; resetBanner();
} }
} }

View File

@ -2,6 +2,7 @@
#include "OLEDDisplay.h" #include "OLEDDisplay.h"
#include "OLEDDisplayUi.h" #include "OLEDDisplayUi.h"
#include "graphics/Screen.h"
#define MAX_LINES 5 #define MAX_LINES 5
namespace graphics namespace graphics
@ -20,6 +21,8 @@ class NotificationRenderer
static bool pauseBanner; static bool pauseBanner;
static void resetBanner();
static void drawBannercallback(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisplayUiState *state); static void drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawNotificationBox(OLEDDisplay *display, OLEDDisplayUiState *state, const char *lines[MAX_LINES + 1], static void drawNotificationBox(OLEDDisplay *display, OLEDDisplayUiState *state, const char *lines[MAX_LINES + 1],
uint16_t totalLines, uint8_t firstOptionToShow, uint16_t maxWidth = 0); uint16_t totalLines, uint8_t firstOptionToShow, uint16_t maxWidth = 0);
@ -28,6 +31,8 @@ class NotificationRenderer
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static bool isOverlayBannerShowing(); static bool isOverlayBannerShowing();
static graphics::notificationTypeEnum current_notification_type;
}; };
} // namespace graphics } // namespace graphics

View File

@ -1357,7 +1357,7 @@ void setup()
if (!rIf->reconfigure()) { if (!rIf->reconfigure()) {
LOG_WARN("Reconfigure failed, rebooting"); LOG_WARN("Reconfigure failed, rebooting");
if (screen) { if (screen) {
screen->showOverlayBanner("Rebooting..."); screen->showSimpleBanner("Rebooting...");
} }
rebootAtMsec = millis() + 5000; rebootAtMsec = millis() + 5000;
} }

View File

@ -1190,7 +1190,7 @@ void AdminModule::reboot(int32_t seconds)
{ {
LOG_INFO("Reboot in %d seconds", seconds); LOG_INFO("Reboot in %d seconds", seconds);
if (screen) if (screen)
screen->showOverlayBanner("Rebooting...", 0); // stays on screen screen->showSimpleBanner("Rebooting...", 0); // stays on screen
rebootAtMsec = (seconds < 0) ? 0 : (millis() + seconds * 1000); rebootAtMsec = (seconds < 0) ? 0 : (millis() + seconds * 1000);
} }

View File

@ -59,7 +59,7 @@ bool KeyVerificationModule::handleReceivedProtobuf(const meshtastic_MeshPacket &
r->hash1.size == 0) { r->hash1.size == 0) {
memcpy(hash2, r->hash2.bytes, 32); memcpy(hash2, r->hash2.bytes, 32);
if (screen) if (screen)
screen->showOverlayBanner("Enter Security Number", 30000); screen->showSimpleBanner("Enter Security Number", 30000);
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING; cn->level = meshtastic_LogRecord_Level_WARNING;
@ -82,12 +82,19 @@ bool KeyVerificationModule::handleReceivedProtobuf(const meshtastic_MeshPacket &
static const char *optionsArray[] = {"ACCEPT", "REJECT"}; static const char *optionsArray[] = {"ACCEPT", "REJECT"};
LOG_INFO("Hash1 matches!"); LOG_INFO("Hash1 matches!");
if (screen) { if (screen) {
screen->showOverlayBanner(message, 30000, optionsArray, 2, [=](int selected) { graphics::BannerOverlayOptions options;
options.message = message;
options.durationMs = 30000;
options.optionsArrayPtr = optionsArray;
options.optionsCount = 2;
options.notificationType = graphics::notificationTypeEnum::selection_picker;
options.bannerCallback = [=](int selected) {
if (selected == 0) { if (selected == 0) {
auto remoteNodePtr = nodeDB->getMeshNode(currentRemoteNode); auto remoteNodePtr = nodeDB->getMeshNode(currentRemoteNode);
remoteNodePtr->bitfield |= NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK; remoteNodePtr->bitfield |= NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK;
} }
}); };
screen->showOverlayBanner(options);
} }
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING; cn->level = meshtastic_LogRecord_Level_WARNING;
@ -185,7 +192,7 @@ meshtastic_MeshPacket *KeyVerificationModule::allocReply()
responsePacket->pki_encrypted = true; responsePacket->pki_encrypted = true;
if (screen) { if (screen) {
snprintf(message, 25, "Security Number \n%03u %03u", currentSecurityNumber / 1000, currentSecurityNumber % 1000); snprintf(message, 25, "Security Number \n%03u %03u", currentSecurityNumber / 1000, currentSecurityNumber % 1000);
screen->showOverlayBanner(message, 30000); screen->showSimpleBanner(message, 30000);
LOG_WARN("%s", message); LOG_WARN("%s", message);
} }
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
@ -255,7 +262,7 @@ void KeyVerificationModule::processSecurityNumber(uint32_t incomingNumber)
sprintf(message, "Verification: \n"); sprintf(message, "Verification: \n");
generateVerificationCode(message + 15); // send the toPhone packet generateVerificationCode(message + 15); // send the toPhone packet
if (screen) { if (screen) {
screen->showOverlayBanner(message, 30000); screen->showSimpleBanner(message, 30000);
} }
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING; cn->level = meshtastic_LogRecord_Level_WARNING;

View File

@ -47,7 +47,7 @@ int SystemCommandsModule::handleInputEvent(const InputEvent *event)
bool isMuted = externalNotificationModule->getMute(); bool isMuted = externalNotificationModule->getMute();
externalNotificationModule->setMute(!isMuted); externalNotificationModule->setMute(!isMuted);
IF_SCREEN(graphics::isMuted = !isMuted; if (!isMuted) externalNotificationModule->stopNow(); IF_SCREEN(graphics::isMuted = !isMuted; if (!isMuted) externalNotificationModule->stopNow();
screen->showOverlayBanner(isMuted ? "Notifications\nEnabled" : "Notifications\nDisabled", 3000);) screen->showSimpleBanner(isMuted ? "Notifications\nEnabled" : "Notifications\nDisabled", 3000);)
} }
return 0; return 0;
// Bluetooth // Bluetooth
@ -58,24 +58,24 @@ int SystemCommandsModule::handleInputEvent(const InputEvent *event)
#if defined(ARDUINO_ARCH_NRF52) #if defined(ARDUINO_ARCH_NRF52)
if (!config.bluetooth.enabled) { if (!config.bluetooth.enabled) {
disableBluetooth(); disableBluetooth();
IF_SCREEN(screen->showOverlayBanner("Bluetooth OFF\nRebooting", 3000)); IF_SCREEN(screen->showSimpleBanner("Bluetooth OFF\nRebooting", 3000));
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 2000; rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 2000;
} else { } else {
IF_SCREEN(screen->showOverlayBanner("Bluetooth ON\nRebooting", 3000)); IF_SCREEN(screen->showSimpleBanner("Bluetooth ON\nRebooting", 3000));
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000; rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000;
} }
#else #else
if (!config.bluetooth.enabled) { if (!config.bluetooth.enabled) {
disableBluetooth(); disableBluetooth();
IF_SCREEN(screen->showOverlayBanner("Bluetooth OFF", 3000)); IF_SCREEN(screen->showSimpleBanner("Bluetooth OFF", 3000));
} else { } else {
IF_SCREEN(screen->showOverlayBanner("Bluetooth ON\nRebooting", 3000)); IF_SCREEN(screen->showSimpleBanner("Bluetooth ON\nRebooting", 3000));
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000; rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000;
} }
#endif #endif
return 0; return 0;
case INPUT_BROKER_MSG_REBOOT: case INPUT_BROKER_MSG_REBOOT:
IF_SCREEN(screen->showOverlayBanner("Rebooting...", 0)); IF_SCREEN(screen->showSimpleBanner("Rebooting...", 0));
nodeDB->saveToDisk(); nodeDB->saveToDisk();
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000; rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000;
// runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; // runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
@ -92,7 +92,7 @@ int SystemCommandsModule::handleInputEvent(const InputEvent *event)
gps->toggleGpsMode(); gps->toggleGpsMode();
const char *msg = const char *msg =
(config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) ? "GPS Enabled" : "GPS Disabled"; (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) ? "GPS Enabled" : "GPS Disabled";
IF_SCREEN(screen->forceDisplay(); screen->showOverlayBanner(msg, 3000);) IF_SCREEN(screen->forceDisplay(); screen->showSimpleBanner(msg, 3000);)
} }
#endif #endif
return true; return true;
@ -100,15 +100,15 @@ int SystemCommandsModule::handleInputEvent(const InputEvent *event)
case INPUT_BROKER_SEND_PING: case INPUT_BROKER_SEND_PING:
service->refreshLocalMeshNode(); service->refreshLocalMeshNode();
if (service->trySendPosition(NODENUM_BROADCAST, true)) { if (service->trySendPosition(NODENUM_BROADCAST, true)) {
IF_SCREEN(screen->showOverlayBanner("Position\nSent", 3000)); IF_SCREEN(screen->showSimpleBanner("Position\nSent", 3000));
} else { } else {
IF_SCREEN(screen->showOverlayBanner("Node Info\nSent", 3000)); IF_SCREEN(screen->showSimpleBanner("Node Info\nSent", 3000));
} }
return true; return true;
// Power control // Power control
case INPUT_BROKER_SHUTDOWN: case INPUT_BROKER_SHUTDOWN:
LOG_ERROR("Shutting Down"); LOG_ERROR("Shutting Down");
IF_SCREEN(screen->showOverlayBanner("Shutting Down...")); IF_SCREEN(screen->showSimpleBanner("Shutting Down..."));
nodeDB->saveToDisk(); nodeDB->saveToDisk();
shutdownAtMsec = millis() + DEFAULT_SHUTDOWN_SECONDS * 1000; shutdownAtMsec = millis() + DEFAULT_SHUTDOWN_SECONDS * 1000;
// runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; // runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;

View File

@ -450,7 +450,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
if (isOwnTelemetry && bannerMsg && isCooldownOver) { if (isOwnTelemetry && bannerMsg && isCooldownOver) {
LOG_INFO("drawFrame: IAQ %d (own) — showing banner: %s", m.iaq, bannerMsg); LOG_INFO("drawFrame: IAQ %d (own) — showing banner: %s", m.iaq, bannerMsg);
screen->showOverlayBanner(bannerMsg, 3000); screen->showSimpleBanner(bannerMsg, 3000);
// Only buzz if IAQ is over 200 // Only buzz if IAQ is over 200
if (m.iaq > 200 && moduleConfig.external_notification.enabled && !externalNotificationModule->getMute()) { if (m.iaq > 200 && moduleConfig.external_notification.enabled && !externalNotificationModule->getMute()) {

View File

@ -42,7 +42,7 @@ void powerCommandsCheck()
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) #if defined(ARCH_ESP32) || defined(ARCH_NRF52)
if (shutdownAtMsec && screen) { if (shutdownAtMsec && screen) {
screen->showOverlayBanner("Shutting Down...", 0); // stays on screen screen->showSimpleBanner("Shutting Down...", 0); // stays on screen
} }
#endif #endif