fix(ui): standardize context menu cycling + PopupMenu height clamping

PopupMenu:
- _cap now uses max_by_height as a hard ceiling (never draw outside screen).
  Previously max(_visible, max_by_height) let callers exceed the screen on
  OLED 64px. Now: OLED→4 items, landscape e-ink→10, portrait e-ink→22.

QuickMsgScreen:
- Contact context menu: Notif and Melody cycle with LEFT/RIGHT in-place;
  ENTER closes without re-cycling.
- Channel context menu: Notif, Melody and Fav same pattern.

RingtoneEditorScreen:
- Migrated from bespoke menu to PopupMenu (same pattern as everywhere else).
- Duration (1/4…1/32) and BPM (60…180) are now single rows that cycle with
  LEFT/RIGHT; separate BPM+/BPM- rows removed.
- Fixed _menu_dur_label buffer too small for "Duration: 1/16" (14→16 bytes).

NearbyScreen:
- Removed redundant "Back" item from context menu (Cancel key navigates back).

TrailScreen:
- Grid toggle responds to LEFT/RIGHT in addition to ENTER.
- Export labels: "Export GPX (live/saved)" → "Export (live/saved)" to fit PM_BW.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-05-29 00:25:02 +02:00
co-authored by Claude Sonnet 4.6
parent 5caac0b693
commit db8c52ea9a
5 changed files with 178 additions and 165 deletions
@@ -80,6 +80,7 @@ public:
int dir = (c == KEY_RIGHT || c == KEY_NEXT) ? 1 : -1;
if (_act_map[idx] == ACT_MIN_DIST && p) { cycleMinDelta(p, dir); _cfg_dirty = true; refreshActionLabels(); return true; }
if (_act_map[idx] == ACT_UNITS && p) { cycleUnits(p, dir); _cfg_dirty = true; refreshActionLabels(); return true; }
if (_act_map[idx] == ACT_GRID) { _map_grid = !_map_grid; refreshActionLabels(); return true; }
}
return true; // swallow on action rows
}
@@ -229,10 +230,10 @@ private:
_act_map[_act_count++] = ACT_LOAD; _action_menu.addItem("Load trail");
}
if (!_store->empty()) {
_act_map[_act_count++] = ACT_EXPORT; _action_menu.addItem("Export GPX (live)");
_act_map[_act_count++] = ACT_EXPORT; _action_menu.addItem("Export (live)");
}
if (saved) {
_act_map[_act_count++] = ACT_EXPORT_SAVED; _action_menu.addItem("Export GPX (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");