From 10ea0d83992675fb69fbf8e681bedc44cd92def9 Mon Sep 17 00:00:00 2001 From: Ruben Laban Date: Wed, 24 Jun 2026 11:11:56 +0200 Subject: [PATCH] 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. --- src/ui-touch/UITask.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/ui-touch/UITask.cpp b/src/ui-touch/UITask.cpp index f5fd06c..149eccc 100644 --- a/src/ui-touch/UITask.cpp +++ b/src/ui-touch/UITask.cpp @@ -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);