feat(companion): parse [LOC] in room messages + wire roomMessage event

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 <noreply@anthropic.com>
This commit is contained in:
MarekZegare4
2026-06-23 02:28:37 +02:00
parent 8adc313cc5
commit 79ebad58ae
2 changed files with 17 additions and 2 deletions

View File

@@ -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,

View File

@@ -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;