Messages from phone show on screen

This commit is contained in:
HarukiToreda 2025-09-25 22:44:23 -04:00
parent 46a8a9a89e
commit dd7a5cf31f
3 changed files with 88 additions and 138 deletions

View File

@ -64,16 +64,6 @@ void MessageStore::addFromPacket(const meshtastic_MeshPacket &packet)
} }
addLiveMessage(sm); addLiveMessage(sm);
// === Auto-switch ONLY if we're currently in ALL-mode ===
using graphics::MessageRenderer::getThreadMode;
if (getThreadMode() == ThreadMode::ALL) {
if (sm.type == MessageType::BROADCAST) {
setThreadMode(ThreadMode::CHANNEL, sm.channelIndex);
} else if (sm.type == MessageType::DM_TO_US) {
setThreadMode(ThreadMode::DIRECT, -1, sm.sender);
}
}
} }
// === Outgoing/manual message === // === Outgoing/manual message ===

View File

@ -1272,11 +1272,8 @@ void Screen::hideCurrentFrame()
{ {
uint8_t currentFrame = ui->getUiState()->currentFrame; uint8_t currentFrame = ui->getUiState()->currentFrame;
bool dismissed = false; bool dismissed = false;
if (currentFrame == framesetInfo.positions.textMessage && devicestate.has_rx_text_message) {
LOG_INFO("Hide Text Message"); if (currentFrame == framesetInfo.positions.waypoint && devicestate.has_rx_waypoint) {
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("Hide Waypoint"); LOG_DEBUG("Hide Waypoint");
devicestate.has_rx_waypoint = false; devicestate.has_rx_waypoint = false;
hiddenFrames.waypoint = true; hiddenFrames.waypoint = true;
@ -1292,7 +1289,7 @@ void Screen::hideCurrentFrame()
} }
if (dismissed) { if (dismissed) {
setFrames(FOCUS_DEFAULT); // You could also use FOCUS_PRESERVE setFrames(FOCUS_DEFAULT);
} }
} }
@ -1444,17 +1441,10 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
// Handles when message is received; will jump to text message frame. // Handles when message is received; will jump to text message frame.
int Screen::handleTextMessage(const meshtastic_MeshPacket *packet) int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
{ {
if (showingNormalScreen) { if (!showingNormalScreen)
if (packet->from == 0) { return 0;
// === Outgoing message (likely sent from phone) ===
devicestate.has_rx_text_message = false;
memset(&devicestate.rx_text_message, 0, sizeof(devicestate.rx_text_message));
hiddenFrames.textMessage = true;
hasUnreadMessage = false; // Clear unread state when user replies
setFrames(FOCUS_PRESERVE); // Stay on same frame, silently update frame list // === Build stored message ===
// === Save our own outgoing message to live RAM ===
StoredMessage sm; StoredMessage sm;
// Always use our local time // Always use our local time
@ -1467,55 +1457,50 @@ int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
sm.isBootRelative = true; // mark for later upgrade sm.isBootRelative = true; // mark for later upgrade
} }
sm.sender = nodeDB->getNodeNum(); // us
sm.channelIndex = packet->channel; sm.channelIndex = packet->channel;
sm.text = std::string(reinterpret_cast<const char *>(packet->decoded.payload.bytes)); sm.text = std::string(reinterpret_cast<const char *>(packet->decoded.payload.bytes));
// Distinguish between broadcast vs DM to peer if (packet->from == 0) {
if (packet->decoded.dest == NODENUM_BROADCAST) { // Outgoing message (sent by us, typically via phone)
sm.sender = nodeDB->getNodeNum(); // us
if (packet->decoded.dest == 0 || packet->decoded.dest == NODENUM_BROADCAST) {
// Fix: treat 0 as broadcast, not DM:00000000
sm.dest = NODENUM_BROADCAST; sm.dest = NODENUM_BROADCAST;
sm.type = MessageType::BROADCAST; sm.type = MessageType::BROADCAST;
} else { } else {
sm.dest = packet->decoded.dest; // peer node, not us sm.dest = packet->decoded.dest;
sm.type = MessageType::DM_TO_US; sm.type = MessageType::DM_TO_US;
} }
messageStore.addLiveMessage(sm); // RAM only (flash updated at shutdown)
// 🔹 Auto-switch thread view
if (sm.type == MessageType::BROADCAST) {
graphics::MessageRenderer::setThreadMode(graphics::MessageRenderer::ThreadMode::CHANNEL, sm.channelIndex);
} else if (sm.type == MessageType::DM_TO_US) {
graphics::MessageRenderer::setThreadMode(graphics::MessageRenderer::ThreadMode::DIRECT, -1,
sm.dest // use peer node
);
}
// 🔹 Reset scroll so newest message starts from the top
graphics::MessageRenderer::resetScrollState();
} else { } else {
// === Incoming message === // === Incoming message ===
devicestate.has_rx_text_message = true; // Needed to include the message frame sm.sender = packet->from;
hasUnreadMessage = true; // Enables mail icon in the header if (packet->to == NODENUM_BROADCAST || packet->decoded.dest == NODENUM_BROADCAST) {
setFrames(FOCUS_PRESERVE); // Refresh frame list without switching view sm.dest = NODENUM_BROADCAST;
sm.type = MessageType::BROADCAST;
// Only wake/force display if the configuration allows it } else {
if (shouldWakeOnReceivedMessage()) { sm.dest = nodeDB->getNodeNum(); // our node (we are DM target)
setOn(true); // Wake up the screen first sm.type = MessageType::DM_TO_US;
forceDisplay(); // Forces screen redraw
} }
// === Prepare banner content === hasUnreadMessage = true; // only incoming triggers mail icon
// Wake/force display if configured
if (shouldWakeOnReceivedMessage()) {
setOn(true);
forceDisplay();
}
// Prepare banner
const meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(packet->from); const meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(packet->from);
const char *longName = (node && node->has_user) ? node->user.long_name : nullptr; const char *longName = (node && node->has_user) ? node->user.long_name : nullptr;
const char *msgRaw = reinterpret_cast<const char *>(packet->decoded.payload.bytes); const char *msgRaw = reinterpret_cast<const char *>(packet->decoded.payload.bytes);
char banner[256]; char banner[256];
// Check for bell character in message to determine alert type
bool isAlert = false; bool isAlert = false;
for (size_t i = 0; i < packet->decoded.payload.size && i < 100; i++) { for (size_t i = 0; i < packet->decoded.payload.size && i < 100; i++) {
if (msgRaw[i] == '\x07') { if (msgRaw[i] == '\x07') { // bell
isAlert = true; isAlert = true;
break; break;
} }
@ -1546,48 +1531,24 @@ int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
#else #else
screen->showSimpleBanner(banner, 3000); screen->showSimpleBanner(banner, 3000);
#endif #endif
// === Save this incoming message to live RAM ===
StoredMessage sm;
// Always use our local time
uint32_t nowSecs = getValidTime(RTCQuality::RTCQualityDevice, true);
if (nowSecs > 0) {
sm.timestamp = nowSecs;
sm.isBootRelative = false;
} else {
sm.timestamp = millis() / 1000;
sm.isBootRelative = true; // mark for later upgrade
} }
sm.sender = packet->from; // Save to store (both outgoing + incoming)
sm.channelIndex = packet->channel; messageStore.addLiveMessage(sm);
sm.text = std::string(reinterpret_cast<const char *>(packet->decoded.payload.bytes));
// Distinguish between broadcast vs DM to us // Keep frame set active
if (packet->to == NODENUM_BROADCAST || packet->decoded.dest == NODENUM_BROADCAST) { setFrames(FOCUS_PRESERVE);
sm.dest = NODENUM_BROADCAST;
sm.type = MessageType::BROADCAST;
} else {
sm.dest = nodeDB->getNodeNum(); // our node (we are DM target)
sm.type = MessageType::DM_TO_US;
}
messageStore.addLiveMessage(sm); // RAM only (flash updated at shutdown)
// Auto-switch thread view // Auto-switch thread view
if (sm.type == MessageType::BROADCAST) { if (sm.type == MessageType::BROADCAST) {
graphics::MessageRenderer::setThreadMode(graphics::MessageRenderer::ThreadMode::CHANNEL, sm.channelIndex); graphics::MessageRenderer::setThreadMode(graphics::MessageRenderer::ThreadMode::CHANNEL, sm.channelIndex);
} else if (sm.type == MessageType::DM_TO_US) { } else if (sm.type == MessageType::DM_TO_US) {
graphics::MessageRenderer::setThreadMode(graphics::MessageRenderer::ThreadMode::DIRECT, -1, uint32_t peer = (packet->from == 0) ? sm.dest : sm.sender;
sm.sender // use peer node graphics::MessageRenderer::setThreadMode(graphics::MessageRenderer::ThreadMode::DIRECT, -1, peer);
);
} }
// Reset scroll so newest message starts from the top // Reset scroll so newest message starts from the top
graphics::MessageRenderer::resetScrollState(); graphics::MessageRenderer::resetScrollState();
}
}
return 0; return 0;
} }
@ -1680,7 +1641,7 @@ int Screen::handleInputEvent(const InputEvent *event)
} else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.lora) { } else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.lora) {
menuHandler::loraMenu(); menuHandler::loraMenu();
} else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.textMessage) { } else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.textMessage) {
if (devicestate.rx_text_message.from) { if (!messageStore.getMessages().empty()) {
menuHandler::messageResponseMenu(); menuHandler::messageResponseMenu();
} else { } else {
#if defined(M5STACK_UNITC6L) #if defined(M5STACK_UNITC6L)

View File

@ -453,7 +453,6 @@ void menuHandler::messageResponseMenu()
LOG_DEBUG("[ReplyCtx] mode=%d ch=%d peer=0x%08x", (int)mode, ch, (unsigned int)peer); LOG_DEBUG("[ReplyCtx] mode=%d ch=%d peer=0x%08x", (int)mode, ch, (unsigned int)peer);
if (selected == ViewMode) { if (selected == ViewMode) {
LOG_DEBUG("Switching to message_viewmode_menu");
menuHandler::menuQueue = menuHandler::message_viewmode_menu; menuHandler::menuQueue = menuHandler::message_viewmode_menu;
screen->runNow(); screen->runNow();
} else if (selected == DismissAll) { } else if (selected == DismissAll) {