Auto update ext apps (#3046)

* first naive impl

* Unregister sdcard notification

* btngrid reload_items fixed

* format-code

* Avoid some unnecessary updates

* clear empty space after removing items

* Fix displaying sdcard error after inserting card while running

* format code

* Eliminate multiple update_items() calls from on_populate()
And call it only once after on_populate()

* update_items() only once when showing btngrid

* normalize offset when menu item count decreases
This commit is contained in:
E.T.
2026-03-02 12:35:45 +01:00
committed by GitHub
parent 6b663894b0
commit f489d43259
3 changed files with 46 additions and 17 deletions
+34 -5
View File
@@ -26,6 +26,7 @@
#include "ui_btngrid.hpp"
#include "rtc_time.hpp"
#include "sd_card.hpp"
namespace ui {
@@ -143,6 +144,7 @@ void BtnGridView::clear() {
// clear vector and release memory, not using swap since it's causing capture to glitch/fault
menu_items.clear();
// TODO(u-foka): Clean up my mess, move this somewhere to clear memory when the view is not visible, but not to be confused with clearing the menu items...
for (auto& item : menu_item_views)
remove_child(item.get());
@@ -198,6 +200,15 @@ void BtnGridView::show_hide_arrows() {
}
}
void BtnGridView::reload_items() {
menu_items.clear();
on_populate();
set_highlighted(highlighted_item, true);
show_hide_arrows();
set_dirty(); // Redraw the now potentially empty space as well
}
void BtnGridView::update_items() {
size_t i = 0;
@@ -237,7 +248,7 @@ void BtnGridView::show_arrows_enabled(bool enabled) {
}
}
bool BtnGridView::set_highlighted(int32_t new_value) {
bool BtnGridView::set_highlighted(int32_t new_value, bool force_update) {
int32_t item_count = (int32_t)menu_items.size();
if (new_value < 0)
@@ -247,13 +258,15 @@ bool BtnGridView::set_highlighted(int32_t new_value) {
new_value = item_count - 1;
}
bool needs_update = false;
if (((uint32_t)new_value > offset) && ((new_value - offset) >= displayed_max)) {
// Shift BtnGridView up
highlighted_item = new_value;
// rounding up new offset to next multiple of rows
offset = new_value - displayed_max + rows_;
offset -= (offset % rows_);
update_items();
needs_update = true;
// refresh whole screen (display flickers) only if scrolling last row up and a blank button is needed at the bottom
if ((new_value + rows_ >= item_count) && (item_count % rows_) != 0)
set_dirty();
@@ -261,13 +274,23 @@ bool BtnGridView::set_highlighted(int32_t new_value) {
// Shift BtnGridView down
highlighted_item = new_value;
offset = (new_value / rows_) * rows_;
update_items();
needs_update = true;
// no need to set_dirty() here since all buttons have been repainted
} else {
// Just update highlight
highlighted_item = new_value;
}
// Normalize offset to show maximum items when count decreased
if (offset + displayed_max > item_count && item_count > 0) {
offset = (item_count >= displayed_max) ? item_count - displayed_max : 0;
needs_update = true;
}
if (needs_update || force_update) {
update_items();
}
if (visible())
item_view(highlighted_item - offset)->focus();
@@ -292,12 +315,18 @@ void BtnGridView::on_blur() {
}
void BtnGridView::on_show() {
on_populate();
View::on_show();
set_highlighted(highlighted_item);
sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status /*status*/) {
this->reload_items();
};
reload_items();
}
void BtnGridView::on_hide() {
sd_card::status_signal -= sd_card_status_signal_token;
View::on_hide();
clear();
set_arrow_up_enabled(false);
+3 -1
View File
@@ -71,7 +71,7 @@ class BtnGridView : public View {
bool show_arrows{true}; // flag used to hide arrows in main menu
void show_arrows_enabled(bool enabled);
bool set_highlighted(int32_t new_value);
bool set_highlighted(int32_t new_value, bool force_update = false);
uint32_t highlighted_index();
void set_parent_rect(const Rect new_parent_rect) override;
@@ -88,6 +88,7 @@ class BtnGridView : public View {
bool on_encoder(const EncoderEvent event) override;
bool blacklisted_app(GridItem new_item);
void reload_items();
void update_items();
void set_btn_height_fixed(uint8_t h) {
button_h = h;
@@ -116,6 +117,7 @@ class BtnGridView : public View {
size_t displayed_max{0};
size_t highlighted_item{0};
size_t offset{0};
SignalToken sd_card_status_signal_token{};
};
} /* namespace ui */
+9 -11
View File
@@ -771,8 +771,6 @@ void add_apps(NavigationView& nav, BtnGridView& grid, app_location_t loc) {
true);
}
};
grid.update_items();
}
// clang-format off
@@ -789,7 +787,7 @@ void add_external_items(NavigationView& nav, app_location_t location, BtnGridVie
"Check SD card\n"
"Update SD card content\n");
}},
error_tile_pos);
error_tile_pos, true);
} else {
std::sort(externalItems.begin(), externalItems.end(), [](const auto &a, const auto &b)
{
@@ -804,8 +802,6 @@ void add_external_items(NavigationView& nav, app_location_t location, BtnGridVie
}
}
grid.update_items();
}
}
// clang-format on
@@ -824,7 +820,8 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav)
void ReceiversMenuView::on_populate() {
bool return_icon = pmem::show_gui_return_icon();
if (return_icon) {
add_item({"..", Theme::getInstance()->fg_light->foreground, &bitmap_icon_previous, [this]() { nav_.pop(); }});
add_item({"..", Theme::getInstance()->fg_light->foreground, &bitmap_icon_previous, [this]() { nav_.pop(); }},
true);
}
add_apps(nav_, *this, RX);
add_external_items(nav_, app_location_t::RX, *this, return_icon ? 1 : 0);
@@ -913,14 +910,15 @@ SystemMenuView::SystemMenuView(NavigationView& nav)
}
void SystemMenuView::on_populate() {
if (!verify_sdcard_format()) {
add_item({"SDCard Error", Theme::getInstance()->error_dark->foreground, nullptr, [this]() {
nav_.display_modal("Error", "SD Card is not exFAT/FAT32");
}});
}
add_apps(nav_, *this, HOME);
add_external_items(nav_, app_location_t::HOME, *this, 0);
add_item({"HackRF", Theme::getInstance()->fg_cyan->foreground, &bitmap_icon_hackrf, [this]() { hackrf_mode(nav_); }});
if (!verify_sdcard_format()) { // Moved to the end... after sd status change event, fstype wasn't populated fast enough..
insert_item({"SDCard Error", Theme::getInstance()->error_dark->foreground, nullptr, [this]() {
nav_.display_modal("Error", "SD Card is not exFAT/FAT32");
}},
0, true);
}
}
/* SystemView ************************************************************/