mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-08-03 18:56:15 +00:00
refactor: dedup persistence header, harden action menu, tidy small items
- Persist.h: shared writeHeader()/readHeader() for the magic+version+count
on-disk header; Waypoint and Trail snapshots now share one implementation
(byte layout unchanged; each keeps its own count clamp/reject + extra fields).
- TrailScreen: pushAction() guards _act_map / PopupMenu capacity, so adding a
new action can't silently overrun the fixed array.
- PopupMenu: add count()/setSelected() accessors; replace the remaining direct
_sel/_count field pokes in NearbyScreen, TrailScreen and QuickMsgScreen.
- Trail summary: unit-suffixed time ("1h 05m" / "5m 03s") so hours can't be
misread as minutes.
- Trail::haversineMeters delegates to geo::haversineKm — single Haversine
implementation (also trims a little flash).
Verified: GAT562 (SSD1306) and WioTrackerL1Eink (GxEPD) solo builds compile clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
151892e1ce
commit
b8a7b5dcc0
@@ -196,13 +196,13 @@ class NearbyScreen : public UIScreen {
|
||||
}
|
||||
|
||||
void rebuildPingMenu() {
|
||||
int keep = _ping_menu._sel; // preserve selection across a rebuild
|
||||
int keep = _ping_menu.selectedIndex(); // preserve selection across a rebuild
|
||||
_ping_menu.begin("Ping", 4);
|
||||
_ping_menu.addItem("Send");
|
||||
if (_ping_time_str[0]) _ping_menu.addItem(_ping_time_str);
|
||||
if (_ping_snr_out_str[0]) _ping_menu.addItem(_ping_snr_out_str);
|
||||
if (_ping_snr_back_str[0]) _ping_menu.addItem(_ping_snr_back_str);
|
||||
if (keep > 0 && keep < _ping_menu._count) _ping_menu._sel = keep;
|
||||
_ping_menu.setSelected(keep);
|
||||
}
|
||||
|
||||
void openPingMenu() { rebuildPingMenu(); }
|
||||
@@ -261,7 +261,7 @@ class NearbyScreen : public UIScreen {
|
||||
}
|
||||
// Keep the menu in sync with the populated result lines (grows as the
|
||||
// reply arrives; never shows blank rows).
|
||||
if (pingRowCount() != _ping_menu._count) rebuildPingMenu();
|
||||
if (pingRowCount() != _ping_menu.count()) rebuildPingMenu();
|
||||
}
|
||||
|
||||
bool handlePingMenuInput(char c, const uint8_t* pub_key, bool allow_enter_to_open = false) {
|
||||
|
||||
@@ -94,4 +94,6 @@ struct PopupMenu {
|
||||
}
|
||||
|
||||
int selectedIndex() const { return _sel; }
|
||||
int count() const { return _count; }
|
||||
void setSelected(int i) { if (i >= 0 && i < _count) _sel = i; }
|
||||
};
|
||||
|
||||
@@ -174,7 +174,8 @@ class QuickMsgScreen : public UIScreen {
|
||||
// Dispatch the selected fullscreen-options row. `channel` picks which
|
||||
// fullscreen view to close when starting a reply.
|
||||
void dispatchFsAction(bool channel) {
|
||||
FsAct a = (FsAct)_fs_act[(_ctx_menu._sel >= 0 && _ctx_menu._sel < _fs_act_n) ? _ctx_menu._sel : 0];
|
||||
int csel = _ctx_menu.selectedIndex();
|
||||
FsAct a = (FsAct)_fs_act[(csel >= 0 && csel < _fs_act_n) ? csel : 0];
|
||||
_ctx_menu.active = false;
|
||||
if (a == FS_REPLY) {
|
||||
(channel ? _fs : _dm_fs).active = false;
|
||||
|
||||
@@ -352,38 +352,34 @@ private:
|
||||
"%s tracking", _store->isActive() ? "Stop" : "Start");
|
||||
}
|
||||
|
||||
// Append an action row, guarding both the id map and the popup capacity so
|
||||
// adding a new action can never silently overrun _act_map / PopupMenu.
|
||||
void pushAction(ActionId id, const char* label) {
|
||||
if (_act_count >= (int)sizeof(_act_map)) return;
|
||||
_act_map[_act_count++] = (uint8_t)id;
|
||||
_action_menu.addItem(label);
|
||||
}
|
||||
|
||||
void openActionMenu() {
|
||||
refreshActionLabels();
|
||||
_act_count = 0;
|
||||
_action_menu.begin("Trail", 4);
|
||||
_act_map[_act_count++] = ACT_MIN_DIST; _action_menu.addItem(_act_min_dist_label);
|
||||
_act_map[_act_count++] = ACT_UNITS; _action_menu.addItem(_act_units_label);
|
||||
_act_map[_act_count++] = ACT_GRID; _action_menu.addItem(_act_grid_label);
|
||||
_act_map[_act_count++] = ACT_TOGGLE; _action_menu.addItem(_act_toggle_label);
|
||||
pushAction(ACT_MIN_DIST, _act_min_dist_label);
|
||||
pushAction(ACT_UNITS, _act_units_label);
|
||||
pushAction(ACT_GRID, _act_grid_label);
|
||||
pushAction(ACT_TOGGLE, _act_toggle_label);
|
||||
// Waypoints: mark the current spot, and browse/navigate saved ones.
|
||||
_act_map[_act_count++] = ACT_MARK; _action_menu.addItem("Mark here");
|
||||
pushAction(ACT_MARK, "Mark here");
|
||||
// "Waypoints" opens the nav list — always available; it hosts the list,
|
||||
// backtrack (Trail-start row) and the "+ Add by coords" entry.
|
||||
_act_map[_act_count++] = ACT_WAYPOINTS; _action_menu.addItem("Waypoints");
|
||||
if (_task->waypoints().count() > 0) {
|
||||
_act_map[_act_count++] = ACT_WP_CLEAR; _action_menu.addItem("Clear waypoints");
|
||||
}
|
||||
if (!_store->empty()) {
|
||||
_act_map[_act_count++] = ACT_SAVE; _action_menu.addItem("Save trail");
|
||||
}
|
||||
pushAction(ACT_WAYPOINTS, "Waypoints");
|
||||
if (_task->waypoints().count() > 0) pushAction(ACT_WP_CLEAR, "Clear waypoints");
|
||||
if (!_store->empty()) pushAction(ACT_SAVE, "Save trail");
|
||||
bool saved = savedTrailExists();
|
||||
if (saved) {
|
||||
_act_map[_act_count++] = ACT_LOAD; _action_menu.addItem("Load trail");
|
||||
}
|
||||
if (!_store->empty()) {
|
||||
_act_map[_act_count++] = ACT_EXPORT; _action_menu.addItem("Export (live)");
|
||||
}
|
||||
if (saved) {
|
||||
_act_map[_act_count++] = ACT_EXPORT_SAVED; _action_menu.addItem("Export (saved)");
|
||||
}
|
||||
if (!_store->empty()) {
|
||||
_act_map[_act_count++] = ACT_RESET; _action_menu.addItem("Reset trail");
|
||||
}
|
||||
if (saved) pushAction(ACT_LOAD, "Load trail");
|
||||
if (!_store->empty()) pushAction(ACT_EXPORT, "Export (live)");
|
||||
if (saved) pushAction(ACT_EXPORT_SAVED, "Export (saved)");
|
||||
if (!_store->empty()) pushAction(ACT_RESET, "Reset trail");
|
||||
}
|
||||
|
||||
static bool savedTrailExists() {
|
||||
@@ -584,7 +580,7 @@ private:
|
||||
// continue cycling.
|
||||
void reopenAt(int sel) {
|
||||
openActionMenu();
|
||||
if (sel >= 0 && sel < _act_count) _action_menu._sel = sel;
|
||||
_action_menu.setSelected(sel);
|
||||
}
|
||||
|
||||
void cycleMinDelta(NodePrefs* p, int dir) {
|
||||
@@ -644,9 +640,10 @@ private:
|
||||
}
|
||||
case 3: {
|
||||
uint32_t es = _store->elapsedSeconds();
|
||||
if (es < 3600) snprintf(buf, n, "Time: %lu:%02lu",
|
||||
// Unit-suffixed so "1h 05m" can't be misread as "1m 05s".
|
||||
if (es < 3600) snprintf(buf, n, "Time: %lum %02lus",
|
||||
(unsigned long)(es / 60), (unsigned long)(es % 60));
|
||||
else snprintf(buf, n, "Time: %lu:%02lu",
|
||||
else snprintf(buf, n, "Time: %luh %02lum",
|
||||
(unsigned long)(es / 3600), (unsigned long)((es % 3600) / 60));
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user