diff --git a/CHANGELOG.md b/CHANGELOG.md index 46f0496e3..22f403ca5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,21 @@ ### Added: - Apps: + - Games: Geometry Flip (by @goosedev72-projects) + - GPIO: [KT0803] FM Transmitter (by @goosedev72-projects) - GPIO/ESP: [ESP32] Ghost ESP (by @jaylikesbunda) + - GPIO/FlipBoard: + - FlipBoard Blinky (by @jamisonderek) + - FlipBoard Keyboard (by @jamisonderek) + - FlipBoard Signal (by @jamisonderek) + - FlipBoard Simon (by @jamisonderek) + - GPIO/FlipperHTTP: Free Roam (by @jblanked) - GPIO/GPS: [NMEA] Nearby Files (by @Stichoza) + - Media: Video Player (by @LTVA1) - NFC: NFC-Eink (by @RebornedBrain) - RFID: Simultaneous UHF RFID Reader (by @haffnerriley) - - Sub-GHz: Sub Analyzer (by @RocketGod-git) + - Sub-GHz: + - Chief Cooker (by @denr01) + - Sub Analyzer (by @RocketGod-git) - SubGHz: - UL: Roger (static 28 bit) with add manually support (by @xMasterX & @mishamyte) - UL: V2 Phoenix full support (button switch, add manually, counter decrypt/encrypt) (by @xMasterX & @RocketGod-git, original code by @Skorpionm) @@ -36,7 +47,7 @@ - Metroflip: Fix unsupported card crash, RENFE Suma 10 support, GEG Connect AID added, Top Up log parsing and animations, 16 new rail lines, support for parsing area codes, saving function for Suica/Japan Rail IC, bugfixes (by @luu176) - NFC Maker: Support making empty/blank NDEF payloads (by @WillyJL) - NFC Playlist: Refactor playlist worker, new settings layout, loop setting, controls to move between items (by @acegoal07) - - Passy: Misc memory management bugfixes (by @qistoph) + - Passy: Misc memory management bugfixes, misc UI improvements (by @qistoph) - Seader: Fix ATS handling (by @NVX), reset SAM on error (by @bettse) - Sentry Safe: New interface, settings & help page (by @H4ckd4ddy) - Seos Compatible: Add keys v2 support with per-device encryption (by @bettse) @@ -58,6 +69,7 @@ - NFC: - Fix incorrect Saflok year formula (#433 by @Eltrick) - Fix read crash with unexpectedly large MFC AUTH(0) response, eg with Chameleon Ultra NTAG emualtion (by @WillyJL) + - Fix slashes in prefilled filename (by @WillyJL) - FBT: Fix redundant decl for apps using an icon disabled in API (by @WillyJL) ### Removed: diff --git a/applications/external b/applications/external index 321d19b4b..102720481 160000 --- a/applications/external +++ b/applications/external @@ -1 +1 @@ -Subproject commit 321d19b4b3d356484166ba8fe142c69337ccc76b +Subproject commit 10272048130f6bd7d09aaca31bce387eb1095ed1 diff --git a/applications/main/archive/archive.c b/applications/main/archive/archive.c index 5d50ff27a..62ed63156 100644 --- a/applications/main/archive/archive.c +++ b/applications/main/archive/archive.c @@ -147,13 +147,14 @@ int32_t archive_app(void* p) { if(path && !furi_string_empty(path)) { archive_set_tab(archive->browser, ArchiveTabBrowser); furi_string_set(archive->browser->path, path); - archive->browser->is_root = false; + archive->browser->is_root = true; archive_file_browser_set_path( archive->browser, archive->browser->path, archive_get_tab_ext(ArchiveTabBrowser), false, - !momentum_settings.show_hidden_files); + !momentum_settings.show_hidden_files, + furi_string_get_cstr(path)); } scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneBrowser); diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index d55180415..ef39ca802 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -121,7 +121,8 @@ void archive_file_browser_set_path( FuriString* path, const char* filter_ext, bool skip_assets, - bool hide_dot_files) { + bool hide_dot_files, + const char* override_home_path) { furi_assert(browser); if(!browser->worker_running) { browser->worker = @@ -137,6 +138,7 @@ void archive_file_browser_set_path( file_browser_worker_set_config( browser->worker, path, filter_ext, skip_assets, hide_dot_files); } + browser->override_home_path = override_home_path; } bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx) { @@ -385,7 +387,9 @@ bool archive_is_home(ArchiveBrowserView* browser) { return true; } - const char* default_path = archive_get_default_path(archive_get_tab(browser)); + const char* default_path = browser->override_home_path ? + browser->override_home_path : + archive_get_default_path(archive_get_tab(browser)); return furi_string_cmp_str(browser->path, default_path) == 0; } @@ -589,7 +593,12 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { tab == ArchiveTabInternal ? false : !momentum_settings.show_hidden_files; archive_file_browser_set_path( - browser, browser->path, archive_get_tab_ext(tab), skip_assets, hide_dot_files); + browser, + browser->path, + archive_get_tab_ext(tab), + skip_assets, + hide_dot_files, + NULL); tab_empty = false; // Empty check will be performed later } } diff --git a/applications/main/archive/helpers/archive_browser.h b/applications/main/archive/helpers/archive_browser.h index 2b020ed1c..2378c53b2 100644 --- a/applications/main/archive/helpers/archive_browser.h +++ b/applications/main/archive/helpers/archive_browser.h @@ -88,7 +88,8 @@ void archive_file_browser_set_path( FuriString* path, const char* filter_ext, bool skip_assets, - bool hide_dot_files); + bool hide_dot_files, + const char* override_home_path); bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx); bool archive_is_file_list_load_required(ArchiveBrowserViewModel* model); void archive_update_offset(ArchiveBrowserView* browser); diff --git a/applications/main/archive/views/archive_browser_view.h b/applications/main/archive/views/archive_browser_view.h index c94d60631..098e2d22c 100644 --- a/applications/main/archive/views/archive_browser_view.h +++ b/applications/main/archive/views/archive_browser_view.h @@ -95,6 +95,7 @@ struct ArchiveBrowserView { bool is_root; FuriTimer* scroll_timer; File* disk_image; + const char* override_home_path; }; typedef struct { diff --git a/applications/main/momentum_app/momentum_app.c b/applications/main/momentum_app/momentum_app.c index 015014ef1..030fb9ada 100644 --- a/applications/main/momentum_app/momentum_app.c +++ b/applications/main/momentum_app/momentum_app.c @@ -158,7 +158,8 @@ static bool momentum_app_back_event_callback(void* context) { return scene_manager_handle_back_event(app->scene_manager); } -static void momentum_app_push_mainmenu_app(MomentumApp* app, FuriString* label, FuriString* exe) { +static void + momentum_app_push_mainmenu_app_raw(MomentumApp* app, FuriString* label, FuriString* exe) { CharList_push_back(app->mainmenu_app_exes, strdup(furi_string_get_cstr(exe))); // Display logic mimics applications/services/gui/modules/menu.c if(furi_string_equal(label, "Momentum")) { @@ -176,6 +177,38 @@ static void momentum_app_push_mainmenu_app(MomentumApp* app, FuriString* label, CharList_push_back(app->mainmenu_app_labels, strdup(furi_string_get_cstr(label))); } +void momentum_app_push_mainmenu_app(MomentumApp* app, FuriString* exe) { + FuriString* label = furi_string_alloc(); + if(furi_string_start_with(exe, "/")) { + uint8_t unused_icon[FAP_MANIFEST_MAX_ICON_SIZE]; + uint8_t* unused_icon_ptr = unused_icon; + if(!flipper_application_load_name_and_icon(exe, app->storage, &unused_icon_ptr, label)) { + const char* end = strrchr(furi_string_get_cstr(exe), '/'); + furi_string_set(label, end ? end + 1 : furi_string_get_cstr(exe)); + } + momentum_app_push_mainmenu_app_raw(app, label, exe); + } else { + bool found = false; + for(size_t i = 0; !found && i < FLIPPER_APPS_COUNT; i++) { + if(!strcmp(furi_string_get_cstr(exe), FLIPPER_APPS[i].name)) { + furi_string_set(label, FLIPPER_APPS[i].name); + found = true; + } + } + for(size_t i = 0; !found && i < FLIPPER_EXTERNAL_APPS_COUNT; i++) { + if(!strcmp(furi_string_get_cstr(exe), FLIPPER_EXTERNAL_APPS[i].name)) { + furi_string_set(label, FLIPPER_EXTERNAL_APPS[i].name); + found = true; + } + } + // Ignore unknown apps just like in main menu, prevents "ghost" apps when saving + if(!furi_string_empty(label)) { + momentum_app_push_mainmenu_app_raw(app, label, exe); + } + } + furi_string_free(label); +} + void momentum_app_load_mainmenu_apps(MomentumApp* app) { // Loading logic mimics applications/services/loader/loader_menu.c Stream* stream = file_stream_alloc(app->storage); @@ -198,45 +231,19 @@ void momentum_app_load_mainmenu_apps(MomentumApp* app) { furi_string_set(line, "Momentum"); } } - if(furi_string_start_with(line, "/")) { - if(!flipper_application_load_name_and_icon( - line, app->storage, &unused_icon, label)) { - const char* end = strrchr(furi_string_get_cstr(line), '/'); - furi_string_set(label, end ? end + 1 : furi_string_get_cstr(line)); - } - momentum_app_push_mainmenu_app(app, label, line); - continue; - } - bool found = false; - for(size_t i = 0; !found && i < FLIPPER_APPS_COUNT; i++) { - if(!strcmp(furi_string_get_cstr(line), FLIPPER_APPS[i].name)) { - furi_string_set(label, FLIPPER_APPS[i].name); - found = true; - } - } - for(size_t i = 0; !found && i < FLIPPER_EXTERNAL_APPS_COUNT; i++) { - if(!strcmp(furi_string_get_cstr(line), FLIPPER_EXTERNAL_APPS[i].name)) { - furi_string_set(label, FLIPPER_EXTERNAL_APPS[i].name); - found = true; - } - } - if(furi_string_empty(label)) { - // Ignore unknown apps just like in main menu, prevents "ghost" apps when saving - continue; - } - momentum_app_push_mainmenu_app(app, label, line); + momentum_app_push_mainmenu_app(app, line); } } else { for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { furi_string_set(label, FLIPPER_APPS[i].name); furi_string_set(line, FLIPPER_APPS[i].name); - momentum_app_push_mainmenu_app(app, label, line); + momentum_app_push_mainmenu_app_raw(app, label, line); } // Until count - 1 because last app is hardcoded below for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT - 1; i++) { furi_string_set(label, FLIPPER_EXTERNAL_APPS[i].name); furi_string_set(line, FLIPPER_EXTERNAL_APPS[i].name); - momentum_app_push_mainmenu_app(app, label, line); + momentum_app_push_mainmenu_app_raw(app, label, line); } } free(unused_icon); diff --git a/applications/main/momentum_app/momentum_app.h b/applications/main/momentum_app/momentum_app.h index 776f21b67..70e51d592 100644 --- a/applications/main/momentum_app/momentum_app.h +++ b/applications/main/momentum_app/momentum_app.h @@ -111,5 +111,6 @@ typedef enum { bool momentum_app_apply(MomentumApp* app); +void momentum_app_push_mainmenu_app(MomentumApp* app, FuriString* exe); void momentum_app_load_mainmenu_apps(MomentumApp* app); void momentum_app_empty_mainmenu_apps(MomentumApp* app); diff --git a/applications/main/momentum_app/scenes/momentum_app_scene_interface_mainmenu_add.c b/applications/main/momentum_app/scenes/momentum_app_scene_interface_mainmenu_add.c index 49f765f31..621cf5858 100644 --- a/applications/main/momentum_app/scenes/momentum_app_scene_interface_mainmenu_add.c +++ b/applications/main/momentum_app/scenes/momentum_app_scene_interface_mainmenu_add.c @@ -43,26 +43,7 @@ static void FuriString* temp_path = furi_string_alloc_set_str(browser_options.base_path); if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) { - CharList_push_back(app->mainmenu_app_exes, strdup(furi_string_get_cstr(temp_path))); - if(is_file_dir) { - const char* path = furi_string_get_cstr(temp_path); - const char* end = strrchr(path, '/'); - furi_string_set_str(temp_path, end ? end + 1 : path); - } else { - Storage* storage = furi_record_open(RECORD_STORAGE); - uint8_t* unused_icon = malloc(FAP_MANIFEST_MAX_ICON_SIZE); - flipper_application_load_name_and_icon( - temp_path, storage, &unused_icon, temp_path); - free(unused_icon); - furi_record_close(RECORD_STORAGE); - if(furi_string_start_with_str(temp_path, "[")) { - size_t trim = furi_string_search_str(temp_path, "] ", 1); - if(trim != FURI_STRING_FAILURE) { - furi_string_right(temp_path, trim + 2); - } - } - } - CharList_push_back(app->mainmenu_app_labels, strdup(furi_string_get_cstr(temp_path))); + momentum_app_push_mainmenu_app(app, temp_path); app->mainmenu_app_index = CharList_size(app->mainmenu_app_labels) - 1; app->save_mainmenu_apps = true; scene_manager_search_and_switch_to_previous_scene( diff --git a/applications/main/momentum_app/scenes/momentum_app_scene_interface_mainmenu_add_main.c b/applications/main/momentum_app/scenes/momentum_app_scene_interface_mainmenu_add_main.c index 40089c96d..bddf25bab 100644 --- a/applications/main/momentum_app/scenes/momentum_app_scene_interface_mainmenu_add_main.c +++ b/applications/main/momentum_app/scenes/momentum_app_scene_interface_mainmenu_add_main.c @@ -5,8 +5,9 @@ static void MomentumApp* app = context; const char* name = (const char*)index; - CharList_push_back(app->mainmenu_app_exes, strdup(name)); - CharList_push_back(app->mainmenu_app_labels, strdup(name)); + FuriString* exe = furi_string_alloc_set(name); + momentum_app_push_mainmenu_app(app, exe); + furi_string_free(exe); app->mainmenu_app_index = CharList_size(app->mainmenu_app_labels) - 1; app->save_mainmenu_apps = true; scene_manager_search_and_switch_to_previous_scene( diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c index 008f9c317..2ee29668c 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c @@ -680,6 +680,7 @@ static void nfc_protocol_support_scene_save_name_on_enter(NfcApp* instance) { furi_string_replace(prefix, " Plus", "+"); // NTAG I2C+ furi_string_replace(prefix, " (Unknown)", ""); furi_string_replace_all(prefix, " ", "_"); + furi_string_replace_all(prefix, "/", "_"); name_generator_make_auto( instance->text_store, NFC_TEXT_STORE_SIZE, furi_string_get_cstr(prefix)); furi_string_free(prefix);