diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index f22a0d8a8..efabf18b3 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -882,71 +882,86 @@ void Screen::setFrames(FrameFocus focus) } #if defined(DISPLAY_CLOCK_FRAME) - fsi.positions.clock = numframes; - normalFrames[numframes++] = uiconfig.is_clockface_analog ? graphics::ClockRenderer::drawAnalogClockFrame - : graphics::ClockRenderer::drawDigitalClockFrame; - indicatorIcons.push_back(digital_icon_clock); + if (!hiddenFrames.clock) { + fsi.positions.clock = numframes; + normalFrames[numframes++] = uiconfig.is_clockface_analog ? graphics::ClockRenderer::drawAnalogClockFrame + : graphics::ClockRenderer::drawDigitalClockFrame; + indicatorIcons.push_back(digital_icon_clock); + } #endif // Declare this early so it’s available in FOCUS_PRESERVE block bool willInsertTextMessage = shouldDrawMessage(&devicestate.rx_text_message); - fsi.positions.home = numframes; - normalFrames[numframes++] = graphics::UIRenderer::drawDeviceFocused; - indicatorIcons.push_back(icon_home); + if (!hiddenFrames.home) { + fsi.positions.home = numframes; + normalFrames[numframes++] = graphics::UIRenderer::drawDeviceFocused; + indicatorIcons.push_back(icon_home); + } fsi.positions.textMessage = numframes; normalFrames[numframes++] = graphics::MessageRenderer::drawTextMessageFrame; indicatorIcons.push_back(icon_mail); #ifndef USE_EINK - fsi.positions.nodelist = numframes; - normalFrames[numframes++] = graphics::NodeListRenderer::drawDynamicNodeListScreen; - indicatorIcons.push_back(icon_nodes); + if (!hiddenFrames.nodelist) { + fsi.positions.nodelist = numframes; + normalFrames[numframes++] = graphics::NodeListRenderer::drawDynamicNodeListScreen; + indicatorIcons.push_back(icon_nodes); + } #endif // Show detailed node views only on E-Ink builds #ifdef USE_EINK - fsi.positions.nodelist_lastheard = numframes; - normalFrames[numframes++] = graphics::NodeListRenderer::drawLastHeardScreen; - indicatorIcons.push_back(icon_nodes); - - fsi.positions.nodelist_hopsignal = numframes; - normalFrames[numframes++] = graphics::NodeListRenderer::drawHopSignalScreen; - indicatorIcons.push_back(icon_signal); - - fsi.positions.nodelist_distance = numframes; - normalFrames[numframes++] = graphics::NodeListRenderer::drawDistanceScreen; - indicatorIcons.push_back(icon_distance); + if (!hiddenFrames.nodelist_lastheard) { + fsi.positions.nodelist_lastheard = numframes; + normalFrames[numframes++] = graphics::NodeListRenderer::drawLastHeardScreen; + indicatorIcons.push_back(icon_nodes); + } + if (!hiddenFrames.nodelist_hopsignal) { + fsi.positions.nodelist_hopsignal = numframes; + normalFrames[numframes++] = graphics::NodeListRenderer::drawHopSignalScreen; + indicatorIcons.push_back(icon_signal); + } + if (!hiddenFrames.nodelist_distance) { + fsi.positions.nodelist_distance = numframes; + normalFrames[numframes++] = graphics::NodeListRenderer::drawDistanceScreen; + indicatorIcons.push_back(icon_distance); + } #endif #if HAS_GPS - fsi.positions.nodelist_bearings = numframes; - normalFrames[numframes++] = graphics::NodeListRenderer::drawNodeListWithCompasses; - indicatorIcons.push_back(icon_list); - - fsi.positions.gps = numframes; - normalFrames[numframes++] = graphics::UIRenderer::drawCompassAndLocationScreen; - indicatorIcons.push_back(icon_compass); + if (!hiddenFrames.nodelist_bearings) { + fsi.positions.nodelist_bearings = numframes; + normalFrames[numframes++] = graphics::NodeListRenderer::drawNodeListWithCompasses; + indicatorIcons.push_back(icon_list); + } + if (!hiddenFrames.gps) { + fsi.positions.gps = numframes; + normalFrames[numframes++] = graphics::UIRenderer::drawCompassAndLocationScreen; + indicatorIcons.push_back(icon_compass); + } #endif - if (RadioLibInterface::instance) { + if (RadioLibInterface::instance && !hiddenFrames.lora) { fsi.positions.lora = numframes; normalFrames[numframes++] = graphics::DebugRenderer::drawLoRaFocused; indicatorIcons.push_back(icon_radio); } - if (!dismissedFrames.memory) { - fsi.positions.memory = numframes; - normalFrames[numframes++] = graphics::DebugRenderer::drawMemoryUsage; - indicatorIcons.push_back(icon_memory); + if (!hiddenFrames.system) { + fsi.positions.system = numframes; + normalFrames[numframes++] = graphics::DebugRenderer::drawSystemScreen; + indicatorIcons.push_back(icon_system); } #if !defined(DISPLAY_CLOCK_FRAME) - fsi.positions.clock = numframes; - normalFrames[numframes++] = uiconfig.is_clockface_analog ? graphics::ClockRenderer::drawAnalogClockFrame - : graphics::ClockRenderer::drawDigitalClockFrame; - indicatorIcons.push_back(digital_icon_clock); + if (!hiddenFrames.clock) { + fsi.positions.clock = numframes; + normalFrames[numframes++] = uiconfig.is_clockface_analog ? graphics::ClockRenderer::drawAnalogClockFrame + : graphics::ClockRenderer::drawDigitalClockFrame; + indicatorIcons.push_back(digital_icon_clock); + } #endif #if HAS_WIFI && !defined(ARCH_PORTDUINO) - if (!dismissedFrames.wifi && isWifiAvailable()) { + if (!hiddenFrames.wifi && isWifiAvailable()) { fsi.positions.wifi = numframes; normalFrames[numframes++] = graphics::DebugRenderer::drawDebugInfoWiFiTrampoline; indicatorIcons.push_back(icon_wifi); @@ -988,27 +1003,29 @@ void Screen::setFrames(FrameFocus focus) if (numMeshNodes > 0) numMeshNodes--; - // Temporary array to hold favorite node frames - std::vector favoriteFrames; + if (!hiddenFrames.show_favorites) { + // Temporary array to hold favorite node frames + std::vector favoriteFrames; - for (size_t i = 0; i < nodeDB->getNumMeshNodes(); i++) { - const meshtastic_NodeInfoLite *n = nodeDB->getMeshNodeByIndex(i); - if (n && n->num != nodeDB->getNodeNum() && n->is_favorite) { - favoriteFrames.push_back(graphics::UIRenderer::drawNodeInfo); + for (size_t i = 0; i < nodeDB->getNumMeshNodes(); i++) { + const meshtastic_NodeInfoLite *n = nodeDB->getMeshNodeByIndex(i); + if (n && n->num != nodeDB->getNodeNum() && n->is_favorite) { + favoriteFrames.push_back(graphics::UIRenderer::drawNodeInfo); + } } - } - // Insert favorite frames *after* collecting them all - if (!favoriteFrames.empty()) { - fsi.positions.firstFavorite = numframes; - for (const auto &f : favoriteFrames) { - normalFrames[numframes++] = f; - indicatorIcons.push_back(icon_node); + // Insert favorite frames *after* collecting them all + if (!favoriteFrames.empty()) { + fsi.positions.firstFavorite = numframes; + for (const auto &f : favoriteFrames) { + normalFrames[numframes++] = f; + indicatorIcons.push_back(icon_node); + } + fsi.positions.lastFavorite = numframes - 1; + } else { + fsi.positions.firstFavorite = 255; + fsi.positions.lastFavorite = 255; } - fsi.positions.lastFavorite = numframes - 1; - } else { - fsi.positions.firstFavorite = 255; - fsi.positions.lastFavorite = 255; } fsi.frameCount = numframes; // Total framecount is used to apply FOCUS_PRESERVE @@ -1047,7 +1064,7 @@ void Screen::setFrames(FrameFocus focus) ui->switchToFrame(fsi.positions.clock); break; case FOCUS_SYSTEM: - ui->switchToFrame(fsi.positions.memory); + ui->switchToFrame(fsi.positions.system); break; case FOCUS_PRESERVE: @@ -1075,30 +1092,96 @@ void Screen::setFrameImmediateDraw(FrameCallback *drawFrames) setFastFramerate(); } +void Screen::toggleFrameVisibility(const std::string &frameName) +{ +#ifndef USE_EINK + if (frameName == "nodelist") { + hiddenFrames.nodelist = !hiddenFrames.nodelist; + } +#endif +#ifdef USE_EINK + if (frameName == "nodelist_lastheard") { + hiddenFrames.nodelist_lastheard = !hiddenFrames.nodelist_lastheard; + } + if (frameName == "nodelist_hopsignal") { + hiddenFrames.nodelist_hopsignal = !hiddenFrames.nodelist_hopsignal; + } + if (frameName == "nodelist_distance") { + hiddenFrames.nodelist_distance = !hiddenFrames.nodelist_distance; + } +#endif +#if HAS_GPS + if (frameName == "nodelist_bearings") { + hiddenFrames.nodelist_bearings = !hiddenFrames.nodelist_bearings; + } + if (frameName == "gps") { + hiddenFrames.gps = !hiddenFrames.gps; + } +#endif + if (frameName == "lora") { + hiddenFrames.lora = !hiddenFrames.lora; + } + if (frameName == "clock") { + hiddenFrames.clock = !hiddenFrames.clock; + } + if (frameName == "show_favorites") { + hiddenFrames.show_favorites = !hiddenFrames.show_favorites; + } +} + +bool Screen::isFrameHidden(const std::string &frameName) const +{ +#ifndef USE_EINK + if (frameName == "nodelist") + return hiddenFrames.nodelist; +#endif +#ifdef USE_EINK + if (frameName == "nodelist_lastheard") + return hiddenFrames.nodelist_lastheard; + if (frameName == "nodelist_hopsignal") + return hiddenFrames.nodelist_hopsignal; + if (frameName == "nodelist_distance") + return hiddenFrames.nodelist_distance; +#endif +#if HAS_GPS + if (frameName == "nodelist_bearings") + return hiddenFrames.nodelist_bearings; + if (frameName == "gps") + return hiddenFrames.gps; +#endif + if (frameName == "lora") + return hiddenFrames.lora; + if (frameName == "clock") + return hiddenFrames.clock; + if (frameName == "show_favorites") + return hiddenFrames.show_favorites; + + return false; +} + // Dismisses the currently displayed screen frame, if possible // Relevant for text message, waypoint, others in future? // Triggered with a CardKB keycombo -void Screen::dismissCurrentFrame() +void Screen::hideCurrentFrame() { uint8_t currentFrame = ui->getUiState()->currentFrame; bool dismissed = false; - if (currentFrame == framesetInfo.positions.textMessage && devicestate.has_rx_text_message) { - LOG_INFO("Dismiss Text Message"); + LOG_INFO("Hide Text Message"); devicestate.has_rx_text_message = false; memset(&devicestate.rx_text_message, 0, sizeof(devicestate.rx_text_message)); } else if (currentFrame == framesetInfo.positions.waypoint && devicestate.has_rx_waypoint) { - LOG_DEBUG("Dismiss Waypoint"); + LOG_DEBUG("Hide Waypoint"); devicestate.has_rx_waypoint = false; - dismissedFrames.waypoint = true; + hiddenFrames.waypoint = true; dismissed = true; } else if (currentFrame == framesetInfo.positions.wifi) { - LOG_DEBUG("Dismiss WiFi Screen"); - dismissedFrames.wifi = true; + LOG_DEBUG("Hide WiFi Screen"); + hiddenFrames.wifi = true; dismissed = true; - } else if (currentFrame == framesetInfo.positions.memory) { - LOG_INFO("Dismiss Memory"); - dismissedFrames.memory = true; + } else if (currentFrame == framesetInfo.positions.lora) { + LOG_INFO("Hide LoRa"); + hiddenFrames.lora = true; dismissed = true; } @@ -1250,7 +1333,7 @@ int Screen::handleTextMessage(const meshtastic_MeshPacket *packet) // Outgoing message (likely sent from phone) devicestate.has_rx_text_message = false; memset(&devicestate.rx_text_message, 0, sizeof(devicestate.rx_text_message)); - dismissedFrames.textMessage = true; + hiddenFrames.textMessage = true; hasUnreadMessage = false; // Clear unread state when user replies setFrames(FOCUS_PRESERVE); // Stay on same frame, silently update frame list @@ -1366,7 +1449,7 @@ int Screen::handleInputEvent(const InputEvent *event) } else if (event->inputEvent == INPUT_BROKER_SELECT) { if (this->ui->getUiState()->currentFrame == framesetInfo.positions.home) { menuHandler::homeBaseMenu(); - } else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.memory) { + } else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.system) { menuHandler::systemBaseMenu(); #if HAS_GPS } else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.gps && gps) { @@ -1375,7 +1458,7 @@ int Screen::handleInputEvent(const InputEvent *event) } else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.clock) { menuHandler::clockMenu(); } else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.lora) { - menuHandler::LoraRegionPicker(); + menuHandler::loraMenu(); } else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.textMessage) { if (devicestate.rx_text_message.from) { menuHandler::messageResponseMenu(); diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 265900131..2209fd3f4 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -591,7 +591,11 @@ class Screen : public concurrency::OSThread void setSSLFrames(); // Dismiss the currently focussed frame, if possible (e.g. text message, waypoint) - void dismissCurrentFrame(); + void hideCurrentFrame(); + + // Menu-driven Show / Hide Toggle + void toggleFrameVisibility(const std::string &frameName); + bool isFrameHidden(const std::string &frameName) const; #ifdef USE_EINK /// Draw an image to remain on E-Ink display after screen off @@ -653,7 +657,7 @@ class Screen : public concurrency::OSThread uint8_t settings = 255; uint8_t wifi = 255; uint8_t deviceFocused = 255; - uint8_t memory = 255; + uint8_t system = 255; uint8_t gps = 255; uint8_t home = 255; uint8_t textMessage = 255; @@ -671,12 +675,28 @@ class Screen : public concurrency::OSThread uint8_t frameCount = 0; } framesetInfo; - struct DismissedFrames { + struct hiddenFrames { bool textMessage = false; bool waypoint = false; bool wifi = false; - bool memory = false; - } dismissedFrames; + bool system = false; + bool home = false; + bool clock = false; +#ifndef USE_EINK + bool nodelist = false; +#endif +#ifdef USE_EINK + bool nodelist_lastheard = false; + bool nodelist_hopsignal = false; + bool nodelist_distance = false; +#endif +#if HAS_GPS + bool nodelist_bearings = false; + bool gps = false; +#endif + bool lora = false; + bool show_favorites = false; + } hiddenFrames; /// Try to start drawing ASAP void setFastFramerate(); diff --git a/src/graphics/draw/DebugRenderer.cpp b/src/graphics/draw/DebugRenderer.cpp index 5d9b5a33b..426d5b47f 100644 --- a/src/graphics/draw/DebugRenderer.cpp +++ b/src/graphics/draw/DebugRenderer.cpp @@ -485,7 +485,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, // **************************** // * System Screen * // **************************** -void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { display->clear(); display->setFont(FONT_SMALL); diff --git a/src/graphics/draw/DebugRenderer.h b/src/graphics/draw/DebugRenderer.h index f4d484f58..3382e931d 100644 --- a/src/graphics/draw/DebugRenderer.h +++ b/src/graphics/draw/DebugRenderer.h @@ -31,8 +31,8 @@ void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state // LoRa information display void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); -// Memory screen display -void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); +// System screen display +void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); } // namespace DebugRenderer } // namespace graphics diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index cf19c4825..9fa2bd612 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -24,6 +24,24 @@ menuHandler::screenMenus menuHandler::menuQueue = menu_none; bool test_enabled = false; uint8_t test_count = 0; +void menuHandler::loraMenu() +{ + static const char *optionsArray[] = {"Back", "Region Picker"}; + enum optionsNumbers { Back = 0, lora_picker = 1 }; + BannerOverlayOptions bannerOptions; + bannerOptions.message = "LoRa Actions"; + bannerOptions.optionsArrayPtr = optionsArray; + bannerOptions.optionsCount = 2; + bannerOptions.bannerCallback = [](int selected) -> void { + if (selected == Back) { + // No action + } else if (selected == lora_picker) { + menuHandler::menuQueue = menuHandler::lora_picker; + } + }; + screen->showOverlayBanner(bannerOptions); +} + void menuHandler::LoraRegionPicker(uint32_t duration) { static const char *optionsArray[] = {"Back", @@ -266,7 +284,7 @@ void menuHandler::messageResponseMenu() bannerOptions.optionsCount = options; bannerOptions.bannerCallback = [](int selected) -> void { if (selected == Dismiss) { - screen->dismissCurrentFrame(); + screen->hideCurrentFrame(); } else if (selected == Preset) { if (devicestate.rx_text_message.to == NODENUM_BROADCAST) { cannedMessageModule->LaunchWithDestination(NODENUM_BROADCAST, devicestate.rx_text_message.channel); @@ -381,7 +399,7 @@ void menuHandler::textMessageBaseMenu() void menuHandler::systemBaseMenu() { - enum optionsNumbers { Back, Notifications, ScreenOptions, PowerMenu, Test, enumEnd }; + enum optionsNumbers { Back, Notifications, ScreenOptions, PowerMenu, FrameToggles, Test, enumEnd }; static const char *optionsArray[enumEnd] = {"Back"}; static int optionsEnumArray[enumEnd] = {Back}; int options = 1; @@ -394,6 +412,9 @@ void menuHandler::systemBaseMenu() optionsEnumArray[options++] = ScreenOptions; #endif + optionsArray[options] = "Frame Visiblity Toggle"; + optionsEnumArray[options++] = FrameToggles; + optionsArray[options] = "Reboot/Shutdown"; optionsEnumArray[options++] = PowerMenu; @@ -417,6 +438,9 @@ void menuHandler::systemBaseMenu() } else if (selected == PowerMenu) { menuHandler::menuQueue = menuHandler::power_menu; screen->runNow(); + } else if (selected == FrameToggles) { + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); } else if (selected == Test) { menuHandler::menuQueue = menuHandler::test_menu; screen->runNow(); @@ -480,6 +504,7 @@ void menuHandler::positionBaseMenu() optionsArray[options] = "Compass Calibrate"; optionsEnumArray[options++] = CompassCalibrate; } + BannerOverlayOptions bannerOptions; bannerOptions.message = "Position Action"; bannerOptions.optionsArrayPtr = optionsArray; @@ -1091,6 +1116,116 @@ void menuHandler::keyVerificationFinalPrompt() } } +void menuHandler::FrameToggles_menu() +{ + enum optionsNumbers { + Finish, + nodelist, + nodelist_lastheard, + nodelist_hopsignal, + nodelist_distance, + nodelist_bearings, + gps, + lora, + clock, + show_favorites, + enumEnd + }; + static const char *optionsArray[enumEnd] = {"Finish"}; + static int optionsEnumArray[enumEnd] = {Finish}; + int options = 1; + + // Track last selected index (not enum value!) + static int lastSelectedIndex = 0; + +#ifndef USE_EINK + optionsArray[options] = screen->isFrameHidden("nodelist") ? "Show Node List" : "Hide Node List"; + optionsEnumArray[options++] = nodelist; +#endif +#ifdef USE_EINK + optionsArray[options] = screen->isFrameHidden("nodelist_lastheard") ? "Show NL - Last Heard" : "Hide NL - Last Heard"; + optionsEnumArray[options++] = nodelist_lastheard; + optionsArray[options] = screen->isFrameHidden("nodelist_hopsignal") ? "Show NL - Hops/Signal" : "Hide NL - Hops/Signal"; + optionsEnumArray[options++] = nodelist_hopsignal; + optionsArray[options] = screen->isFrameHidden("nodelist_distance") ? "Show NL - Distance" : "Hide NL - Distance"; + optionsEnumArray[options++] = nodelist_distance; +#endif +#if HAS_GPS + optionsArray[options] = screen->isFrameHidden("nodelist_bearings") ? "Show Bearings" : "Hide Bearings"; + optionsEnumArray[options++] = nodelist_bearings; + + optionsArray[options] = screen->isFrameHidden("gps") ? "Show Position" : "Hide Position"; + optionsEnumArray[options++] = gps; + + optionsArray[options] = screen->isFrameHidden("lora") ? "Show LoRa" : "Hide LoRa"; + optionsEnumArray[options++] = lora; + + optionsArray[options] = screen->isFrameHidden("clock") ? "Show Clock" : "Hide Clock"; + optionsEnumArray[options++] = clock; + + optionsArray[options] = screen->isFrameHidden("show_favorites") ? "Show Favorites" : "Hide Favorites"; + optionsEnumArray[options++] = show_favorites; +#endif + + BannerOverlayOptions bannerOptions; + bannerOptions.message = "Show/Hide Frames"; + bannerOptions.optionsArrayPtr = optionsArray; + bannerOptions.optionsCount = options; + bannerOptions.optionsEnumPtr = optionsEnumArray; + bannerOptions.InitialSelected = lastSelectedIndex; // Use index, not enum value + + bannerOptions.bannerCallback = [optionsEnumArray, options](int selected) mutable -> void { + // Find the index of selected in optionsEnumArray + int idx = 0; + for (; idx < options; ++idx) { + if (optionsEnumArray[idx] == selected) + break; + } + lastSelectedIndex = idx; + + if (selected == Finish) { + screen->setFrames(Screen::FOCUS_DEFAULT); + } else if (selected == nodelist) { + screen->toggleFrameVisibility("nodelist"); + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); + } else if (selected == nodelist_lastheard) { + screen->toggleFrameVisibility("nodelist_lastheard"); + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); + } else if (selected == nodelist_hopsignal) { + screen->toggleFrameVisibility("nodelist_hopsignal"); + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); + } else if (selected == nodelist_distance) { + screen->toggleFrameVisibility("nodelist_distance"); + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); + } else if (selected == nodelist_bearings) { + screen->toggleFrameVisibility("nodelist_bearings"); + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); + } else if (selected == gps) { + screen->toggleFrameVisibility("gps"); + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); + } else if (selected == lora) { + screen->toggleFrameVisibility("lora"); + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); + } else if (selected == clock) { + screen->toggleFrameVisibility("clock"); + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); + } else if (selected == show_favorites) { + screen->toggleFrameVisibility("show_favorites"); + menuHandler::menuQueue = menuHandler::FrameToggles; + screen->runNow(); + } + }; + screen->showOverlayBanner(bannerOptions); +} + void menuHandler::handleMenuSwitch(OLEDDisplay *display) { if (menuQueue != menu_none) @@ -1184,6 +1319,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display) case power_menu: powerMenu(); break; + case FrameToggles: + FrameToggles_menu(); + break; case throttle_message: screen->showSimpleBanner("Too Many Attempts\nTry again in 60 seconds.", 5000); break; diff --git a/src/graphics/draw/MenuHandler.h b/src/graphics/draw/MenuHandler.h index 2e4923241..7f069493b 100644 --- a/src/graphics/draw/MenuHandler.h +++ b/src/graphics/draw/MenuHandler.h @@ -38,10 +38,12 @@ class menuHandler key_verification_final_prompt, trace_route_menu, throttle_message, + FrameToggles }; static screenMenus menuQueue; static void LoraRegionPicker(uint32_t duration = 30000); + static void loraMenu(); static void handleMenuSwitch(OLEDDisplay *display); static void clockMenu(); static void TZPicker(); @@ -73,6 +75,7 @@ class menuHandler static void notificationsMenu(); static void screenOptionsMenu(); static void powerMenu(); + static void FrameToggles_menu(); private: static void saveUIConfig(); diff --git a/src/graphics/images.h b/src/graphics/images.h index beef3a1b2..a43ef6223 100644 --- a/src/graphics/images.h +++ b/src/graphics/images.h @@ -117,8 +117,8 @@ const uint8_t icon_radio[] PROGMEM = { 0xA9 // Row 7: #..#.#.# }; -// 🪙 Memory Icon -const uint8_t icon_memory[] PROGMEM = { +// 🪙 System Icon +const uint8_t icon_system[] PROGMEM = { 0x24, // Row 0: ..#..#.. 0x3C, // Row 1: ..####.. 0xC3, // Row 2: ##....##