mirror of
https://github.com/meshtastic/firmware.git
synced 2025-10-28 15:22:55 +00:00
Messages from phone show on screen
This commit is contained in:
parent
46a8a9a89e
commit
dd7a5cf31f
@ -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 ===
|
||||||
|
|||||||
@ -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,100 +1441,88 @@ 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 ===
|
||||||
|
StoredMessage sm;
|
||||||
|
|
||||||
// === Save our own outgoing message to live RAM ===
|
// Always use our local time
|
||||||
StoredMessage sm;
|
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
|
||||||
|
}
|
||||||
|
|
||||||
// Always use our local time
|
sm.channelIndex = packet->channel;
|
||||||
uint32_t nowSecs = getValidTime(RTCQuality::RTCQualityDevice, true);
|
sm.text = std::string(reinterpret_cast<const char *>(packet->decoded.payload.bytes));
|
||||||
if (nowSecs > 0) {
|
|
||||||
sm.timestamp = nowSecs;
|
|
||||||
sm.isBootRelative = false;
|
|
||||||
} else {
|
|
||||||
sm.timestamp = millis() / 1000;
|
|
||||||
sm.isBootRelative = true; // mark for later upgrade
|
|
||||||
}
|
|
||||||
|
|
||||||
sm.sender = nodeDB->getNodeNum(); // us
|
if (packet->from == 0) {
|
||||||
sm.channelIndex = packet->channel;
|
// Outgoing message (sent by us, typically via phone)
|
||||||
sm.text = std::string(reinterpret_cast<const char *>(packet->decoded.payload.bytes));
|
sm.sender = nodeDB->getNodeNum(); // us
|
||||||
|
if (packet->decoded.dest == 0 || packet->decoded.dest == NODENUM_BROADCAST) {
|
||||||
// Distinguish between broadcast vs DM to peer
|
// Fix: treat 0 as broadcast, not DM:00000000
|
||||||
if (packet->decoded.dest == NODENUM_BROADCAST) {
|
sm.dest = NODENUM_BROADCAST;
|
||||||
sm.dest = NODENUM_BROADCAST;
|
sm.type = MessageType::BROADCAST;
|
||||||
sm.type = MessageType::BROADCAST;
|
|
||||||
} else {
|
|
||||||
sm.dest = packet->decoded.dest; // peer node, not 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 ===
|
sm.dest = packet->decoded.dest;
|
||||||
devicestate.has_rx_text_message = true; // Needed to include the message frame
|
sm.type = MessageType::DM_TO_US;
|
||||||
hasUnreadMessage = true; // Enables mail icon in the header
|
}
|
||||||
setFrames(FOCUS_PRESERVE); // Refresh frame list without switching view
|
|
||||||
|
|
||||||
// Only wake/force display if the configuration allows it
|
} else {
|
||||||
if (shouldWakeOnReceivedMessage()) {
|
// === Incoming message ===
|
||||||
setOn(true); // Wake up the screen first
|
sm.sender = packet->from;
|
||||||
forceDisplay(); // Forces screen redraw
|
if (packet->to == NODENUM_BROADCAST || packet->decoded.dest == NODENUM_BROADCAST) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 char *longName = (node && node->has_user) ? node->user.long_name : nullptr;
|
||||||
|
|
||||||
|
const char *msgRaw = reinterpret_cast<const char *>(packet->decoded.payload.bytes);
|
||||||
|
char banner[256];
|
||||||
|
|
||||||
|
bool isAlert = false;
|
||||||
|
for (size_t i = 0; i < packet->decoded.payload.size && i < 100; i++) {
|
||||||
|
if (msgRaw[i] == '\x07') { // bell
|
||||||
|
isAlert = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// === Prepare banner content ===
|
if (isAlert) {
|
||||||
const meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(packet->from);
|
if (longName && longName[0]) {
|
||||||
const char *longName = (node && node->has_user) ? node->user.long_name : nullptr;
|
snprintf(banner, sizeof(banner), "Alert Received from\n%s", longName);
|
||||||
|
|
||||||
const char *msgRaw = reinterpret_cast<const char *>(packet->decoded.payload.bytes);
|
|
||||||
char banner[256];
|
|
||||||
|
|
||||||
// Check for bell character in message to determine alert type
|
|
||||||
bool isAlert = false;
|
|
||||||
for (size_t i = 0; i < packet->decoded.payload.size && i < 100; i++) {
|
|
||||||
if (msgRaw[i] == '\x07') {
|
|
||||||
isAlert = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isAlert) {
|
|
||||||
if (longName && longName[0]) {
|
|
||||||
snprintf(banner, sizeof(banner), "Alert Received from\n%s", longName);
|
|
||||||
} else {
|
|
||||||
strcpy(banner, "Alert Received");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (longName && longName[0]) {
|
strcpy(banner, "Alert Received");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (longName && longName[0]) {
|
||||||
#if defined(M5STACK_UNITC6L)
|
#if defined(M5STACK_UNITC6L)
|
||||||
strcpy(banner, "New Message");
|
strcpy(banner, "New Message");
|
||||||
#else
|
#else
|
||||||
snprintf(banner, sizeof(banner), "New Message from\n%s", longName);
|
snprintf(banner, sizeof(banner), "New Message from\n%s", longName);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
strcpy(banner, "New Message");
|
strcpy(banner, "New Message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(M5STACK_UNITC6L)
|
#if defined(M5STACK_UNITC6L)
|
||||||
screen->setOn(true);
|
screen->setOn(true);
|
||||||
@ -1546,49 +1531,25 @@ 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;
|
|
||||||
sm.channelIndex = packet->channel;
|
|
||||||
sm.text = std::string(reinterpret_cast<const char *>(packet->decoded.payload.bytes));
|
|
||||||
|
|
||||||
// Distinguish between broadcast vs DM to us
|
|
||||||
if (packet->to == NODENUM_BROADCAST || packet->decoded.dest == NODENUM_BROADCAST) {
|
|
||||||
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
|
|
||||||
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.sender // use peer node
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset scroll so newest message starts from the top
|
|
||||||
graphics::MessageRenderer::resetScrollState();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save to store (both outgoing + incoming)
|
||||||
|
messageStore.addLiveMessage(sm);
|
||||||
|
|
||||||
|
// Keep frame set active
|
||||||
|
setFrames(FOCUS_PRESERVE);
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
uint32_t peer = (packet->from == 0) ? sm.dest : sm.sender;
|
||||||
|
graphics::MessageRenderer::setThreadMode(graphics::MessageRenderer::ThreadMode::DIRECT, -1, peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset scroll so newest message starts from the top
|
||||||
|
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)
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user