Clean up after Copilot

This commit is contained in:
Jonathan Bennett 2025-06-01 22:47:44 -05:00
parent 8cdb34a299
commit 6f6ee8c06a
6 changed files with 97 additions and 120 deletions

View File

@ -95,11 +95,6 @@ namespace graphics
FrameCallback *normalFrames;
static uint32_t targetFramerate = IDLE_FRAMERATE;
// Global variables for alert banner - explicitly define with extern "C" linkage to prevent optimization
extern "C" {
static char alertBannerBuffer[256] = "";
char *alertBannerMessage = alertBannerBuffer;
uint32_t alertBannerUntil = 0;
}
uint32_t logo_timeout = 5000; // 4 seconds for EACH logo
@ -117,12 +112,6 @@ std::vector<MeshModule *> moduleFrames;
std::vector<std::string> functionSymbol;
std::string functionSymbolString;
// Stores the last 4 of our hardware ID, to make finding the device for pairing easier
// FIXME: Needs refactoring and getMacAddr needs to be moved to a utility class
extern "C" {
char ourId[5];
}
#if HAS_GPS
// GeoCoord object for the screen
GeoCoord geoCoord;
@ -1006,7 +995,7 @@ void Screen::setup()
// === Generate device ID from MAC address ===
uint8_t dmac[6];
getMacAddr(dmac);
snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
snprintf(screen->ourId, sizeof(screen->ourId), "%02x%02x", dmac[4], dmac[5]);
#if ARCH_PORTDUINO
handleSetOn(false); // Ensure proper init for Arduino targets

View File

@ -220,6 +220,13 @@ class Screen : public concurrency::OSThread
meshtastic_Config_DisplayConfig_OledType model;
OLEDDISPLAY_GEOMETRY geometry;
char alertBannerMessage[256] = {0};
uint32_t alertBannerUntil = 0;
// Stores the last 4 of our hardware ID, to make finding the device for pairing easier
// FIXME: Needs refactoring and getMacAddr needs to be moved to a utility class
char ourId[5];
/// Initializes the UI, turns on the display, starts showing boot screen.
//
// Not thread safe - must be called before any other methods are called.
@ -698,11 +705,6 @@ class Screen : public concurrency::OSThread
} // namespace graphics
extern "C" {
extern char *alertBannerMessage;
extern uint32_t alertBannerUntil;
}
// Extern declarations for function symbols used in UIRenderer
extern std::vector<std::string> functionSymbol;
extern std::string functionSymbolString;

View File

@ -41,9 +41,6 @@ extern PowerStatus *powerStatus;
extern NodeStatus *nodeStatus;
extern GPSStatus *gpsStatus;
extern Channels channels;
extern "C" {
extern char ourId[5];
}
extern AirTime *airTime;
// External functions from Screen.cpp
@ -116,25 +113,25 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL1);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL2);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12,
8, imgQuestionL1);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 11 + FONT_HEIGHT_SMALL, 12,
8, imgQuestionL2);
#else
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8,
imgQuestion);
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(screen->ourId), y + 2 + FONT_HEIGHT_SMALL, 8,
8, imgQuestion);
#endif
} else {
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
imgSFL1);
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8,
imgSFL2);
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 16,
8, imgSFL1);
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(screen->ourId), y + 11 + FONT_HEIGHT_SMALL, 16,
8, imgSFL2);
#else
display->drawFastImage(x + SCREEN_WIDTH - 13 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 11, 8,
imgSF);
display->drawFastImage(x + SCREEN_WIDTH - 13 - display->getStringWidth(screen->ourId), y + 2 + FONT_HEIGHT_SMALL, 11,
8, imgSF);
#endif
}
#endif
@ -143,16 +140,17 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL1);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL2);
#else
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(screen->ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8,
imgInfo);
#endif
}
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT_SMALL, ourId);
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(screen->ourId), y + FONT_HEIGHT_SMALL, screen->ourId);
// Draw any log messages
display->drawLogBuffer(x, y + (FONT_HEIGHT_SMALL * 2));
@ -427,8 +425,8 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
uint8_t dmac[6];
char shortnameble[35];
getMacAddr(dmac);
snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
snprintf(shortnameble, sizeof(shortnameble), "BLE: %s", ourId);
snprintf(screen->ourId, sizeof(screen->ourId), "%02x%02x", dmac[4], dmac[5]);
snprintf(shortnameble, sizeof(shortnameble), "BLE: %s", screen->ourId);
int textWidth = display->getStringWidth(shortnameble);
int nameX = (SCREEN_WIDTH - textWidth);
display->drawString(nameX, compactFirstLine, shortnameble);

View File

@ -76,7 +76,7 @@ void NotificationRenderer::drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUi
void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
{
// Exit if no message is active or duration has passed
if (strlen(alertBannerMessage) == 0 || (alertBannerUntil != 0 && millis() > alertBannerUntil))
if (strlen(screen->alertBannerMessage) == 0 || (screen->alertBannerUntil != 0 && millis() > screen->alertBannerUntil))
return;
// === Layout Configuration ===
@ -84,45 +84,38 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
constexpr uint8_t lineSpacing = 1; // Extra space between lines
// Search the message to determine if we need the bell added
bool needs_bell = (strstr(alertBannerMessage, "Alert Received") != nullptr);
bool needs_bell = (strstr(screen->alertBannerMessage, "Alert Received") != nullptr);
// Setup font and alignment
display->setFont(FONT_SMALL);
display->setTextAlignment(TEXT_ALIGN_LEFT); // We will manually center per line
// === Split the message into lines (supports multi-line banners) ===
const int MAX_LINES = 10;
char lines[MAX_LINES][256];
int lineCount = 0;
// Create a working copy of the message to tokenize
char messageCopy[256];
strncpy(messageCopy, alertBannerMessage, sizeof(messageCopy) - 1);
messageCopy[sizeof(messageCopy) - 1] = '\0';
char *line = strtok(messageCopy, "\n");
while (line != nullptr && lineCount < MAX_LINES) {
strncpy(lines[lineCount], line, sizeof(lines[lineCount]) - 1);
lines[lineCount][sizeof(lines[lineCount]) - 1] = '\0';
lineCount++;
line = strtok(nullptr, "\n");
}
// === Measure text dimensions ===
uint16_t minWidth = (SCREEN_WIDTH > 128) ? 106 : 78;
uint16_t maxWidth = 0;
uint16_t lineWidths[MAX_LINES];
for (int i = 0; i < lineCount; i++) {
uint16_t w = display->getStringWidth(lines[i], strlen(lines[i]), true);
lineWidths[i] = w;
if (w > maxWidth)
maxWidth = w;
char *lineStarts[MAX_LINES];
uint16_t lineCount = 0;
char lineBuffer[40] = {0};
uint16_t alertLength = strnlen(screen->alertBannerMessage, sizeof(screen->alertBannerMessage));
lineStarts[lineCount] = screen->alertBannerMessage;
// loop through lines finding \n characters
while (lineCount < 10 && lineStarts[lineCount] != screen->alertBannerMessage + alertLength) {
lineStarts[lineCount + 1] = std::find(lineStarts[lineCount], screen->alertBannerMessage + alertLength, '\n');
lineWidths[lineCount] =
display->getStringWidth(lineStarts[lineCount], lineStarts[lineCount + 1] - lineStarts[lineCount], true);
if (lineWidths[lineCount] > maxWidth) {
maxWidth = lineWidths[lineCount];
}
lineCount++;
}
// set width from longest line
uint16_t boxWidth = padding * 2 + maxWidth;
if (needs_bell && boxWidth < minWidth)
if (needs_bell && boxWidth < (SCREEN_WIDTH > 128) ? 106 : 78)
boxWidth += (SCREEN_WIDTH > 128) ? 26 : 20;
// set height from line count
uint16_t boxHeight = padding * 2 + lineCount * FONT_HEIGHT_SMALL + (lineCount - 1) * lineSpacing;
int16_t boxLeft = (display->width() / 2) - (boxWidth / 2);
@ -137,18 +130,20 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
// === Draw each line centered in the box ===
int16_t lineY = boxTop + padding;
for (int i = 0; i < lineCount; i++) {
strncpy(lineBuffer, lineStarts[i], 40);
lineStarts[i][40] = '\0';
int16_t textX = boxLeft + (boxWidth - lineWidths[i]) / 2;
uint16_t line_width = display->getStringWidth(lines[i], strlen(lines[i]), true);
if (needs_bell && i == 0) {
int bellY = lineY + (FONT_HEIGHT_SMALL - 8) / 2;
display->drawXbm(textX - 10, bellY, 8, 8, bell_alert);
display->drawXbm(textX + line_width + 2, bellY, 8, 8, bell_alert);
display->drawXbm(textX + lineWidths[i] + 2, bellY, 8, 8, bell_alert);
}
display->drawString(textX, lineY, lines[i]);
display->drawString(textX, lineY, lineBuffer);
if (SCREEN_WIDTH > 128)
display->drawString(textX + 1, lineY, lines[i]); // Faux bold
display->drawString(textX + 1, lineY, lineBuffer); // Faux bold
lineY += FONT_HEIGHT_SMALL + lineSpacing;
}

View File

@ -21,9 +21,6 @@
// External variables
extern graphics::Screen *screen;
extern "C" {
extern char ourId[5];
}
namespace graphics
{
@ -669,7 +666,7 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
uint8_t dmac[6];
char shortnameble[35];
getMacAddr(dmac);
snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
snprintf(screen->ourId, sizeof(screen->ourId), "%02x%02x", dmac[4], dmac[5]);
snprintf(shortnameble, sizeof(shortnameble), "%s",
graphics::UIRenderer::haveGlyphs(owner.short_name) ? owner.short_name : "");

View File

@ -380,9 +380,8 @@ bool CannedMessageModule::handleTabSwitch(const InputEvent *event)
if (event->kbchar != 0x09)
return false;
runState = (runState == CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION)
? CANNED_MESSAGE_RUN_STATE_FREETEXT
: CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION;
runState = (runState == CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION) ? CANNED_MESSAGE_RUN_STATE_FREETEXT
: CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION;
destIndex = 0;
scrollIndex = 0;
@ -720,8 +719,8 @@ bool CannedMessageModule::handleSystemCommandInput(const InputEvent *event)
if (event->inputEvent != static_cast<char>(ANYKEY))
return false;
// Block ALL input if an alert banner is active
if (strlen(alertBannerMessage) > 0 && (alertBannerUntil == 0 || millis() <= alertBannerUntil)) {
// Block ALL input if an alert banner is active // TODO: Make an accessor function
if (strlen(screen->alertBannerMessage) > 0 && (screen->alertBannerUntil == 0 || millis() <= screen->alertBannerUntil)) {
return true;
}
@ -890,8 +889,7 @@ int32_t CannedMessageModule::runOnce()
// Normal module disable/idle handling
if (((!moduleConfig.canned_message.enabled) && !CANNED_MESSAGE_MODULE_ENABLE) ||
(this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) ||
(this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) {
(this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) || (this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) {
temporaryMessage = "";
return INT32_MAX;
}
@ -906,25 +904,23 @@ int32_t CannedMessageModule::runOnce()
this->currentMessageIndex = -1;
this->freetext = "";
this->cursor = 0;
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(SENSECAP_INDICATOR)
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(SENSECAP_INDICATOR)
int destSelect = 0;
#endif
#endif
this->notifyObservers(&e);
}
else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) &&
!Throttle::isWithinTimespanMs(this->lastTouchMillis, INACTIVATE_AFTER_MS)) {
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) &&
!Throttle::isWithinTimespanMs(this->lastTouchMillis, INACTIVATE_AFTER_MS)) {
// Reset module on inactivity
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
this->currentMessageIndex = -1;
this->freetext = "";
this->cursor = 0;
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
int destSelect = 0;
#endif
#endif
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
this->notifyObservers(&e);
}
else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
if (this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
if (this->freetext.length() > 0) {
sendText(this->dest, this->channel, this->freetext.c_str(), true);
@ -969,8 +965,7 @@ int32_t CannedMessageModule::runOnce()
this->currentMessageIndex = firstRealMsgIdx;
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
}
else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_UP) {
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_UP) {
if (this->messagesCount > 0) {
this->currentMessageIndex = getPrevIndex();
this->freetext = "";
@ -978,8 +973,7 @@ int32_t CannedMessageModule::runOnce()
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
LOG_DEBUG("MOVE UP (%d):%s", this->currentMessageIndex, this->getCurrentMessage());
}
}
else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_DOWN) {
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_DOWN) {
if (this->messagesCount > 0) {
this->currentMessageIndex = this->getNextIndex();
this->freetext = "";
@ -987,8 +981,7 @@ int32_t CannedMessageModule::runOnce()
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
LOG_DEBUG("MOVE DOWN (%d):%s", this->currentMessageIndex, this->getCurrentMessage());
}
}
else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT || this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) {
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT || this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) {
switch (this->payload) {
case INPUT_BROKER_MSG_LEFT:
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT && this->cursor > 0) {
@ -1012,7 +1005,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = this->freetext.substring(0, this->freetext.length() - 1);
} else {
this->freetext = this->freetext.substring(0, this->cursor - 1) +
this->freetext.substring(this->cursor, this->freetext.length());
this->freetext.substring(this->cursor, this->freetext.length());
}
this->cursor--;
}
@ -1023,11 +1016,13 @@ int32_t CannedMessageModule::runOnce()
case INPUT_BROKER_MSG_RIGHT:
break;
default:
if (this->highlight != 0x00) break;
if (this->highlight != 0x00)
break;
if (this->cursor == this->freetext.length()) {
this->freetext += this->payload;
} else {
this->freetext = this->freetext.substring(0, this->cursor) + this->payload + this->freetext.substring(this->cursor);
this->freetext =
this->freetext.substring(0, this->cursor) + this->payload + this->freetext.substring(this->cursor);
}
this->cursor += 1;
uint16_t maxChars = meshtastic_Constants_DATA_PAYLOAD_LEN - (moduleConfig.canned_message.send_bell ? 1 : 0);
@ -1346,7 +1341,8 @@ bool CannedMessageModule::interceptingKeyboardInput()
}
// Draw the node/channel selection screen
void CannedMessageModule::drawDestinationSelectionScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
void CannedMessageModule::drawDestinationSelectionScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
requestFocus();
display->setColor(WHITE); // Always draw cleanly
display->setTextAlignment(TEXT_ALIGN_LEFT);
@ -1380,32 +1376,32 @@ void CannedMessageModule::drawDestinationSelectionScreen(OLEDDisplay *display, O
if (itemIndex >= totalEntries)
break;
int xOffset = 0;
int yOffset = row * (FONT_HEIGHT_SMALL - 4) + rowYOffset;
char entryText[64];
int xOffset = 0;
int yOffset = row * (FONT_HEIGHT_SMALL - 4) + rowYOffset;
char entryText[64];
// Draw Channels First
if (itemIndex < numActiveChannels) {
uint8_t channelIndex = this->activeChannelIndices[itemIndex];
snprintf(entryText, sizeof(entryText), "@%s", channels.getName(channelIndex));
}
// Then Draw Nodes
else {
int nodeIndex = itemIndex - numActiveChannels;
if (nodeIndex >= 0 && nodeIndex < static_cast<int>(this->filteredNodes.size())) {
meshtastic_NodeInfoLite *node = this->filteredNodes[nodeIndex].node;
if (node) {
if (node->is_favorite) {
snprintf(entryText, sizeof(entryText), "* %s", node->user.long_name);
} else {
snprintf(entryText, sizeof(entryText), "%s", node->user.long_name);
}
// Draw Channels First
if (itemIndex < numActiveChannels) {
uint8_t channelIndex = this->activeChannelIndices[itemIndex];
snprintf(entryText, sizeof(entryText), "@%s", channels.getName(channelIndex));
}
// Then Draw Nodes
else {
int nodeIndex = itemIndex - numActiveChannels;
if (nodeIndex >= 0 && nodeIndex < static_cast<int>(this->filteredNodes.size())) {
meshtastic_NodeInfoLite *node = this->filteredNodes[nodeIndex].node;
if (node) {
if (node->is_favorite) {
snprintf(entryText, sizeof(entryText), "* %s", node->user.long_name);
} else {
snprintf(entryText, sizeof(entryText), "%s", node->user.long_name);
}
}
}
}
if (strlen(entryText) == 0 || strcmp(entryText, "Unknown") == 0)
strcpy(entryText, "?");
if (strlen(entryText) == 0 || strcmp(entryText, "Unknown") == 0)
strcpy(entryText, "?");
// === Highlight background (if selected) ===
if (itemIndex == destIndex) {