touch: fix contact action sheet overflow on landscape display

The grid_items count missed the conditional "Show on map" button,
causing the card height to be calculated short when the contact has a
GPS fix. Additionally, on landscape displays (sh=240) the backdrop is
only 218px, which repeater cards with many buttons already exceeded.

Fix both: pre-check the GPS condition and include it in grid_items,
and cap the card's displayed height to the available backdrop space
with vertical scroll enabled when the content overflows. The close
badge is FLOATING so it stays anchored regardless of scroll position.
This commit is contained in:
Ruben Laban committed 2026-06-24 11:11:56 +02:00
1 parent 4e3c212a89
commit 10ea0d8399
1 file changed
+19 -11
+19 -11
View File
@@ -10353,16 +10353,25 @@ static void openContactActionSheet(uint32_t mesh_idx, bool is_repeater, const ch
has_los = peer_gps && self_gps;
}
#endif
bool has_map_btn = false;
if (!from_map) {
ContactInfo _mc;
has_map_btn = the_mesh.getContactByIdx(mesh_idx, _mc) && (_mc.gps_lat != 0 || _mc.gps_lon != 0);
}
// Everything except Delete goes in a 2-column grid; Delete is a full-width
// bottom row. Grid items = msg/ping + telemetry + range + favorite + reset +
// block (6), + trace/admin for repeaters (2), + Join for rooms (1), +
// line-of-sight (1).
const int grid_items = (from_map ? 5 : 6) + (is_repeater ? 2 : 0) + (is_room ? 1 : 0) + (has_los ? 1 : 0);
// line-of-sight (1), + Show on map (1 when contact has GPS and !from_map).
const int grid_items = (from_map ? 5 : 6) + (is_repeater ? 2 : 0) + (is_room ? 1 : 0) + (has_los ? 1 : 0) + (has_map_btn ? 1 : 0);
const int grid_rows = (grid_items + 1) / 2; // ceil
const int card_h = title_h + (grid_rows + 1) * (btn_h + btn_gap) + padding;
// On landscape displays (sh=240) the backdrop is only 218px; cap the card
// to that space and let it scroll vertically when buttons overflow.
const int avail_card_h = sh - STATUSBAR_H - 4;
const int capped_card_h = LV_MIN(card_h, avail_card_h);
lv_obj_t* card = lv_obj_create(s_action_sheet_root);
lv_obj_remove_style_all(card);
lv_obj_set_size(card, card_w, card_h);
lv_obj_set_size(card, card_w, capped_card_h);
lv_obj_align(card, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_style_bg_color(card, lv_color_hex(COLOR_PANEL), LV_PART_MAIN);
lv_obj_set_style_bg_opa(card, LV_OPA_COVER, LV_PART_MAIN);
@@ -10370,7 +10379,11 @@ static void openContactActionSheet(uint32_t mesh_idx, bool is_repeater, const ch
lv_obj_set_style_border_color(card, lv_color_hex(0x18191A), LV_PART_MAIN);
lv_obj_set_style_border_width(card, 1, LV_PART_MAIN);
lv_obj_set_style_pad_all(card, padding, LV_PART_MAIN);
lv_obj_clear_flag(card, LV_OBJ_FLAG_SCROLLABLE);
if (card_h > capped_card_h) {
lv_obj_set_scroll_dir(card, LV_DIR_VER);
} else {
lv_obj_clear_flag(card, LV_OBJ_FLAG_SCROLLABLE);
}
addCloseXBadge(card, actionSheetCloseCb);
lv_obj_t* title = lv_label_create(card);
@@ -10440,13 +10453,8 @@ static void openContactActionSheet(uint32_t mesh_idx, bool is_repeater, const ch
mk_btn(LV_SYMBOL_ENVELOPE " Message", actionSheetSendMsgCb, 0);
}
mk_btn(LV_SYMBOL_BATTERY_3 " Telemetry", actionSheetTelemetryCb, 0);
// Show on map — only when the contact has a location, and not when the sheet
// was opened from the map (you're already there).
if (!from_map) {
ContactInfo _mc;
if (the_mesh.getContactByIdx(s_action_sheet_mesh_idx, _mc) && (_mc.gps_lat != 0 || _mc.gps_lon != 0))
mk_btn(LV_SYMBOL_GPS " Show on map", actionSheetShowOnMapCb, 0);
}
if (has_map_btn)
mk_btn(LV_SYMBOL_GPS " Show on map", actionSheetShowOnMapCb, 0);
if (is_repeater) {
mk_btn(LV_SYMBOL_GPS " Trace SNR", actionSheetTracePingCb, 0);
mk_btn(LV_SYMBOL_SETTINGS " Admin", actionSheetAdminCb, 0);