From 0b270c0e1a48bde3722c0331f85fcfa555af6e5a Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Sun, 1 Feb 2026 19:38:26 +1100 Subject: [PATCH] "Changed word wrapping in channel view screen to boundary wrapping" --- examples/companion_radio/main.cpp | 29 +++++++++-- .../companion_radio/ui-new/ChannelScreen.h | 51 ++++++++++--------- examples/companion_radio/ui-new/UITask.cpp | 9 ++++ examples/companion_radio/ui-new/UITask.h | 3 ++ 4 files changed, 63 insertions(+), 29 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 82e55d58..78bb873b 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -14,6 +14,9 @@ static char composeBuffer[138]; // 137 chars max + null terminator static int composePos = 0; static uint8_t composeChannelIdx = 0; // Which channel to send to + static unsigned long lastComposeRefresh = 0; + static bool composeNeedsRefresh = false; + #define COMPOSE_REFRESH_INTERVAL 250 // ms between e-ink refreshes while typing void initKeyboard(); void handleKeyboardInput(); @@ -345,6 +348,13 @@ void loop() { #if defined(LilyGo_TDeck_Pro) if (!composeMode) { ui_task.loop(); + } else { + // Handle debounced compose screen refresh + if (composeNeedsRefresh && (millis() - lastComposeRefresh) >= COMPOSE_REFRESH_INTERVAL) { + drawComposeScreen(); + lastComposeRefresh = millis(); + composeNeedsRefresh = false; + } } #else ui_task.loop(); @@ -371,6 +381,8 @@ void initKeyboard() { composeBuffer[0] = '\0'; composePos = 0; composeMode = false; + composeNeedsRefresh = false; + lastComposeRefresh = 0; } else { MESH_DEBUG_PRINTLN("setup() - Keyboard initialization failed!"); } @@ -416,7 +428,7 @@ void handleKeyboardInput() { composePos--; composeBuffer[composePos] = '\0'; Serial.printf("Compose: Backspace, pos now %d\n", composePos); - drawComposeScreen(); + composeNeedsRefresh = true; // Use debounced refresh } return; } @@ -460,7 +472,7 @@ void handleKeyboardInput() { composeBuffer[composePos++] = key; composeBuffer[composePos] = '\0'; Serial.printf("Compose: Added '%c', pos now %d\n", key, composePos); - drawComposeScreen(); + composeNeedsRefresh = true; // Use debounced refresh } return; } @@ -581,10 +593,13 @@ void drawComposeScreen() { display.setCursor(0, 14); display.setColor(DisplayDriver::LIGHT); - // Word wrap the compose buffer + // Word wrap the compose buffer - calculate chars per line based on actual font width int x = 0; int y = 14; - int charsPerLine = display.width() / 6; + uint16_t testWidth = display.getTextWidth("MMMMMMMMMM"); // 10 wide chars + int charsPerLine = (testWidth > 0) ? (display.width() * 10) / testWidth : 20; + if (charsPerLine < 12) charsPerLine = 12; + if (charsPerLine > 40) charsPerLine = 40; char charStr[2] = {0, 0}; // Buffer for single character as string for (int i = 0; i < composePos; i++) { @@ -643,6 +658,12 @@ void sendComposedMessage() { the_mesh.getNodePrefs()->node_name, composeBuffer, composePos)) { MESH_DEBUG_PRINTLN("Message sent to channel %s", channel.name); + + // Add the sent message to local channel history so we can see what we sent + ui_task.addSentChannelMessage(composeChannelIdx, + the_mesh.getNodePrefs()->node_name, + composeBuffer); + ui_task.showAlert("Sent!", 1500); } else { MESH_DEBUG_PRINTLN("Failed to send message"); diff --git a/examples/companion_radio/ui-new/ChannelScreen.h b/examples/companion_radio/ui-new/ChannelScreen.h index 75620327..fd0a1291 100644 --- a/examples/companion_radio/ui-new/ChannelScreen.h +++ b/examples/companion_radio/ui-new/ChannelScreen.h @@ -126,8 +126,12 @@ public: int headerHeight = 14; int footerHeight = 14; - // Calculate chars per line based on display width - int charsPerLine = display.width() / 6; + // Calculate chars per line based on actual font width (not assumed 6px) + // Measure a test string and scale accordingly + uint16_t testWidth = display.getTextWidth("MMMMMMMMMM"); // 10 wide chars + int charsPerLine = (testWidth > 0) ? (display.width() * 10) / testWidth : 20; + if (charsPerLine < 12) charsPerLine = 12; // Minimum reasonable + if (charsPerLine > 40) charsPerLine = 40; // Maximum reasonable int y = headerHeight; @@ -168,40 +172,37 @@ public: display.print(tmp); y += lineHeight; - // Message text with word wrap + // Message text with character wrapping (like compose screen - fills full width) display.setColor(DisplayDriver::LIGHT); int textLen = strlen(msg->text); int pos = 0; int linesForThisMsg = 0; - int maxLinesPerMsg = 3; + int maxLinesPerMsg = 6; // Allow more lines per message + int x = 0; + char charStr[2] = {0, 0}; + + display.setCursor(0, y); while (pos < textLen && linesForThisMsg < maxLinesPerMsg && y < display.height() - footerHeight - 2) { - display.setCursor(0, y); + charStr[0] = msg->text[pos]; + display.print(charStr); + x++; + pos++; - int lineEnd = pos + charsPerLine; - if (lineEnd >= textLen) { - lineEnd = textLen; - } else { - int lastSpace = -1; - for (int j = pos; j < lineEnd && j < textLen; j++) { - if (msg->text[j] == ' ') lastSpace = j; + if (x >= charsPerLine) { + x = 0; + linesForThisMsg++; + y += lineHeight; + if (linesForThisMsg < maxLinesPerMsg && y < display.height() - footerHeight - 2) { + display.setCursor(0, y); } - if (lastSpace > pos) lineEnd = lastSpace; } - - char lineBuf[42]; - int lineLen = lineEnd - pos; - if (lineLen > 40) lineLen = 40; - strncpy(lineBuf, msg->text + pos, lineLen); - lineBuf[lineLen] = '\0'; - display.print(lineBuf); - - pos = lineEnd; - while (pos < textLen && msg->text[pos] == ' ') pos++; - + } + + // If we didn't end on a full line, still count it + if (x > 0) { y += lineHeight; - linesForThisMsg++; } y += 2; diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 306e993d..ee0c42a6 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -966,4 +966,13 @@ void UITask::gotoChannelScreen() { uint8_t UITask::getChannelScreenViewIdx() const { return ((ChannelScreen *) channel_screen)->getViewChannelIdx(); +} + +void UITask::addSentChannelMessage(uint8_t channel_idx, const char* sender, const char* text) { + // Format the message as "Sender: message" + char formattedMsg[CHANNEL_MSG_TEXT_LEN]; + snprintf(formattedMsg, sizeof(formattedMsg), "%s: %s", sender, text); + + // Add to channel history with path_len=0 (local message) + ((ChannelScreen *) channel_screen)->addMessage(channel_idx, 0, sender, formattedMsg); } \ No newline at end of file diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index ac397142..0c354eb1 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -89,6 +89,9 @@ public: // Inject a key press from external source (e.g., keyboard) void injectKey(char c); + // Add a sent message to the channel screen history + void addSentChannelMessage(uint8_t channel_idx, const char* sender, const char* text); + // Get current screen for checking state UIScreen* getCurrentScreen() const { return curr; } UIScreen* getMsgPreviewScreen() const { return msg_preview; }