diff --git a/examples/companion_radio/AbstractUITask.h b/examples/companion_radio/AbstractUITask.h index 7baeeff..fae82d1 100644 --- a/examples/companion_radio/AbstractUITask.h +++ b/examples/companion_radio/AbstractUITask.h @@ -45,4 +45,5 @@ public: virtual void loop() = 0; virtual void showAlert(const char* text, int duration_millis) {} virtual void forceRefresh() {} -}; + virtual void addSentChannelMessage(uint8_t channel_idx, const char* sender, const char* text) {} +}; \ No newline at end of file diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index ec3db4a..ccc7fe7 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -476,7 +476,7 @@ bool MyMesh::filterRecvFloodPacket(mesh::Packet* packet) { } } - return false; // never filter — let normal processing continue + return false; // never filter — let normal processing continue } void MyMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) { @@ -1088,6 +1088,12 @@ void MyMesh::handleCmdFrame(size_t len) { bool success = getChannel(channel_idx, channel); if (success && sendGroupMessage(msg_timestamp, channel.channel, _prefs.node_name, text, len - i)) { writeOKFrame(); +#ifdef DISPLAY_CLASS + // Show BLE-app-sent message on device channel screen + if (_ui) { + _ui->addSentChannelMessage(channel_idx, _prefs.node_name, text); + } +#endif } else { writeErrFrame(ERR_CODE_NOT_FOUND); // bad channel_idx } diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 84ab040..48c53dd 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -546,7 +546,7 @@ void handleKeyboardInput() { return; } - // $ key opens emoji picker (Sym+$ types literal '$') + // '$' key (without Sym) opens emoji picker if (key == KB_KEY_EMOJI) { emojiPicker.reset(); emojiPickerMode = true; @@ -855,10 +855,10 @@ void sendComposedMessage() { if (the_mesh.sendGroupMessage(timestamp, channel.channel, the_mesh.getNodePrefs()->node_name, utf8Buf, utf8Len)) { - // Add escape-byte version to local display (renders as sprites) + // Add to local display (UTF-8 gets sanitized to escape bytes by addMessage) ui_task.addSentChannelMessage(composeChannelIdx, the_mesh.getNodePrefs()->node_name, - composeBuffer); + utf8Buf); // Queue UTF-8 version for BLE app sync (so companion app shows real emoji) the_mesh.queueSentChannelMessage(composeChannelIdx, timestamp, diff --git a/examples/companion_radio/ui-new/ChannelScreen.h b/examples/companion_radio/ui-new/ChannelScreen.h index 5137cb0..323d25e 100644 --- a/examples/companion_radio/ui-new/ChannelScreen.h +++ b/examples/companion_radio/ui-new/ChannelScreen.h @@ -149,9 +149,19 @@ public: } } - // Display messages from scroll position + // Reverse to chronological order (oldest first, newest last at bottom) + for (int l = 0, r = numChannelMsgs - 1; l < r; l++, r--) { + int tmp = channelMsgs[l]; channelMsgs[l] = channelMsgs[r]; channelMsgs[r] = tmp; + } + + // Calculate start index so newest messages appear at the bottom + // scrollPos=0 shows the most recent messages, scrollPos++ scrolls up to older + int startIdx = numChannelMsgs - _msgsPerPage - _scrollPos; + if (startIdx < 0) startIdx = 0; + + // Display messages oldest-to-newest (top to bottom) int msgsDrawn = 0; - for (int i = _scrollPos; i < numChannelMsgs && y + lineHeight <= maxY; i++) { + for (int i = startIdx; i < numChannelMsgs && y + lineHeight <= maxY; i++) { int idx = channelMsgs[i]; ChannelMessage* msg = &_messages[idx]; diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index 9fc7340..5241cda 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -94,7 +94,7 @@ public: 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); + void addSentChannelMessage(uint8_t channel_idx, const char* sender, const char* text) override; // Get current screen for checking state UIScreen* getCurrentScreen() const { return curr; } diff --git a/variants/lilygo_tdeck_pro/Tca8418keyboard.h b/variants/lilygo_tdeck_pro/Tca8418keyboard.h index a70cb2f..b2242bd 100644 --- a/variants/lilygo_tdeck_pro/Tca8418keyboard.h +++ b/variants/lilygo_tdeck_pro/Tca8418keyboard.h @@ -21,7 +21,7 @@ #define KB_KEY_BACKSPACE '\b' #define KB_KEY_ENTER '\r' #define KB_KEY_SPACE ' ' -#define KB_KEY_EMOJI 0x01 // Internal code: bare $ key (emoji picker trigger) +#define KB_KEY_EMOJI 0x01 // Non-printable code for $ key (emoji picker) class TCA8418Keyboard { private: @@ -226,15 +226,15 @@ public: return 0; } - // Handle $ key (key code 22, next to M) - // Bare press -> emoji picker trigger, Sym+$ -> literal '$' character + // Handle dedicated $ key (key code 22, next to M) + // Bare press = emoji picker, Sym+$ = literal '$' if (keyCode == 22) { if (_symActive) { _symActive = false; Serial.println("KB: Sym+$ -> '$'"); return '$'; } - Serial.println("KB: $ key -> emoji trigger"); + Serial.println("KB: $ key -> emoji"); return KB_KEY_EMOJI; }