diff --git a/firmware/application/external/acars_rx/main.cpp b/firmware/application/external/acars_rx/main.cpp index 50b53c1e..d11adcb8 100644 --- a/firmware/application/external/acars_rx/main.cpp +++ b/firmware/application/external/acars_rx/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_acars_rx.application_information"), us }, /*.icon_color = */ ui::Color::orange().v, /*.menu_location = */ app_location_t::RX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_acars */ {'P', 'A', 'C', 'A'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/adsbtx/main.cpp b/firmware/application/external/adsbtx/main.cpp index bb9e0ef9..9506211f 100644 --- a/firmware/application/external/adsbtx/main.cpp +++ b/firmware/application/external/adsbtx/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_adsbtx.application_information"), used }, /*.icon_color = */ ui::Color::green().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_adsbtx */ {'P', 'A', 'D', 'T'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/afsk_rx/main.cpp b/firmware/application/external/afsk_rx/main.cpp index aa2b3341..ca1a7cfc 100644 --- a/firmware/application/external/afsk_rx/main.cpp +++ b/firmware/application/external/afsk_rx/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_afsk_rx.application_information"), use }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::RX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_afsk_rx */ {'P', 'A', 'F', 'R'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/analogtv/main.cpp b/firmware/application/external/analogtv/main.cpp index 92ff6135..0106a091 100644 --- a/firmware/application/external/analogtv/main.cpp +++ b/firmware/application/external/analogtv/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_analogtv.application_information"), us }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::RX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_am_tv */ {'P', 'A', 'M', 'T'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/audio_test/main.cpp b/firmware/application/external/audio_test/main.cpp index 48554ce1..79003140 100644 --- a/firmware/application/external/audio_test/main.cpp +++ b/firmware/application/external/audio_test/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_audio_test.application_information"), }, /*.icon_color = */ ui::Color::cyan().v, /*.menu_location = */ app_location_t::DEBUG, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_none */ {'P', 'A', 'B', 'P'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/blespam/main.cpp b/firmware/application/external/blespam/main.cpp index aa8e8b2a..d58beb99 100644 --- a/firmware/application/external/blespam/main.cpp +++ b/firmware/application/external/blespam/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_blespam.application_information"), use }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_btle_tx */ {'P', 'B', 'T', 'T'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/calculator/main.cpp b/firmware/application/external/calculator/main.cpp index e03488b6..ebb2c985 100644 --- a/firmware/application/external/calculator/main.cpp +++ b/firmware/application/external/calculator/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_calculator.application_information"), }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::UTILITIES, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_none */ {0, 0, 0, 0}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/coasterp/main.cpp b/firmware/application/external/coasterp/main.cpp index a81d5888..0415f842 100644 --- a/firmware/application/external/coasterp/main.cpp +++ b/firmware/application/external/coasterp/main.cpp @@ -76,6 +76,7 @@ __attribute__((section(".external_app.app_coasterp.application_information"), us }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_fsktx */ {'P', 'F', 'S', 'K'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/cvs_spam/main.cpp b/firmware/application/external/cvs_spam/main.cpp index 9f35de18..b9ccb5f0 100644 --- a/firmware/application/external/cvs_spam/main.cpp +++ b/firmware/application/external/cvs_spam/main.cpp @@ -17,17 +17,18 @@ void initialize_app(NavigationView& nav) { extern "C" { __attribute__((section(".external_app.app_cvs_spam.application_information"), used)) application_information_t _application_information_cvs_spam = { - (uint8_t*)0x00000000, - ui::external_app::cvs_spam::initialize_app, - CURRENT_HEADER_VERSION, - VERSION_MD5, - "CVS Spam", - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81}, - ui::Color::red().v, - app_location_t::TX, - {'P', 'R', 'E', 'P'}, - 0x00000000}; + /*.memory_location = */ (uint8_t*)0x00000000, + /*.externalAppEntry = */ ui::external_app::cvs_spam::initialize_app, + /*.header_version = */ CURRENT_HEADER_VERSION, + /*.app_version = */ VERSION_MD5, + + /*.app_name = */ "CVS Spam", + /*.bitmap_data = */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81}, + /*.icon_color = */ ui::Color::red().v, + /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, + + /*.m4_app_tag = portapack::spi_flash::image_tag_afsk_rx */ {'P', 'R', 'E', 'P'}, + /*.m4_app_offset = */ 0x00000000, // will be filled at compile time +}; } \ No newline at end of file diff --git a/firmware/application/external/extsensors/main.cpp b/firmware/application/external/extsensors/main.cpp index 27926409..4597dd19 100644 --- a/firmware/application/external/extsensors/main.cpp +++ b/firmware/application/external/extsensors/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_extsensors.application_information"), }, /*.icon_color = */ ui::Color::orange().v, /*.menu_location = */ app_location_t::DEBUG, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_none */ {0, 0, 0, 0}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/flippertx/main.cpp b/firmware/application/external/flippertx/main.cpp index 48613d7a..3dde72c2 100644 --- a/firmware/application/external/flippertx/main.cpp +++ b/firmware/application/external/flippertx/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_flippertx.application_information"), u }, /*.icon_color = */ ui::Color::orange().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_ookstreaming */ {'P', 'O', 'S', 'K'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/font_viewer/main.cpp b/firmware/application/external/font_viewer/main.cpp index be07615c..7110a3d2 100644 --- a/firmware/application/external/font_viewer/main.cpp +++ b/firmware/application/external/font_viewer/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_font_viewer.application_information"), }, /*.icon_color = */ ui::Color::cyan().v, /*.menu_location = */ app_location_t::DEBUG, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_none */ {0, 0, 0, 0}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/foxhunt/main.cpp b/firmware/application/external/foxhunt/main.cpp index 1f652846..8aa239c0 100644 --- a/firmware/application/external/foxhunt/main.cpp +++ b/firmware/application/external/foxhunt/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_foxhunt_rx.application_information"), }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::RX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_am_audio */ {'P', 'A', 'M', 'A'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/gpssim/main.cpp b/firmware/application/external/gpssim/main.cpp index ebcfdd07..763bdbb7 100644 --- a/firmware/application/external/gpssim/main.cpp +++ b/firmware/application/external/gpssim/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_gpssim.application_information"), used }, /*.icon_color = */ ui::Color::green().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_gpssim */ {'P', 'G', 'P', 'S'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/jammer/main.cpp b/firmware/application/external/jammer/main.cpp index 8fe3403b..7c01ba0e 100644 --- a/firmware/application/external/jammer/main.cpp +++ b/firmware/application/external/jammer/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_jammer.application_information"), used }, /*.icon_color = */ ui::Color::green().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_jammer */ {'P', 'J', 'A', 'M'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/keyfob/main.cpp b/firmware/application/external/keyfob/main.cpp index 0c40554a..e12b2194 100644 --- a/firmware/application/external/keyfob/main.cpp +++ b/firmware/application/external/keyfob/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_keyfob.application_information"), used }, /*.icon_color = */ ui::Color::orange().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_keyfob */ {'P', 'O', 'O', 'K'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/lcr/main.cpp b/firmware/application/external/lcr/main.cpp index aa748af7..1d2b86e6 100644 --- a/firmware/application/external/lcr/main.cpp +++ b/firmware/application/external/lcr/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_lcr.application_information"), used)) }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_afsk */ {'P', 'A', 'F', 'T'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/lge/main.cpp b/firmware/application/external/lge/main.cpp index e09564e8..d2794a0f 100644 --- a/firmware/application/external/lge/main.cpp +++ b/firmware/application/external/lge/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_lge.application_information"), used)) }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_fsktx */ {'P', 'F', 'S', 'K'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/morse_tx/main.cpp b/firmware/application/external/morse_tx/main.cpp index a1d499a1..b591599f 100644 --- a/firmware/application/external/morse_tx/main.cpp +++ b/firmware/application/external/morse_tx/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_morse_tx.application_information"), us }, /*.icon_color = */ ui::Color::green().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_tones */ {'P', 'T', 'O', 'N'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/nrf_rx/main.cpp b/firmware/application/external/nrf_rx/main.cpp index 3a3f1369..f7a4912b 100644 --- a/firmware/application/external/nrf_rx/main.cpp +++ b/firmware/application/external/nrf_rx/main.cpp @@ -76,6 +76,7 @@ __attribute__((section(".external_app.app_nrf_rx.application_information"), used }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::RX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_nrf_rx */ {'P', 'N', 'R', 'R'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/ook_editor/main.cpp b/firmware/application/external/ook_editor/main.cpp index 98dd8097..39692a4a 100644 --- a/firmware/application/external/ook_editor/main.cpp +++ b/firmware/application/external/ook_editor/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_ook_editor.application_information"), }, /*.icon_color = */ ui::Color::orange().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_ook */ {'P', 'O', 'O', 'K'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/ookbrute/main.cpp b/firmware/application/external/ookbrute/main.cpp index 901ea305..e323fda2 100644 --- a/firmware/application/external/ookbrute/main.cpp +++ b/firmware/application/external/ookbrute/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_ookbrute.application_information"), us }, /*.icon_color = */ ui::Color::orange().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_ook */ {'P', 'O', 'O', 'K'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/protoview/main.cpp b/firmware/application/external/protoview/main.cpp index 403bef32..a32b8e1b 100644 --- a/firmware/application/external/protoview/main.cpp +++ b/firmware/application/external/protoview/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_protoview.application_information"), u }, /*.icon_color = */ ui::Color::orange().v, /*.menu_location = */ app_location_t::RX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_protoview */ {'P', 'P', 'V', 'W'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/random_password/main.cpp b/firmware/application/external/random_password/main.cpp index 4861914b..f92851e1 100644 --- a/firmware/application/external/random_password/main.cpp +++ b/firmware/application/external/random_password/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_random_password.application_informatio }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::UTILITIES, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_afsk_rx */ {'P', 'A', 'F', 'R'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/remote/main.cpp b/firmware/application/external/remote/main.cpp index af7e5bc3..358452a4 100644 --- a/firmware/application/external/remote/main.cpp +++ b/firmware/application/external/remote/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_remote.application_information"), used }, /*.icon_color = */ ui::Color::green().v, /*.menu_location = */ app_location_t::HOME, + /*.desired_menu_position = */ 4, /*.m4_app_tag = portapack::spi_flash::image_tag_replay */ {'P', 'R', 'E', 'P'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/shoppingcart_lock/main.cpp b/firmware/application/external/shoppingcart_lock/main.cpp index 3dad8ecf..7d7a6292 100644 --- a/firmware/application/external/shoppingcart_lock/main.cpp +++ b/firmware/application/external/shoppingcart_lock/main.cpp @@ -16,12 +16,13 @@ void initialize_app(NavigationView& nav) { extern "C" { __attribute__((section(".external_app.app_shoppingcart_lock.application_information"), used)) application_information_t _application_information_shoppingcart_lock = { - (uint8_t*)0x00000000, - ui::external_app::shoppingcart_lock::initialize_app, - CURRENT_HEADER_VERSION, - VERSION_MD5, - "Cart Lock", - { + /*.memory_location = */ (uint8_t*)0x00000000, + /*.externalAppEntry = */ ui::external_app::shoppingcart_lock::initialize_app, + /*.header_version = */ CURRENT_HEADER_VERSION, + /*.app_version = */ VERSION_MD5, + + /*.app_name = */ "Cart Lock", + /*.bitmap_data = */ { 0x00, 0x00, 0x00, @@ -55,9 +56,11 @@ __attribute__((section(".external_app.app_shoppingcart_lock.application_informat 0x7E, 0x00, }, - ui::Color::red().v, - app_location_t::UTILITIES, - {'P', 'A', 'T', 'X'}, - 0x00000000, + /*.icon_color = */ ui::Color::red().v, + /*.menu_location = */ app_location_t::UTILITIES, + /*.desired_menu_position = */ -1, + + /*.m4_app_tag = portapack::spi_flash::image_tag_afsk_rx */ {'P', 'A', 'T', 'X'}, + /*.m4_app_offset = */ 0x00000000, // will be filled at compile time }; } \ No newline at end of file diff --git a/firmware/application/external/spainter/main.cpp b/firmware/application/external/spainter/main.cpp index e9678fdd..b12817a6 100644 --- a/firmware/application/external/spainter/main.cpp +++ b/firmware/application/external/spainter/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_spainter.application_information"), us }, /*.icon_color = */ ui::Color::orange().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_spainter */ {'P', 'S', 'P', 'T'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/sstvtx/main.cpp b/firmware/application/external/sstvtx/main.cpp index 6a842ffc..887132ba 100644 --- a/firmware/application/external/sstvtx/main.cpp +++ b/firmware/application/external/sstvtx/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_sstvtx.application_information"), used }, /*.icon_color = */ ui::Color::green().v, /*.menu_location = */ app_location_t::TX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_sstvtx */ {'P', 'S', 'T', 'X'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/tetris/main.cpp b/firmware/application/external/tetris/main.cpp index f34a020f..fe66298a 100644 --- a/firmware/application/external/tetris/main.cpp +++ b/firmware/application/external/tetris/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_tetris.application_information"), used }, /*.icon_color = */ ui::Color::orange().v, /*.menu_location = */ app_location_t::UTILITIES, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_none */ {0, 0, 0, 0}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/tpmsrx/main.cpp b/firmware/application/external/tpmsrx/main.cpp index 7c4c4a04..552a14c0 100644 --- a/firmware/application/external/tpmsrx/main.cpp +++ b/firmware/application/external/tpmsrx/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_tpmsrx.application_information"), used }, /*.icon_color = */ ui::Color::green().v, /*.menu_location = */ app_location_t::RX, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_tpms */ {'P', 'T', 'P', 'M'}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/external/wardrivemap/main.cpp b/firmware/application/external/wardrivemap/main.cpp index fb5fb7eb..4da13113 100644 --- a/firmware/application/external/wardrivemap/main.cpp +++ b/firmware/application/external/wardrivemap/main.cpp @@ -75,6 +75,7 @@ __attribute__((section(".external_app.app_wardrivemap.application_information"), }, /*.icon_color = */ ui::Color::yellow().v, /*.menu_location = */ app_location_t::UTILITIES, + /*.desired_menu_position = */ -1, /*.m4_app_tag = portapack::spi_flash::image_tag_none */ {0, 0, 0, 0}, /*.m4_app_offset = */ 0x00000000, // will be filled at compile time diff --git a/firmware/application/ui/ui_btngrid.cpp b/firmware/application/ui/ui_btngrid.cpp index 8c6b60be..d9646c6a 100644 --- a/firmware/application/ui/ui_btngrid.cpp +++ b/firmware/application/ui/ui_btngrid.cpp @@ -118,30 +118,36 @@ void BtnGridView::clear() { menu_item_views.clear(); } -void BtnGridView::add_items(std::initializer_list new_items) { +void BtnGridView::add_items(std::initializer_list new_items, bool inhibit_update) { for (auto item : new_items) { if (!blacklisted_app(item)) menu_items.push_back(item); } - update_items(); -} - -void BtnGridView::add_item(GridItem new_item) { - if (!blacklisted_app(new_item)) { - menu_items.push_back(new_item); + if (!inhibit_update) { update_items(); } } -void BtnGridView::insert_item(GridItem new_item, uint8_t position) { +void BtnGridView::add_item(const GridItem& new_item, bool inhibit_update) { + if (!blacklisted_app(new_item)) { + menu_items.push_back(new_item); + if (!inhibit_update) { + update_items(); + } + } +} + +void BtnGridView::insert_item(const GridItem& new_item, size_t position, bool inhibit_update) { if (!blacklisted_app(new_item)) { if (position < menu_items.size()) { auto pos_iter = menu_items.begin() + position; menu_items.insert(pos_iter, new_item); - update_items(); } else { menu_items.push_back(new_item); + } + + if (!inhibit_update) { update_items(); } } diff --git a/firmware/application/ui/ui_btngrid.hpp b/firmware/application/ui/ui_btngrid.hpp index b20a3433..e862b2c7 100644 --- a/firmware/application/ui/ui_btngrid.hpp +++ b/firmware/application/ui/ui_btngrid.hpp @@ -59,9 +59,9 @@ class BtnGridView : public View { ~BtnGridView(); - void add_items(std::initializer_list new_items); - void add_item(GridItem new_item); - void insert_item(GridItem new_item, uint8_t position); + void add_items(std::initializer_list new_items, bool inhibit_update = false); + void add_item(const GridItem& new_item, bool inhibit_update = false); + void insert_item(const GridItem& new_item, size_t position, bool inhibit_update = false); void set_max_rows(int rows); int rows(); void clear(); @@ -81,12 +81,13 @@ class BtnGridView : public View { bool on_encoder(const EncoderEvent event) override; bool blacklisted_app(GridItem new_item); + void update_items(); + protected: virtual void on_populate() = 0; private: int rows_{3}; - void update_items(); void on_tick_second(); bool keep_highlight{false}; diff --git a/firmware/application/ui_external_items_menu_loader.cpp b/firmware/application/ui_external_items_menu_loader.cpp index 31a322e1..6ec1202b 100644 --- a/firmware/application/ui_external_items_menu_loader.cpp +++ b/firmware/application/ui_external_items_menu_loader.cpp @@ -97,10 +97,10 @@ namespace ui { } } -/* static */ std::vector ExternalItemsMenuLoader::load_external_items(app_location_t app_location, NavigationView& nav) { +/* static */ std::vector ExternalItemsMenuLoader::load_external_items(app_location_t app_location, NavigationView& nav) { bitmaps.clear(); - std::vector external_apps; + std::vector external_apps; auto dev = (i2cdev::I2cDev_PPmod*)i2cdev::I2CDevManager::get_dev_by_model(I2C_DEVMDL::I2CDECMDL_PPMOD); @@ -121,7 +121,7 @@ namespace ui { if (appInfo->header_version > CURRENT_STANDALONE_APPLICATION_API_VERSION) continue; - GridItem gridItem = {}; + GridItemEx gridItem = {}; gridItem.text = reinterpret_cast(&appInfo->app_name[0]); gridItem.color = Color((uint16_t)appInfo->icon_color); @@ -150,6 +150,8 @@ namespace ui { nav.display_modal("Error", "Unable to download app."); }; + gridItem.desired_position = -1; // TODO: Where should we put the module's app icon? First? Last? Also configurable? + external_apps.push_back(gridItem); } } @@ -180,7 +182,7 @@ namespace ui { bool versionMatches = VERSION_MD5 == application_information.app_version; - GridItem gridItem = {}; + GridItemEx gridItem = {}; gridItem.text = reinterpret_cast(&application_information.app_name[0]); if (versionMatches) { @@ -195,6 +197,8 @@ namespace ui { nav.display_modal("Error", "The .ppma file in your " + apps_dir.string() + "\nfolder can't be read. Please\nupdate your SD Card content."); } }; + + gridItem.desired_position = application_information.desired_menu_position; } else { gridItem.color = Theme::getInstance()->fg_light->foreground; @@ -203,6 +207,8 @@ namespace ui { gridItem.on_select = [&nav]() { nav.display_modal("Error", "The .ppma file in your " + apps_dir.string() + "\nfolder is outdated. Please\nupdate your SD Card content."); }; + + gridItem.desired_position = application_information.desired_menu_position; } external_apps.push_back(gridItem); @@ -228,7 +234,7 @@ namespace ui { if (application_information.header_version > CURRENT_STANDALONE_APPLICATION_API_VERSION) continue; - GridItem gridItem = {}; + GridItemEx gridItem = {}; gridItem.text = reinterpret_cast(&application_information.app_name[0]); gridItem.color = Color((uint16_t)application_information.icon_color); @@ -243,6 +249,8 @@ namespace ui { } }; + gridItem.desired_position = -1; // No desired position support for standalone apps yet + external_apps.push_back(gridItem); } diff --git a/firmware/application/ui_external_items_menu_loader.hpp b/firmware/application/ui_external_items_menu_loader.hpp index 3b547f1f..59695609 100644 --- a/firmware/application/ui_external_items_menu_loader.hpp +++ b/firmware/application/ui_external_items_menu_loader.hpp @@ -55,7 +55,11 @@ class DynamicBitmap { class ExternalItemsMenuLoader { public: - static std::vector load_external_items(app_location_t, NavigationView&); + struct GridItemEx : GridItem { + int32_t desired_position; + }; + + static std::vector load_external_items(app_location_t, NavigationView&); ExternalItemsMenuLoader() = delete; static bool run_external_app(ui::NavigationView&, std::filesystem::path); static bool run_standalone_app(ui::NavigationView&, std::filesystem::path); diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 1aeaf3f6..bfe1913c 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -752,13 +752,16 @@ static void add_apps(NavigationView& nav, BtnGridView& grid, app_location_t loc) grid.add_item({app.displayName, app.iconColor, app.icon, [&nav, &app]() { i2cdev::I2CDevManager::set_autoscan_interval(0); //if i navigate away from any menu, turn off autoscan - nav.push_view(std::unique_ptr(app.viewFactory->produce(nav))); }}); + nav.push_view(std::unique_ptr(app.viewFactory->produce(nav))); }}, + true); } }; + + grid.update_items(); } // clang-format off -void addExternalItems(NavigationView& nav, app_location_t location, BtnGridView& grid) { +void add_external_items(NavigationView& nav, app_location_t location, BtnGridView& grid, uint8_t notice_pos) { auto externalItems = ExternalItemsMenuLoader::load_external_items(location, nav); if (externalItems.empty()) { grid.insert_item({"Notice!", @@ -771,11 +774,23 @@ void addExternalItems(NavigationView& nav, app_location_t location, BtnGridView& "see Mayhem wiki and copy apps\n" "to " + apps_dir.string() + " folder of SD card."); }}, - pmem::show_gui_return_icon() ? 1 : 0); + notice_pos); } else { + std::sort(externalItems.begin(), externalItems.end(), [](const auto &a, const auto &b) + { + return a.desired_position < b.desired_position; + }); + for (auto const& gridItem : externalItems) { - grid.add_item(gridItem); + if (gridItem.desired_position < 0) { + grid.add_item(gridItem, true); + } else { + grid.insert_item(gridItem, gridItem.desired_position, true); + } + } + + grid.update_items(); } } // clang-format on @@ -786,13 +801,14 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) : nav_(nav) {} void ReceiversMenuView::on_populate() { - if (pmem::show_gui_return_icon()) { + 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_apps(nav_, *this, RX); - addExternalItems(nav_, app_location_t::RX, *this); + add_external_items(nav_, app_location_t::RX, *this, return_icon ? 1 : 0); } /* TransmittersMenuView **************************************************/ @@ -801,13 +817,14 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) : nav_(nav) {} void TransmittersMenuView::on_populate() { - if (pmem::show_gui_return_icon()) { + bool return_icon = pmem::show_gui_return_icon(); + if (return_icon) { add_items({{"..", Theme::getInstance()->fg_light->foreground, &bitmap_icon_previous, [this]() { nav_.pop(); }}}); } add_apps(nav_, *this, TX); - addExternalItems(nav_, app_location_t::TX, *this); + add_external_items(nav_, app_location_t::TX, *this, return_icon ? 1 : 0); } /* UtilitiesMenuView *****************************************************/ @@ -818,13 +835,14 @@ UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) } void UtilitiesMenuView::on_populate() { - if (pmem::show_gui_return_icon()) { + bool return_icon = pmem::show_gui_return_icon(); + if (return_icon) { add_items({{"..", Theme::getInstance()->fg_light->foreground, &bitmap_icon_previous, [this]() { nav_.pop(); }}}); } add_apps(nav_, *this, UTILITIES); - addExternalItems(nav_, app_location_t::UTILITIES, *this); + add_external_items(nav_, app_location_t::UTILITIES, *this, return_icon ? 1 : 0); } /* SystemMenuView ********************************************************/ @@ -849,7 +867,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) void SystemMenuView::on_populate() { add_apps(nav_, *this, HOME); - addExternalItems(nav_, app_location_t::HOME, *this); + add_external_items(nav_, app_location_t::HOME, *this, 2); add_item({"HackRF", Theme::getInstance()->fg_cyan->foreground, &bitmap_icon_hackrf, [this]() { hackrf_mode(nav_); }}); } diff --git a/firmware/common/external_app.hpp b/firmware/common/external_app.hpp index c257671b..0a5726c4 100644 --- a/firmware/common/external_app.hpp +++ b/firmware/common/external_app.hpp @@ -27,7 +27,7 @@ #include "spi_image.hpp" #include "standalone_app.hpp" -#define CURRENT_HEADER_VERSION 0x00000002 +#define CURRENT_HEADER_VERSION 0x00000003 #define MIN_HEADER_VERSION_FOR_CHECKSUM 0x00000002 typedef void (*externalAppEntry_t)(ui::NavigationView& nav); @@ -42,6 +42,7 @@ struct application_information_t { uint8_t bitmap_data[32]; uint32_t icon_color; app_location_t menu_location; + int32_t desired_menu_position; portapack::spi_flash::image_tag_t m4_app_tag; uint32_t m4_app_offset; diff --git a/firmware/tools/export_external_apps.py b/firmware/tools/export_external_apps.py index f0216a6d..0c61b444 100755 --- a/firmware/tools/export_external_apps.py +++ b/firmware/tools/export_external_apps.py @@ -91,8 +91,8 @@ cmake_objcopy = sys.argv[3] memory_location_header_position = 0 externalAppEntry_header_position = 4 -m4_app_tag_header_position = 72 -m4_app_offset_header_position = 76 +m4_app_tag_header_position = 76 +m4_app_offset_header_position = 80 for external_image_prefix in sys.argv[4:]: @@ -123,7 +123,10 @@ for external_image_prefix in sys.argv[4:]: write_image(external_application_image, "{}/{}.ppma".format(binary_dir, external_image_prefix)) continue + print(chunk_data) chunk_tag = chunk_data.decode("utf-8") + print(chunk_tag) + print("{}/../baseband/{}.bin".format(binary_dir, chunk_tag)) m4_image = read_image("{}/../baseband/{}.bin".format(binary_dir, chunk_tag)) app_image_len = len(external_application_image) external_application_image += m4_image