diff --git a/docs/solo_features/tools_screen/tools_screen.md b/docs/solo_features/tools_screen/tools_screen.md index dbb6a483..4673c5c1 100644 --- a/docs/solo_features/tools_screen/tools_screen.md +++ b/docs/solo_features/tools_screen/tools_screen.md @@ -104,7 +104,7 @@ Cycle views with **LEFT / RIGHT**: | Item | Action | | --------------------- | --------------------------------------------------- | -| Start / Stop tracking | Begin or end a recording session | +| Start / Stop tracking | Begin or end a recording session. If **GPS is off**, choosing Start asks **"GPS is off — Enable GPS & start"** so a session can't silently run with nothing to record | | Mark here | Drop a waypoint at the current GPS fix (see below) | | Waypoints… | Open the waypoint list / navigation / add-by-coords | | Share my pos | Send your current position as a one-shot `[LOC]` message — pick a contact or channel (see **Live Share**) | diff --git a/examples/companion_radio/ui-new/TrailScreen.h b/examples/companion_radio/ui-new/TrailScreen.h index d2ca5b27..fc3b05eb 100644 --- a/examples/companion_radio/ui-new/TrailScreen.h +++ b/examples/companion_radio/ui-new/TrailScreen.h @@ -79,7 +79,7 @@ class TrailScreen : public UIScreen { // correctly (settings rows cycle with LEFT/RIGHT; everything else is Enter). // Live-share *config* lives in its own tool (Tools › Live Share); the map only // keeps the one-shot "Share my pos" action. - enum MenuLevel { ML_MAIN, ML_FILE, ML_SETTINGS }; + enum MenuLevel { ML_MAIN, ML_FILE, ML_SETTINGS, ML_CONFIRM_GPS }; PopupMenu _action_menu; uint8_t _menu_level = ML_MAIN; uint8_t _act_map[16]; // max rows on any one level; pushAction guards the cap @@ -152,6 +152,16 @@ public: } auto res = _action_menu.handleInput(c); if (res == PopupMenu::SELECTED) { + // GPS-off confirmation popup: rows aren't ActionIds, route by level. + if (_menu_level == ML_CONFIRM_GPS) { + if (_action_menu.selectedIndex() == 0) { // "Enable GPS & start" + _task->toggleGPS(); // off → on (persists, shows GPS alert) + _store->setActive(true); + _task->showAlert("GPS on, tracking started", 1200); + } + _menu_level = ML_MAIN; // popup already closed by handleInput() + return true; + } int sel = _action_menu.selectedIndex(); ActionId act = (sel >= 0 && sel < _act_count) ? (ActionId)_act_map[sel] : ACT_TOGGLE; switch (act) { @@ -163,7 +173,16 @@ public: case ACT_GRID: case ACT_AUTOPAUSE: cycleSetting(act, 1); reopenSettingsAt(sel); return true; case ACT_SHARE_NOW: shareMyLocationNow(); break; - case ACT_TOGGLE: handleToggle(); break; + case ACT_TOGGLE: + // Starting a trail with GPS switched off logs nothing and just + // sits on "Waiting for GPS fix" forever -- prompt to enable it + // first (only on boards that actually have a toggleable GPS). + if (!_store->isActive() && _task->hasGPS() && !_task->getGPSState()) { + buildGpsConfirmMenu(); + return true; + } + handleToggle(); + break; case ACT_MARK: _wp.markHere(); break; case ACT_WAYPOINTS: _wp.openList(); break; case ACT_SAVE: handleSave(); break; @@ -330,6 +349,16 @@ private: pushAction(ACT_SETTINGS, "Settings..."); } + // Confirmation shown when "Start tracking" is chosen with GPS off. Rows are + // plain (not ActionIds); handled by _menu_level in the SELECTED branch. + void buildGpsConfirmMenu() { + _menu_level = ML_CONFIRM_GPS; + _act_count = 0; + _action_menu.begin("GPS is off", 2); + _action_menu.addItem("Enable GPS & start"); + _action_menu.addItem("Cancel"); + } + // Trail-file submenu — only the operations that make sense right now. void buildFileMenu() { _menu_level = ML_FILE; diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 48628e08..51030eaf 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -2616,6 +2616,16 @@ bool UITask::getGPSState() { return false; } +bool UITask::hasGPS() { + if (_sensors != NULL) { + int num = _sensors->getNumSettings(); + for (int i = 0; i < num; i++) { + if (strcmp(_sensors->getSettingName(i), "gps") == 0) return true; + } + } + return false; +} + void UITask::toggleGPS() { if (_sensors != NULL) { // toggle GPS on/off diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index 154429e1..39908e85 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -323,6 +323,7 @@ public: void cycleBuzzerMode(); // ON → OFF → Auto → ON int getBuzzerMode(); // 0=ON, 1=OFF, 2=Auto bool getGPSState(); + bool hasGPS(); // true if this board exposes a toggleable GPS (distinct from GPS being off) void toggleGPS(); void applyBrightness(); void setBrightnessLevel(uint8_t level); diff --git a/release-notes.md b/release-notes.md index 0ae0a7e5..d6a43596 100644 --- a/release-notes.md +++ b/release-notes.md @@ -21,6 +21,7 @@ - **Nearby Nodes** — live `[LOC]` senders now respect the type filter and sort by their shared position; the distance-sorted list refreshes so live shares bubble to the top. - **Map** — live contacts are labelled before waypoints, so a person's name shows rather than a nearby waypoint's. - **GPS status icon** is hidden when GPS is turned off in Settings, instead of sitting there empty. +- **Trail — start with GPS off** now prompts **"GPS is off — Enable GPS & start"** instead of silently starting a session that shows "Waiting for GPS fix" forever and records nothing. - Null-guarded the Locator target picker and clamped the loc-share channel index on load. ### Under the hood