Make NodeDB sort its internal vector when lastheard is updated. Don't sort in NodeListRenderer

This commit is contained in:
Jonathan Bennett 2025-06-25 17:20:36 -05:00
parent 42c1967e7b
commit 667ff17fdb
4 changed files with 25 additions and 43 deletions

View File

@ -113,35 +113,6 @@ int calculateMaxScroll(int totalEntries, int visibleRows)
return std::max(0, (totalEntries - 1) / (visibleRows * 2));
}
void retrieveAndSortNodes(std::vector<NodeEntry> &nodeList)
{
size_t numNodes = nodeDB->getNumMeshNodes();
for (size_t i = 0; i < numNodes; i++) {
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i);
if (!node || node->num == nodeDB->getNodeNum())
continue;
NodeEntry entry;
entry.node = node;
entry.sortValue = sinceLastSeen(node);
nodeList.push_back(entry);
}
// Sort nodes: favorites first, then by last heard (most recent first)
std::sort(nodeList.begin(), nodeList.end(), [](const NodeEntry &a, const NodeEntry &b) {
bool aFav = a.node->is_favorite;
bool bFav = b.node->is_favorite;
if (aFav != bFav)
return aFav;
if (a.sortValue == 0 || a.sortValue == UINT32_MAX)
return false;
if (b.sortValue == 0 || b.sortValue == UINT32_MAX)
return true;
return a.sortValue < b.sortValue;
});
}
void drawColumnSeparator(OLEDDisplay *display, int16_t x, int16_t yStart, int16_t yEnd)
{
int columnWidth = display->getWidth() / 2;
@ -440,17 +411,14 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
// Space below header
y += COMMON_HEADER_HEIGHT;
// Fetch and display sorted node list
std::vector<NodeEntry> nodeList;
retrieveAndSortNodes(nodeList);
int totalEntries = nodeList.size();
int totalEntries = nodeDB->getNumMeshNodes();
int totalRowsAvailable = (display->getHeight() - y) / rowYOffset;
int visibleNodeRows = totalRowsAvailable;
int totalColumns = 2;
int startIndex = scrollIndex * visibleNodeRows * totalColumns;
startIndex++; // skip own node
int endIndex = std::min(startIndex + visibleNodeRows * totalColumns, totalEntries);
int yOffset = 0;
@ -462,10 +430,10 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
for (int i = startIndex; i < endIndex; ++i) {
int xPos = x + (col * columnWidth);
int yPos = y + yOffset;
renderer(display, nodeList[i].node, xPos, yPos, columnWidth);
renderer(display, nodeDB->getMeshNodeByIndex(i), xPos, yPos, columnWidth);
if (extras) {
extras(display, nodeList[i].node, xPos, yPos, columnWidth, heading, lat, lon);
extras(display, nodeDB->getMeshNodeByIndex(i), xPos, yPos, columnWidth, heading, lat, lon);
}
lastNodeY = std::max(lastNodeY, yPos + FONT_HEIGHT_SMALL);

View File

@ -23,12 +23,6 @@ namespace NodeListRenderer
typedef void (*EntryRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int);
typedef void (*NodeExtrasRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int, float, double, double);
// Node entry structure
struct NodeEntry {
meshtastic_NodeInfoLite *node;
uint32_t sortValue;
};
// Node list mode enumeration
enum NodeListMode { MODE_LAST_HEARD = 0, MODE_HOP_SIGNAL = 1, MODE_DISTANCE = 2, MODE_COUNT = 3 };
@ -57,7 +51,6 @@ void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state,
// Utility functions
const char *getCurrentModeTitle(int screenWidth);
void retrieveAndSortNodes(std::vector<NodeEntry> &nodeList);
const char *getSafeNodeName(meshtastic_NodeInfoLite *node);
void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char **fields);

View File

@ -1337,6 +1337,24 @@ bool NodeDB::saveNodeDatabaseToDisk()
return saveProto(nodeDatabaseFileName, nodeDatabaseSize, &meshtastic_NodeDatabase_msg, &nodeDatabase, false);
}
void NodeDB::sortMeshDB()
{
std::sort(meshNodes->begin(), meshNodes->end(), [](const meshtastic_NodeInfoLite a, const meshtastic_NodeInfoLite b) {
if (a.num == myNodeInfo.my_node_num) {
return true;
}
bool aFav = a.is_favorite;
bool bFav = b.is_favorite;
if (aFav != bFav)
return aFav;
if (a.last_heard == 0 || a.last_heard == UINT32_MAX)
return false;
if (b.last_heard == 0 || b.last_heard == UINT32_MAX)
return true;
return a.last_heard > b.last_heard;
});
}
bool NodeDB::saveToDiskNoRetry(int saveWhat)
{
bool success = true;
@ -1558,6 +1576,7 @@ void NodeDB::addFromContact(meshtastic_SharedContact contact)
// Mark the node's key as manually verified to indicate trustworthiness.
updateGUIforNode = info;
// powerFSM.trigger(EVENT_NODEDB_UPDATED); This event has been retired
sortMeshDB();
notifyObservers(true); // Force an update whether or not our node counts have changed
}
saveNodeDatabaseToDisk();
@ -1661,6 +1680,7 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
info->has_hops_away = true;
info->hops_away = mp.hop_start - mp.hop_limit;
}
sortMeshDB();
}
}

View File

@ -310,6 +310,7 @@ class NodeDB
bool saveChannelsToDisk();
bool saveDeviceStateToDisk();
bool saveNodeDatabaseToDisk();
void sortMeshDB();
};
extern NodeDB *nodeDB;