mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-08-03 02:36:11 +00:00
refactor(companion): unify the active target across Locator/Nav entry points
Three notions of "set a target" had drifted apart: LocatorScreen's picker hand-wrote the prefs fields and deferred the save, while the Nearby/Waypoints popups wrote the same fields again and saved immediately, and the live>last- advertised position precedence was duplicated between the engine and the picker. - setTarget() is now the single definition of the active target (fields + re-arm). setTargetNow() wraps it for popups (immediate save + confirm); the Locator screen keeps its deferred save so LEFT/RIGHT cycling doesn't thrash flash. applyTarget() delegates instead of re-writing the fields. - resolvePersonPos() is the single live-share / last-advertised precedence, used by both locatorDistance() and the picker. - Consistent action verb "Set as target" in Nearby and Waypoints menus. No behaviour change for the user beyond the relabel; pure consolidation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f481e3669f
commit
83d139a62d
@@ -2272,23 +2272,37 @@ void UITask::loop() {
|
||||
// configured radius (m). Returns false when no target is set or there's no fix
|
||||
// — the single place the target-distance maths lives, shared by the crossing
|
||||
// evaluator and the proximity beeper.
|
||||
// One precedence for a person's position — an active [LOC] live share wins,
|
||||
// else the last-advertised GPS fix. Not everyone keeps live-sharing on, so the
|
||||
// fallback lets a rarely-updating but stationary node (a repeater, or someone
|
||||
// who shared a fix once) still work as a target.
|
||||
bool UITask::resolvePersonPos(const uint8_t* key, int32_t& lat, int32_t& lon,
|
||||
bool* live, uint32_t* ts) const {
|
||||
if (live) *live = false;
|
||||
if (ts) *ts = 0;
|
||||
if (!key) return false;
|
||||
const LiveTrackStore::Entry* e =
|
||||
_livetrack.activeByKey(key, (uint32_t)rtc_clock.getCurrentTime());
|
||||
if (e) {
|
||||
lat = e->lat_1e6; lon = e->lon_1e6;
|
||||
if (live) *live = true;
|
||||
if (ts) *ts = e->ts;
|
||||
return true;
|
||||
}
|
||||
ContactInfo* c = the_mesh.lookupContactByPubKey(key, NodePrefs::FAVOURITE_PREFIX_LEN);
|
||||
if (c && (c->gps_lat != 0 || c->gps_lon != 0)) {
|
||||
lat = c->gps_lat; lon = c->gps_lon;
|
||||
if (ts) *ts = c->lastmod;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UITask::locatorDistance(float& dist_m, float& radius_m) const {
|
||||
if (!_node_prefs || !_node_prefs->locator_has_target) return false;
|
||||
int32_t tlat, tlon;
|
||||
if (_node_prefs->locator_target_kind == 1) {
|
||||
// Live contact: prefer the latest [LOC] position. With no active share —
|
||||
// not everyone keeps live-sharing on — fall back to their last-advertised
|
||||
// position, so a rarely-updating but stationary node (a repeater, or a
|
||||
// contact who simply shared a fix once) still works as a target.
|
||||
const LiveTrackStore::Entry* e =
|
||||
_livetrack.activeByKey(_node_prefs->locator_key, (uint32_t)rtc_clock.getCurrentTime());
|
||||
if (e) {
|
||||
tlat = e->lat_1e6; tlon = e->lon_1e6;
|
||||
} else {
|
||||
ContactInfo* c = the_mesh.lookupContactByPubKey(_node_prefs->locator_key, NodePrefs::FAVOURITE_PREFIX_LEN);
|
||||
if (!c || (c->gps_lat == 0 && c->gps_lon == 0)) return false;
|
||||
tlat = c->gps_lat; tlon = c->gps_lon;
|
||||
}
|
||||
if (!resolvePersonPos(_node_prefs->locator_key, tlat, tlon)) return false;
|
||||
} else {
|
||||
tlat = _node_prefs->locator_lat_1e6; tlon = _node_prefs->locator_lon_1e6;
|
||||
}
|
||||
@@ -2333,17 +2347,22 @@ void UITask::fireLocator(bool arrived) {
|
||||
playMelody(arrived ? "locarr:d=8,o=6,b=140:c,e,g" : "loclv:d=8,o=6,b=140:g,e,c");
|
||||
}
|
||||
|
||||
void UITask::setLocatorTarget(uint8_t kind, const uint8_t* key, int32_t lat, int32_t lon, const char* name) {
|
||||
void UITask::setTarget(uint8_t kind, const uint8_t* key, int32_t lat, int32_t lon, const char* name) {
|
||||
if (!_node_prefs) return;
|
||||
_node_prefs->locator_target_kind = kind;
|
||||
if (kind == 1) memcpy(_node_prefs->locator_key, key, NodePrefs::FAVOURITE_PREFIX_LEN);
|
||||
if (kind == 1 && key) memcpy(_node_prefs->locator_key, key, NodePrefs::FAVOURITE_PREFIX_LEN);
|
||||
_node_prefs->locator_lat_1e6 = lat;
|
||||
_node_prefs->locator_lon_1e6 = lon;
|
||||
snprintf(_node_prefs->locator_label, sizeof(_node_prefs->locator_label), "%s", name);
|
||||
_node_prefs->locator_has_target = 1;
|
||||
resetLocator(); // re-seed the crossing engine so the change can't fire on a stale state
|
||||
}
|
||||
|
||||
void UITask::setTargetNow(uint8_t kind, const uint8_t* key, int32_t lat, int32_t lon, const char* name) {
|
||||
if (!_node_prefs) return;
|
||||
setTarget(kind, key, lat, lon, name);
|
||||
the_mesh.savePrefs();
|
||||
resetLocator();
|
||||
showAlert("Locator target set", 1200);
|
||||
showAlert("Target set", 1200);
|
||||
}
|
||||
|
||||
// Homing beeper: while armed with a target and inside the radius, emit a short
|
||||
|
||||
Reference in New Issue
Block a user