feat(l2): long trails with a card copy; map follow and redraw fixes

Trail on the L2: 32768 points every 5 m, no simplification, no point
spacing setting; copied to the card every minute and restored at power-on.
The line keeps up with the position dot (incremental sync, pending point).

Map: a tap's finger jitter no longer turns follow off; the GPS button
shows when the map follows. The trail is drawn as one polyline with
breaks and off-view chunks skipped (an lv_line queued a draw task per
point).

Fewer rebuilds: conversation bubbles patched (new messages, delivery
marks), home mini-map dots reused, Nearby rows rewritten in place,
history read in runs and each file opened once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-09-29 22:02:49 +02:00
co-authored by Claude Opus 5.5
parent 5f6cbe34b3
commit b3b77a1f6d
15 changed files with 601 additions and 188 deletions
@@ -61,9 +61,11 @@ struct Setting {
};
// ── Value labels ──────────────────────────────────────────────────────────────
#ifndef TRAIL_FIXED_MIN_DELTA_M
static void optMinDelta(uint8_t v, char* b, int n, const NodePrefs& p) {
snprintf(b, n, "%s", TrailStore::minDeltaLabel(v, p.units_imperial));
}
#endif
static void optAutoPause(uint8_t v, char* b, int n, const NodePrefs&) {
uint16_t s = NodePrefs::trailAutoPauseSecs(v);
if (s == 0) snprintf(b, n, "Off"); else snprintf(b, n, "%u min", (unsigned)(s / 60));
@@ -160,8 +162,10 @@ static void applySound(UiCore& c) { c.host()->applySoundPrefs(); }
#define SW(label, hint, sec, f, chg) { label, hint, sec, NP_OFF(f), 2, nullptr, chg, nullptr, 1 }
#define MAP(label, hint, sec, f, vals, opt, chg) { label, hint, sec, NP_OFF(f), COUNT_OF(vals), opt, chg, vals, NP_SIZE(f) }
static const Setting ALL[] = {
#ifndef TRAIL_FIXED_MIN_DELTA_M // else every sample past a fixed jitter gate is kept
IDX("Point spacing", "Between trail points", SEC_TRAIL, trail_min_delta_idx,
TrailStore::MIN_DELTA_COUNT, optMinDelta, nullptr),
#endif
IDX("Auto-pause", "Pause when standing still", SEC_TRAIL, trail_autopause_idx,
NodePrefs::TRAIL_AUTOPAUSE_COUNT, optAutoPause, nullptr),
SW("Save on low battery", "Save it on low battery", SEC_TRAIL, trail_autosave_lowbatt, nullptr),
@@ -21,7 +21,11 @@ public:
_next_sample_ms = millis() + (uint32_t)TrailStore::SAMPLING_SECS * 1000UL;
int32_t la, lo;
if (!_course->currentLocation(la, lo)) return;
#ifdef TRAIL_FIXED_MIN_DELTA_M // no point spacing setting: a fixed GPS-jitter gate (the L2)
uint16_t md = TRAIL_FIXED_MIN_DELTA_M;
#else
uint16_t md = TrailStore::minDeltaMeters(_prefs->trail_min_delta_idx, _prefs->units_imperial);
#endif
// Auto-pause: freeze the trail once the device has stayed within
// TRAIL_AUTOPAUSE_MOVE_M of one spot for the configured delay; resume on
// the next real move. Its own coarse gate (not the trail min-delta) so