From 79ebad58ae6b79606d8765818afe2d3b0114b5fb Mon Sep 17 00:00:00 2001 From: MarekZegare4 Date: Tue, 23 Jun 2026 02:28:37 +0200 Subject: [PATCH] feat(companion): parse [LOC] in room messages + wire roomMessage event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two receive→UI wiring gaps of the same class as the room-history fix: - onSignedMessageRecv (room posts) didn't parse [LOC] live-location shares, while DM (onMessageRecv) and channel (onChannelMessageRecv) both do — so a guest sharing position in a room never appeared on the map/nearby. Resolve the signed sender prefix to a name and track by name, mirroring the channel path (unverified: only a 4-byte prefix is available here). - UIEventType::roomMessage was defined but never emitted; room notifications rode on contactMessage and always played the global DM melody. Emit roomMessage for room posts and handle it explicitly (default DM melody, no per-sender lookup since the author varies); drop the now-duplicate dead case. Build verified: WioTrackerL1 solo. Co-Authored-By: Claude Opus 4.8 --- examples/companion_radio/MyMesh.cpp | 13 ++++++++++++- examples/companion_radio/ui-new/UITask.cpp | 6 +++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index e2e3c02b..ec876b41 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -485,7 +485,7 @@ void MyMesh::queueMessage(const ContactInfo &from, uint8_t txt_type, mesh::Packe bool should_display = txt_type == TXT_TYPE_PLAIN || txt_type == TXT_TYPE_SIGNED_PLAIN; if (should_display && _ui) { _ui->newMsg(path_len, from.name, text, offline_queue_len, from.type, from.id.pub_key); - _ui->notify(UIEventType::contactMessage); + _ui->notify(from.type == ADV_TYPE_ROOM ? UIEventType::roomMessage : UIEventType::contactMessage); // Add to the on-device conversation history. Room servers (ADV_TYPE_ROOM) are // viewed through the same history list as chat contacts (keyed by the server's // pubkey), so their posts must be stored too — otherwise an incoming room @@ -664,6 +664,17 @@ void MyMesh::onSignedMessageRecv(const ContactInfo &from, mesh::Packet *pkt, uin // from.sync_since change needs to be persisted dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); queueMessage(from, TXT_TYPE_SIGNED_PLAIN, pkt, sender_timestamp, sender_prefix, 4, text); + + // Live position share inside a room (mirrors the DM and channel paths). The + // post's author is the signed sender_prefix, not the room server `from`, so + // resolve that 4-byte prefix to a contact name and track by name. Unverified: + // we only hold a 4-byte prefix here, not the full pubkey LiveTrack keys on. + int32_t loc_lat, loc_lon; + if (_ui && geo::parseLocShare(text, loc_lat, loc_lon)) { + ContactInfo* sc = sender_prefix ? lookupContactByPubKey(sender_prefix, 4) : nullptr; + const char* who = (sc && sc->name[0]) ? sc->name : from.name; + _ui->onSharedLocation(nullptr, who, loc_lat, loc_lon, sender_timestamp, false); + } } void MyMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh::Packet *pkt, uint32_t timestamp, diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 52b58af9..17e51024 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -1616,6 +1616,11 @@ void UITask::notify(UIEventType t) { sn.playCH(_last_notif_ch_idx); _last_notif_ch_idx = -1; break; + case UIEventType::roomMessage: + // Rooms have many authors and no per-room melody pref, so use the default DM + // notification (no per-sender melody/mute lookup — the author varies per post). + sn.playDM(false, nullptr); + break; case UIEventType::advertReceivedFlood: case UIEventType::advertReceivedZeroHop: sn.playAD(t == UIEventType::advertReceivedFlood); @@ -1623,7 +1628,6 @@ void UITask::notify(UIEventType t) { case UIEventType::ack: buzzer.play("ack:d=32,o=8,b=120:c"); break; - case UIEventType::roomMessage: case UIEventType::none: default: break;