mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-08-03 02:36:11 +00:00
refactor(ui): rename "Breadcrumb" to "Trail" across the feature
User-facing label change requested for the GPS trail viewer. Carries
through internally for consistency:
- Files: Breadcrumb.h → Trail.h, BreadcrumbScreen.h → TrailScreen.h
- Types: BreadcrumbPoint/Store/Screen → Trail*
- NodePrefs fields: breadcrumb_*_idx → trail_*_idx (same byte layout, no
sentinel bump needed)
- UITask: _breadcrumb, breadcrumb_screen, gotoBreadcrumbScreen,
_next_breadcrumb_sample_ms → trail-prefixed equivalents
- Tools menu label "Breadcrumb" → "Trail", screen title "TRAIL"
Status bar indicator stays "G" — semantics ("GPS logging active") match.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
adef2fceb9
commit
ae783edc47
@@ -305,8 +305,8 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
|||||||
}
|
}
|
||||||
|
|
||||||
rd(_prefs.favourite_contacts, sizeof(_prefs.favourite_contacts));
|
rd(_prefs.favourite_contacts, sizeof(_prefs.favourite_contacts));
|
||||||
rd(&_prefs.breadcrumb_interval_idx, sizeof(_prefs.breadcrumb_interval_idx));
|
rd(&_prefs.trail_interval_idx, sizeof(_prefs.trail_interval_idx));
|
||||||
rd(&_prefs.breadcrumb_min_delta_idx, sizeof(_prefs.breadcrumb_min_delta_idx));
|
rd(&_prefs.trail_min_delta_idx, sizeof(_prefs.trail_min_delta_idx));
|
||||||
|
|
||||||
// Schema sentinel: bumped on layout changes. Mismatch means an older file
|
// Schema sentinel: bumped on layout changes. Mismatch means an older file
|
||||||
// (or a different schema); rd() already zero-inits any fields not present,
|
// (or a different schema); rd() already zero-inits any fields not present,
|
||||||
@@ -405,8 +405,8 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
|
|||||||
file.write((uint8_t *)&_prefs.eink_full_refresh_every, sizeof(_prefs.eink_full_refresh_every));
|
file.write((uint8_t *)&_prefs.eink_full_refresh_every, sizeof(_prefs.eink_full_refresh_every));
|
||||||
file.write((uint8_t *)&_prefs.page_order_set, sizeof(_prefs.page_order_set));
|
file.write((uint8_t *)&_prefs.page_order_set, sizeof(_prefs.page_order_set));
|
||||||
file.write((uint8_t *)_prefs.favourite_contacts, sizeof(_prefs.favourite_contacts));
|
file.write((uint8_t *)_prefs.favourite_contacts, sizeof(_prefs.favourite_contacts));
|
||||||
file.write((uint8_t *)&_prefs.breadcrumb_interval_idx, sizeof(_prefs.breadcrumb_interval_idx));
|
file.write((uint8_t *)&_prefs.trail_interval_idx, sizeof(_prefs.trail_interval_idx));
|
||||||
file.write((uint8_t *)&_prefs.breadcrumb_min_delta_idx, sizeof(_prefs.breadcrumb_min_delta_idx));
|
file.write((uint8_t *)&_prefs.trail_min_delta_idx, sizeof(_prefs.trail_min_delta_idx));
|
||||||
|
|
||||||
// Tail sentinel — must be last. See NodePrefs::SCHEMA_SENTINEL.
|
// Tail sentinel — must be last. See NodePrefs::SCHEMA_SENTINEL.
|
||||||
uint32_t sentinel = NodePrefs::SCHEMA_SENTINEL;
|
uint32_t sentinel = NodePrefs::SCHEMA_SENTINEL;
|
||||||
|
|||||||
@@ -99,10 +99,10 @@ struct NodePrefs { // persisted to file
|
|||||||
static const uint8_t FAVOURITE_PREFIX_LEN = 6;
|
static const uint8_t FAVOURITE_PREFIX_LEN = 6;
|
||||||
uint8_t favourite_contacts[FAVOURITES_COUNT][FAVOURITE_PREFIX_LEN];
|
uint8_t favourite_contacts[FAVOURITES_COUNT][FAVOURITE_PREFIX_LEN];
|
||||||
|
|
||||||
// GPS breadcrumb cadence — indices into BreadcrumbStore::intervalSecs / minDeltaMeters.
|
// GPS trail cadence — indices into TrailStore::intervalSecs / minDeltaMeters.
|
||||||
// Logging on/off is a runtime state (Tools › Breadcrumb), not a persisted preference.
|
// Logging on/off is a runtime state (Tools › Trail), not a persisted preference.
|
||||||
uint8_t breadcrumb_interval_idx; // 0..3: 1min / 30s / 5min / 15min
|
uint8_t trail_interval_idx; // 0..3: 1min / 30s / 5min / 15min
|
||||||
uint8_t breadcrumb_min_delta_idx; // 0..2: 25m / 5m / 100m
|
uint8_t trail_min_delta_idx; // 0..2: 25m / 5m / 100m
|
||||||
|
|
||||||
// Tail sentinel written at the end of /new_prefs. Bump the low byte when
|
// Tail sentinel written at the end of /new_prefs. Bump the low byte when
|
||||||
// adding/removing/reordering fields in DataStore::savePrefs/loadPrefsInt so
|
// adding/removing/reordering fields in DataStore::savePrefs/loadPrefsInt so
|
||||||
|
|||||||
@@ -4,18 +4,18 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// RAM-only GPS breadcrumb ring buffer.
|
// RAM-only GPS trail ring buffer.
|
||||||
// Storage cost: 256 × 12 B = 3 KB. The trail survives auto-off (only the
|
// Storage cost: 256 × 12 B = 3 KB. The trail survives auto-off (only the
|
||||||
// display blanks) but is lost on reboot — user explicitly snapshots to a
|
// display blanks) but is lost on reboot — user explicitly snapshots to a
|
||||||
// LittleFS slot before powering down to keep it.
|
// LittleFS slot before powering down to keep it.
|
||||||
|
|
||||||
struct BreadcrumbPoint {
|
struct TrailPoint {
|
||||||
int32_t lat_1e6;
|
int32_t lat_1e6;
|
||||||
int32_t lon_1e6;
|
int32_t lon_1e6;
|
||||||
uint32_t ts; // epoch seconds (RTC)
|
uint32_t ts; // epoch seconds (RTC)
|
||||||
};
|
};
|
||||||
|
|
||||||
class BreadcrumbStore {
|
class TrailStore {
|
||||||
public:
|
public:
|
||||||
static const int CAPACITY = 256;
|
static const int CAPACITY = 256;
|
||||||
|
|
||||||
@@ -48,9 +48,9 @@ public:
|
|||||||
bool empty() const { return _count == 0; }
|
bool empty() const { return _count == 0; }
|
||||||
|
|
||||||
// i = 0 → oldest entry, i = count()-1 → newest.
|
// i = 0 → oldest entry, i = count()-1 → newest.
|
||||||
const BreadcrumbPoint& at(int i) const { return _buf[(_head + i) % CAPACITY]; }
|
const TrailPoint& at(int i) const { return _buf[(_head + i) % CAPACITY]; }
|
||||||
const BreadcrumbPoint& first() const { return at(0); }
|
const TrailPoint& first() const { return at(0); }
|
||||||
const BreadcrumbPoint& last() const { return at(_count - 1); }
|
const TrailPoint& last() const { return at(_count - 1); }
|
||||||
|
|
||||||
void clear() { _head = 0; _count = 0; }
|
void clear() { _head = 0; _count = 0; }
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BreadcrumbPoint _buf[CAPACITY];
|
TrailPoint _buf[CAPACITY];
|
||||||
int _head = 0;
|
int _head = 0;
|
||||||
int _count = 0;
|
int _count = 0;
|
||||||
bool _active = false;
|
bool _active = false;
|
||||||
@@ -44,9 +44,9 @@ public:
|
|||||||
if (_sel == 1) { _task->gotoBotScreen(); return true; }
|
if (_sel == 1) { _task->gotoBotScreen(); return true; }
|
||||||
if (_sel == 2) { _task->gotoNearbyScreen(); return true; }
|
if (_sel == 2) { _task->gotoNearbyScreen(); return true; }
|
||||||
if (_sel == 3) { _task->gotoAutoAdvertScreen(); return true; }
|
if (_sel == 3) { _task->gotoAutoAdvertScreen(); return true; }
|
||||||
if (_sel == 4) { _task->gotoBreadcrumbScreen(); return true; }
|
if (_sel == 4) { _task->gotoTrailScreen(); return true; }
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const char* ToolsScreen::ITEMS[5] = { "Ringtone Editor", "Auto-Reply Bot", "Nearby Nodes", "Auto-Advert", "Breadcrumb" };
|
const char* ToolsScreen::ITEMS[5] = { "Ringtone Editor", "Auto-Reply Bot", "Nearby Nodes", "Auto-Advert", "Trail" };
|
||||||
|
|||||||
+9
-9
@@ -1,23 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
// GPS breadcrumb viewer. Tools › Breadcrumb.
|
// GPS trail viewer. Tools › Trail.
|
||||||
// Phase 1: Summary view only. Phases 2/3 add Map and List views.
|
// Phase 1: Summary view only. Phases 2/3 add Map and List views.
|
||||||
// Included by UITask.cpp after Breadcrumb store + ToolsScreen.
|
// Included by UITask.cpp after Trail store + ToolsScreen.
|
||||||
|
|
||||||
#include "../Breadcrumb.h"
|
#include "../Trail.h"
|
||||||
|
|
||||||
class BreadcrumbScreen : public UIScreen {
|
class TrailScreen : public UIScreen {
|
||||||
UITask* _task;
|
UITask* _task;
|
||||||
BreadcrumbStore* _store;
|
TrailStore* _store;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BreadcrumbScreen(UITask* task, BreadcrumbStore* store) : _task(task), _store(store) {}
|
TrailScreen(UITask* task, TrailStore* store) : _task(task), _store(store) {}
|
||||||
|
|
||||||
void enter() { /* nothing to reset; live trail stays */ }
|
void enter() { /* nothing to reset; live trail stays */ }
|
||||||
|
|
||||||
int render(DisplayDriver& display) override {
|
int render(DisplayDriver& display) override {
|
||||||
display.setTextSize(1);
|
display.setTextSize(1);
|
||||||
display.setColor(DisplayDriver::LIGHT);
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
display.drawTextCentered(display.width() / 2, 0, "BREADCRUMB");
|
display.drawTextCentered(display.width() / 2, 0, "TRAIL");
|
||||||
display.fillRect(0, display.headerH() - 1, display.width(), display.sepH());
|
display.fillRect(0, display.headerH() - 1, display.width(), display.sepH());
|
||||||
|
|
||||||
const int y0 = display.listStart();
|
const int y0 = display.listStart();
|
||||||
@@ -31,7 +31,7 @@ public:
|
|||||||
display.setCursor(2, y0);
|
display.setCursor(2, y0);
|
||||||
display.print(buf);
|
display.print(buf);
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "Points: %d / %d", _store->count(), BreadcrumbStore::CAPACITY);
|
snprintf(buf, sizeof(buf), "Points: %d / %d", _store->count(), TrailStore::CAPACITY);
|
||||||
display.setCursor(2, y0 + step);
|
display.setCursor(2, y0 + step);
|
||||||
display.print(buf);
|
display.print(buf);
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ static const int QUICK_MSGS_MAX = 10;
|
|||||||
#include "NearbyScreen.h"
|
#include "NearbyScreen.h"
|
||||||
#include "DashboardConfigScreen.h"
|
#include "DashboardConfigScreen.h"
|
||||||
#include "AutoAdvertScreen.h"
|
#include "AutoAdvertScreen.h"
|
||||||
#include "BreadcrumbScreen.h"
|
#include "TrailScreen.h"
|
||||||
#include "ToolsScreen.h"
|
#include "ToolsScreen.h"
|
||||||
|
|
||||||
// ── HomeScreen ────────────────────────────────────────────────────────────────
|
// ── HomeScreen ────────────────────────────────────────────────────────────────
|
||||||
@@ -403,8 +403,8 @@ class HomeScreen : public UIScreen {
|
|||||||
leftmostX = aX - 1;
|
leftmostX = aX - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "G" indicator — GPS breadcrumb logging active. Same blink convention.
|
// "G" indicator — GPS trail logging active. Same blink convention.
|
||||||
if (_task->breadcrumb().isActive()) {
|
if (_task->trail().isActive()) {
|
||||||
int gX = leftmostX - ind;
|
int gX = leftmostX - ind;
|
||||||
bool show_g = Features::BLINK_INDICATORS ? ((millis() % 4000) < 2000) : true;
|
bool show_g = Features::BLINK_INDICATORS ? ((millis() % 4000) < 2000) : true;
|
||||||
if (show_g) {
|
if (show_g) {
|
||||||
@@ -1088,7 +1088,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
|
|||||||
nearby_screen = new NearbyScreen(this);
|
nearby_screen = new NearbyScreen(this);
|
||||||
dashboard_config = new DashboardConfigScreen(this, node_prefs);
|
dashboard_config = new DashboardConfigScreen(this, node_prefs);
|
||||||
auto_advert_screen = new AutoAdvertScreen(this, node_prefs);
|
auto_advert_screen = new AutoAdvertScreen(this, node_prefs);
|
||||||
breadcrumb_screen = new BreadcrumbScreen(this, &_breadcrumb);
|
trail_screen = new TrailScreen(this, &_trail);
|
||||||
applyBrightness();
|
applyBrightness();
|
||||||
applyFont();
|
applyFont();
|
||||||
applyRotation();
|
applyRotation();
|
||||||
@@ -1125,9 +1125,9 @@ void UITask::gotoDashboardConfig() {
|
|||||||
setCurrScreen(dashboard_config);
|
setCurrScreen(dashboard_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UITask::gotoBreadcrumbScreen() {
|
void UITask::gotoTrailScreen() {
|
||||||
((BreadcrumbScreen*)breadcrumb_screen)->enter();
|
((TrailScreen*)trail_screen)->enter();
|
||||||
setCurrScreen(breadcrumb_screen);
|
setCurrScreen(trail_screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UITask::gotoAutoAdvertScreen() {
|
void UITask::gotoAutoAdvertScreen() {
|
||||||
@@ -1747,19 +1747,19 @@ void UITask::loop() {
|
|||||||
next_batt_chck = millis() + 8000;
|
next_batt_chck = millis() + 8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GPS breadcrumb sampling — runs in the background while the trail is
|
// GPS trail sampling — runs in the background while the trail is
|
||||||
// active, independent of which screen is shown. Skips silently if no GPS
|
// active, independent of which screen is shown. Skips silently if no GPS
|
||||||
// fix; min-delta gate inside addPoint() avoids near-stationary spam.
|
// fix; min-delta gate inside addPoint() avoids near-stationary spam.
|
||||||
if (_breadcrumb.isActive() && _node_prefs != NULL
|
if (_trail.isActive() && _node_prefs != NULL
|
||||||
&& (int32_t)(millis() - _next_breadcrumb_sample_ms) >= 0) {
|
&& (int32_t)(millis() - _next_trail_sample_ms) >= 0) {
|
||||||
uint16_t interval_s = BreadcrumbStore::intervalSecs(_node_prefs->breadcrumb_interval_idx);
|
uint16_t interval_s = TrailStore::intervalSecs(_node_prefs->trail_interval_idx);
|
||||||
_next_breadcrumb_sample_ms = millis() + (uint32_t)interval_s * 1000UL;
|
_next_trail_sample_ms = millis() + (uint32_t)interval_s * 1000UL;
|
||||||
LocationProvider* loc = _sensors ? _sensors->getLocationProvider() : nullptr;
|
LocationProvider* loc = _sensors ? _sensors->getLocationProvider() : nullptr;
|
||||||
if (loc && loc->isValid()) {
|
if (loc && loc->isValid()) {
|
||||||
uint16_t md = BreadcrumbStore::minDeltaMeters(_node_prefs->breadcrumb_min_delta_idx);
|
uint16_t md = TrailStore::minDeltaMeters(_node_prefs->trail_min_delta_idx);
|
||||||
_breadcrumb.addPoint((int32_t)loc->getLatitude(),
|
_trail.addPoint((int32_t)loc->getLatitude(),
|
||||||
(int32_t)loc->getLongitude(),
|
(int32_t)loc->getLongitude(),
|
||||||
(uint32_t)rtc_clock.getCurrentTime(), md);
|
(uint32_t)rtc_clock.getCurrentTime(), md);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "../AbstractUITask.h"
|
#include "../AbstractUITask.h"
|
||||||
#include "../NodePrefs.h"
|
#include "../NodePrefs.h"
|
||||||
#include "../Breadcrumb.h"
|
#include "../Trail.h"
|
||||||
|
|
||||||
class UITask : public AbstractUITask {
|
class UITask : public AbstractUITask {
|
||||||
DisplayDriver* _display;
|
DisplayDriver* _display;
|
||||||
@@ -74,11 +74,11 @@ class UITask : public AbstractUITask {
|
|||||||
UIScreen* nearby_screen;
|
UIScreen* nearby_screen;
|
||||||
UIScreen* dashboard_config;
|
UIScreen* dashboard_config;
|
||||||
UIScreen* auto_advert_screen;
|
UIScreen* auto_advert_screen;
|
||||||
UIScreen* breadcrumb_screen;
|
UIScreen* trail_screen;
|
||||||
UIScreen* curr;
|
UIScreen* curr;
|
||||||
CayenneLPP _dash_lpp;
|
CayenneLPP _dash_lpp;
|
||||||
BreadcrumbStore _breadcrumb;
|
TrailStore _trail;
|
||||||
uint32_t _next_breadcrumb_sample_ms = 0;
|
uint32_t _next_trail_sample_ms = 0;
|
||||||
|
|
||||||
void userLedHandler();
|
void userLedHandler();
|
||||||
|
|
||||||
@@ -121,8 +121,8 @@ public:
|
|||||||
void gotoNearbyScreen();
|
void gotoNearbyScreen();
|
||||||
void gotoDashboardConfig();
|
void gotoDashboardConfig();
|
||||||
void gotoAutoAdvertScreen();
|
void gotoAutoAdvertScreen();
|
||||||
void gotoBreadcrumbScreen();
|
void gotoTrailScreen();
|
||||||
BreadcrumbStore& breadcrumb() { return _breadcrumb; }
|
TrailStore& trail() { return _trail; }
|
||||||
void playMelody(const char* melody);
|
void playMelody(const char* melody);
|
||||||
void stopMelody();
|
void stopMelody();
|
||||||
bool isMelodyPlaying();
|
bool isMelodyPlaying();
|
||||||
|
|||||||
Reference in New Issue
Block a user