From 550c0796eb24d28ac3ec10b96b35a659805917d4 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Thu, 26 Jun 2025 13:03:52 -0500 Subject: [PATCH] More progress --- src/graphics/Screen.cpp | 18 ++++++++++++++++ src/graphics/Screen.h | 2 ++ src/graphics/draw/NotificationRenderer.cpp | 25 +++++++++++----------- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 731d1140f..3a19279e0 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -157,6 +157,24 @@ void Screen::showOverlayBanner(const char *message, uint32_t durationMs, const c ui->update(); } +// Called to trigger a banner with custom message and duration +void Screen::showNodePicker(const char *message, uint32_t durationMs, std::function bannerCallback) +{ +#ifdef USE_EINK + EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Skip full refresh for all overlay menus +#endif + // Store the message and set the expiration timestamp + strncpy(NotificationRenderer::alertBannerMessage, message, 255); + NotificationRenderer::alertBannerMessage[255] = '\0'; // Ensure null termination + NotificationRenderer::alertBannerUntil = (durationMs == 0) ? 0 : millis() + durationMs; + NotificationRenderer::alertBannerCallback = bannerCallback; + NotificationRenderer::pauseBanner = false; + static OverlayCallback overlays[] = {graphics::UIRenderer::drawNavigationBar, NotificationRenderer::drawAlertBannerOverlay}; + ui->setOverlays(overlays, sizeof(overlays) / sizeof(overlays[0])); + setFastFramerate(); // Draw ASAP + ui->update(); +} + static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { uint8_t module_frame; diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 870eea7fe..39230b3ed 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -291,6 +291,8 @@ class Screen : public concurrency::OSThread void showOverlayBanner(const char *message, uint32_t durationMs = 3000, const char **optionsArrayPtr = nullptr, uint8_t options = 0, std::function bannerCallback = NULL, int8_t InitialSelected = 0); + void showNodePicker(const char *message, uint32_t durationMs, std::function bannerCallback); + void startFirmwareUpdateScreen() { ScreenCmd cmd; diff --git a/src/graphics/draw/NotificationRenderer.cpp b/src/graphics/draw/NotificationRenderer.cpp index a9240ab56..fca5c0f6f 100644 --- a/src/graphics/draw/NotificationRenderer.cpp +++ b/src/graphics/draw/NotificationRenderer.cpp @@ -61,11 +61,7 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp return; // === Layout Configuration === - constexpr uint16_t hPadding = 5; constexpr uint16_t vPadding = 2; - constexpr uint8_t lineSpacing = 1; - - bool needs_bell = (strstr(alertBannerMessage, "Alert Received") != nullptr); // Setup font and alignment display->setFont(FONT_SMALL); @@ -137,6 +133,12 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp uint8_t effectiveLineHeight = FONT_HEIGHT_SMALL - 3; uint8_t visibleTotalLines = std::min(totalLines, (screenHeight - vPadding * 2) / effectiveLineHeight); uint8_t linesShown = lineCount; + const char *linePointers[visibleTotalLines]; // this is sort of a dynamic allocation + + // copy the linestarts to display to the linePointers holder + for (int i = 0; i < lineCount; i++) { + linePointers[i] = lineStarts[i]; + } uint8_t firstOptionToShow = 0; if (alertBannerOptions > 0) { @@ -156,19 +158,19 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp strncpy(lineBuffer + 2, optionsArrayPtr[i], 36); strncpy(lineBuffer + strlen(optionsArrayPtr[i]) + 2, " <", 3); lineBuffer[39] = '\0'; - lineStarts[linesShown] = lineBuffer; + linePointers[linesShown] = lineBuffer; } else { - lineStarts[linesShown] = optionsArrayPtr[i]; + linePointers[linesShown] = optionsArrayPtr[i]; } } if (alertBannerOptions > 0) { - drawNotificationBox(display, state, lineStarts, totalLines, firstOptionToShow, maxWidth); + drawNotificationBox(display, state, linePointers, totalLines, firstOptionToShow, maxWidth); } else { - drawNotificationBox(display, state, lineStarts, totalLines, firstOptionToShow); + drawNotificationBox(display, state, linePointers, totalLines, firstOptionToShow); } } -void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplayUiState *state, const char *lines[MAX_LINES + 1], +void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplayUiState *state, const char *lines[], uint16_t totalLines, uint8_t firstOptionToShow, uint16_t maxWidth) { bool is_picker = false; @@ -176,15 +178,14 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay // === Layout Configuration === constexpr uint16_t hPadding = 5; constexpr uint16_t vPadding = 2; - constexpr uint8_t lineSpacing = 1; bool needs_bell = false; - uint16_t lineWidths[MAX_LINES] = {0}; + uint16_t lineWidths[totalLines] = {0}; if (maxWidth != 0) is_picker = true; // seelction box - while (lineCount < MAX_LINES) { + while (lineCount < totalLines) { if (lines[lineCount] != nullptr) { lineWidths[lineCount] = display->getStringWidth(lines[lineCount], strlen(lines[lineCount]), true); if (!is_picker) {