mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-14 15:16:40 +00:00
fix(ui): DM contact picker missed real contacts (off-by-MAX_ANON_CONTACTS)
getContactByIdx() indexes the raw contacts[] table directly, whose first MAX_ANON_CONTACTS (8) slots are reserved for anon requests -- getNumContacts() already excludes them from its count, so real contacts start at index MAX_ANON_CONTACTS, not 0 (NearbyScreen.h's own contact scan already applies this offset; its comment documents why). MessagesScreen.h's buildContactList() didn't, so its loop only ever read the reserved anon slots (empty name, type 0) for any total at or under MAX_ANON_CONTACTS -- e.g. a device with exactly one known contact would show "SELECT CONTACT" / "No favourites" with an empty list forever, regardless of the dm_show_all/fav_only setting or that contact's own favourite flag. Reproduced live in the browser sim: a fresh companion_radio instance with one real ADV_TYPE_CHAT contact showed nothing until this fix. Also fixed _sorted[]'s stored index (was the bare loop counter, needed to be the raw table index every other call site in the file already assumes) and the same missing-offset bug in BotScreen.h's room-contact counter and MessageHistory.h's pub_key-prefix contact lookup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -96,8 +96,14 @@ class BotScreen : public UIScreen {
|
||||
_num_rooms = 0;
|
||||
ContactInfo ci;
|
||||
int total = the_mesh.getNumContacts();
|
||||
// +MAX_ANON_CONTACTS: getContactByIdx() indexes the raw contacts[] table,
|
||||
// whose first MAX_ANON_CONTACTS slots are reserved anon-request entries
|
||||
// that getNumContacts() already excludes from its count (see
|
||||
// NearbyScreen.h's own contact scan, and MessagesScreen.h's
|
||||
// buildContactList(), for the same offset) -- without it this underrode
|
||||
// real room-server contacts by up to MAX_ANON_CONTACTS.
|
||||
for (int i = 0; i < total; i++)
|
||||
if (the_mesh.getContactByIdx(i, ci) && ci.type == ADV_TYPE_ROOM) _num_rooms++;
|
||||
if (the_mesh.getContactByIdx(MAX_ANON_CONTACTS + i, ci) && ci.type == ADV_TYPE_ROOM) _num_rooms++;
|
||||
}
|
||||
|
||||
// Header as a circular tab bar (shared geometry — see TabBar.h). `right_reserve`
|
||||
|
||||
@@ -388,9 +388,12 @@ private:
|
||||
// Look up a contact by 4-byte pub_key prefix (as stored in DmHistEntry).
|
||||
bool contactByPrefix(const uint8_t* prefix, ContactInfo& out) const {
|
||||
int total = the_mesh.getNumContacts();
|
||||
// +MAX_ANON_CONTACTS: see MessagesScreen.h's buildContactList() for why
|
||||
// getContactByIdx() needs this offset (raw table index, not the
|
||||
// anon-excluded logical count getNumContacts() returns).
|
||||
for (int i = 0; i < total; i++) {
|
||||
ContactInfo c;
|
||||
if (!the_mesh.getContactByIdx(i, c)) continue;
|
||||
if (!the_mesh.getContactByIdx(MAX_ANON_CONTACTS + i, c)) continue;
|
||||
if (memcmp(c.id.pub_key, prefix, 4) == 0) { out = c; return true; }
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -694,8 +694,20 @@ class MessagesScreen : public UIScreen {
|
||||
// task stack for one local array.
|
||||
uint8_t keys[MAX_CONTACTS];
|
||||
bool fav_only = rooms ? (p && p->room_fav_only) : !(p && p->dm_show_all);
|
||||
// getContactByIdx() indexes the RAW contacts[] table, whose first
|
||||
// MAX_ANON_CONTACTS slots are reserved for anon requests (see
|
||||
// BaseChatMesh::resetContacts()/ContactsIterator); getNumContacts()
|
||||
// already excludes them from the count, so the real contacts start at
|
||||
// MAX_ANON_CONTACTS, not 0 -- same offset NearbyScreen.h's own contact
|
||||
// scan already applies. Without it, this loop only ever read the
|
||||
// reserved anon slots (empty name, type 0) for the first
|
||||
// MAX_ANON_CONTACTS iterations and, for any total at or under that count,
|
||||
// NEVER reached a real contact at all -- e.g. a device with exactly one
|
||||
// known contact would show "No favourites" with an empty list forever,
|
||||
// regardless of the dm_show_all/fav_only setting or that contact's own
|
||||
// favourite flag.
|
||||
for (int i = 0; i < total; i++) {
|
||||
if (!the_mesh.getContactByIdx(i, c)) continue;
|
||||
if (!the_mesh.getContactByIdx(MAX_ANON_CONTACTS + i, c)) continue;
|
||||
if (c.type != (rooms ? ADV_TYPE_ROOM : ADV_TYPE_CHAT)) continue;
|
||||
bool fav = (c.flags & 0x01) != 0;
|
||||
if (fav_only && !fav) continue;
|
||||
@@ -703,7 +715,11 @@ class MessagesScreen : public UIScreen {
|
||||
if (k > 127) k = 127;
|
||||
if (fav && !(p && p->fav_sort_off)) k += 128;
|
||||
keys[_num_contacts] = k;
|
||||
_sorted[_num_contacts++] = i;
|
||||
// Store the RAW table index (not the bare loop counter) -- every other
|
||||
// call site in this file (render()'s mesh_idx, toggleFav(), the
|
||||
// context-menu handlers, ...) reads _sorted[...] straight into
|
||||
// getContactByIdx() with no offset of its own.
|
||||
_sorted[_num_contacts++] = MAX_ANON_CONTACTS + i;
|
||||
}
|
||||
// Descending insertion sort; rows with key 0 keep their contact-table order.
|
||||
for (int i = 1; i < _num_contacts; i++) {
|
||||
|
||||
Reference in New Issue
Block a user