feat(companion): widen Locator targeting beyond favourites/live-share

Locator's person target now resolves any known contact's position, not just
an active live [LOC] share: locatorDistance() falls back to the contact's
last-advertised gps_lat/gps_lon when there's no current live share, so a
rarely-updating but stationary node (a repeater, or someone who shared a fix
once) still works as a target. LocatorScreen's target picker is widened to
match (favourites always offered, plus every other contact with a currently
resolvable position), and shows a compact age tag for non-live entries so
staleness is visible.

Also adds a quick "Set Locator target" action directly from Nearby Nodes' and
Waypoints' own popup menus (UITask::setLocatorTarget()), so picking a target
doesn't require a detour through Tools > Locator.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
MarekZegare4
2026-06-24 16:18:39 +02:00
co-authored by Claude Sonnet 4.6
parent 57f5346427
commit b7e7e945d2
6 changed files with 138 additions and 41 deletions
+13
View File
@@ -61,6 +61,19 @@ static inline void fmtDist(char* buf, int n, float km, bool imperial) {
}
}
// Compact age tag for a timestamp, e.g. "12s" / "5m" / "3h" / "2d" — sized to
// sit inline after a name (unlike a full "X ago" sentence). Empty string for
// an unknown (0) or future timestamp. Takes `now` rather than reading the RTC
// itself, so this stays a pure function like the rest of this file.
static inline void fmtAgeShort(char* buf, int n, uint32_t now, uint32_t lastmod) {
if (lastmod == 0 || now < lastmod) { buf[0] = '\0'; return; }
uint32_t age = now - lastmod;
if (age < 60) snprintf(buf, n, "%us", (unsigned)age);
else if (age < 3600) snprintf(buf, n, "%um", (unsigned)(age / 60));
else if (age < 86400) snprintf(buf, n, "%uh", (unsigned)(age / 3600));
else snprintf(buf, n, "%ud", (unsigned)(age / 86400));
}
// Tag marking a shared waypoint inside a message: "[WAY]<lat>,<lon> <label>".
// A plain {loc} expansion ("<lat>,<lon>") parses too — the tag just adds intent
// and a label, and keeps the text readable on apps/firmware that don't know it.