diff --git a/examples/companion_radio/AbstractUITask.h b/examples/companion_radio/AbstractUITask.h index 3d0fa85b..9ec3b482 100644 --- a/examples/companion_radio/AbstractUITask.h +++ b/examples/companion_radio/AbstractUITask.h @@ -65,7 +65,7 @@ public: virtual void msgRead(int msgcount) = 0; virtual void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount, uint8_t contact_type = 0, const uint8_t* pub_key = nullptr) = 0; virtual void notify(UIEventType t = UIEventType::none) = 0; - virtual void addChannelMsg(uint8_t channel_idx, const char* text) {} + virtual void addChannelMsg(uint8_t channel_idx, const char* text, uint32_t timestamp = 0) {} virtual void addDMMsg(const uint8_t* pub_key, bool outgoing, const char* text, uint32_t sender_timestamp = 0) {} // A node shared its current position via a [LOC] message. pub_key is the // sender's key prefix for a verified DM share, or null for a channel share diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 8e9224e3..d0f33f6c 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -721,7 +721,7 @@ void MyMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh::Packe _serial->writeFrame(frame, 1); } #ifdef DISPLAY_CLASS - if (_ui) _ui->addChannelMsg(channel_idx, text); + if (_ui) _ui->addChannelMsg(channel_idx, text, timestamp); if (_ui) _ui->notify(UIEventType::channelMessage); const char *channel_name = "Unknown"; ChannelDetails channel_details; diff --git a/examples/companion_radio/ui-new/QuickMsgScreen.h b/examples/companion_radio/ui-new/QuickMsgScreen.h index dfd69598..b560f0b1 100644 --- a/examples/companion_radio/ui-new/QuickMsgScreen.h +++ b/examples/companion_radio/ui-new/QuickMsgScreen.h @@ -398,7 +398,11 @@ class QuickMsgScreen : public UIScreen { } memcpy(_dm_hist[pos].prefix, pub_key, 4); _dm_hist[pos].outgoing = outgoing ? 1 : 0; - _dm_hist[pos].timestamp = rtc_clock.getCurrentTime(); + // Prefer the sender's own timestamp — a room-sync replay or an + // offline-queued message held by a repeater can arrive long after it was + // actually sent, so "now" would mislabel every backlog message as fresh. + // Fall back to receipt time only when the sender's timestamp is unknown. + _dm_hist[pos].timestamp = msg_ts ? msg_ts : rtc_clock.getCurrentTime(); strncpy(_dm_hist[pos].text, text, sizeof(DmHistEntry::text) - 1); _dm_hist[pos].text[sizeof(DmHistEntry::text) - 1] = '\0'; _dm_hist[pos].ack_status = (outgoing && ack_tag) ? ACK_PENDING : ACK_NONE; @@ -677,8 +681,10 @@ public: } // Returns the ring position the message was stored at, or -1 if rejected, so - // the outgoing path can attach a relay seq to that exact entry. - int addChannelMsg(uint8_t ch_idx, const char* text) { + // the outgoing path can attach a relay seq to that exact entry. `timestamp` + // is the sender's own send time (0 = unknown/outgoing — use receipt time); + // see storeDMMsg() for why this matters for synced/queued backlog messages. + int addChannelMsg(uint8_t ch_idx, const char* text, uint32_t timestamp = 0) { // Guard against bogus channel indices (e.g. findChannelIdx() returned -1 // and was cast to uint8_t → 255). Storing such an entry would burn a ring // slot for a message that no visible channel can ever surface. @@ -698,7 +704,7 @@ public: _hist_head = (_hist_head + 1) % CH_HIST_MAX; } _hist[pos].ch_idx = ch_idx; - _hist[pos].timestamp = rtc_clock.getCurrentTime(); + _hist[pos].timestamp = timestamp ? timestamp : rtc_clock.getCurrentTime(); strncpy(_hist[pos].text, text, sizeof(_hist[pos].text) - 1); _hist[pos].text[sizeof(_hist[pos].text) - 1] = '\0'; _hist[pos].relay_status = ACK_NONE; diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 4a95278e..bb5046a1 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -1628,9 +1628,9 @@ int UITask::getRecentDMContacts(uint8_t out[][NodePrefs::FAVOURITE_PREFIX_LEN], return ((QuickMsgScreen*)quick_msg)->getRecentDMContacts(out, max); } -void UITask::addChannelMsg(uint8_t channel_idx, const char* text) { +void UITask::addChannelMsg(uint8_t channel_idx, const char* text, uint32_t timestamp) { _last_notif_ch_idx = (int)channel_idx; - ((QuickMsgScreen*)quick_msg)->addChannelMsg(channel_idx, text); + ((QuickMsgScreen*)quick_msg)->addChannelMsg(channel_idx, text, timestamp); } int UITask::getChannelUnreadCount() const { diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index 1a80f414..d4e72e0a 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -261,7 +261,7 @@ public: void stopMelody(); bool isMelodyPlaying(); void showAlert(const char* text, int duration_millis); - void addChannelMsg(uint8_t channel_idx, const char* text) override; + void addChannelMsg(uint8_t channel_idx, const char* text, uint32_t timestamp = 0) override; void addDMMsg(const uint8_t* pub_key, bool outgoing, const char* text, uint32_t sender_timestamp = 0) override; void onMsgAck(uint32_t ack_crc) override; void onChannelRelayed(uint32_t seq) override;