diff --git a/applications/debug/file_browser_test/file_browser_app.c b/applications/debug/file_browser_test/file_browser_app.c index 6cb50d38..996cb2bd 100644 --- a/applications/debug/file_browser_test/file_browser_app.c +++ b/applications/debug/file_browser_test/file_browser_app.c @@ -48,7 +48,7 @@ FileBrowserApp* file_browser_app_alloc(char* arg) { app->file_path = furi_string_alloc(); app->file_browser = file_browser_alloc(app->file_path); - file_browser_configure(app->file_browser, "*", true, &I_badusb_10px, true); + file_browser_configure(app->file_browser, "*", NULL, true, &I_badusb_10px, true); view_dispatcher_add_view( app->view_dispatcher, FileBrowserAppViewStart, widget_get_view(app->widget)); diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index fa705189..a216705b 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -84,7 +84,8 @@ static void archive_file_browser_set_path( bool hide_dot_files) { furi_assert(browser); if(!browser->worker_running) { - browser->worker = file_browser_worker_alloc(path, filter_ext, skip_assets, hide_dot_files); + browser->worker = + file_browser_worker_alloc(path, NULL, filter_ext, skip_assets, hide_dot_files); file_browser_worker_set_callback_context(browser->worker, browser); file_browser_worker_set_folder_callback(browser->worker, archive_folder_open_cb); file_browser_worker_set_list_callback(browser->worker, archive_list_load_cb); diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c b/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c index c562fc2d..9264eb97 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_file_select.c @@ -1,12 +1,14 @@ #include "../bad_usb_app_i.h" #include "furi_hal_power.h" #include "furi_hal_usb.h" +#include static bool bad_usb_file_select(BadUsbApp* bad_usb) { furi_assert(bad_usb); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, BAD_USB_APP_EXTENSION, &I_badusb_10px); + browser_options.base_path = BAD_USB_APP_PATH_FOLDER; // Input events and views are managed by file_browser bool res = dialog_file_browser_show( diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index 10cec086..90186674 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -148,6 +148,7 @@ static bool fap_loader_select_app(FapLoader* loader) { .hide_ext = true, .item_loader_callback = fap_loader_item_callback, .item_loader_context = loader, + .base_path = EXT_PATH("apps"), }; return dialog_file_browser_show( diff --git a/applications/main/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c index b6d8361b..b7c8223b 100644 --- a/applications/main/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -218,6 +218,7 @@ void ibutton_free(iButton* ibutton) { bool ibutton_file_select(iButton* ibutton) { DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, IBUTTON_APP_EXTENSION, &I_ibutt_10px); + browser_options.base_path = IBUTTON_APP_FOLDER; bool success = dialog_file_browser_show( ibutton->dialogs, ibutton->file_path, ibutton->file_path, &browser_options); diff --git a/applications/main/infrared/scenes/infrared_scene_remote_list.c b/applications/main/infrared/scenes/infrared_scene_remote_list.c index 1667352d..55f14416 100644 --- a/applications/main/infrared/scenes/infrared_scene_remote_list.c +++ b/applications/main/infrared/scenes/infrared_scene_remote_list.c @@ -7,6 +7,7 @@ void infrared_scene_remote_list_on_enter(void* context) { DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, INFRARED_APP_EXTENSION, &I_ir_10px); + browser_options.base_path = INFRARED_APP_FOLDER; bool success = dialog_file_browser_show( infrared->dialogs, infrared->file_path, infrared->file_path, &browser_options); diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c index d391c5e8..2207e7e0 100644 --- a/applications/main/lfrfid/lfrfid.c +++ b/applications/main/lfrfid/lfrfid.c @@ -230,6 +230,7 @@ bool lfrfid_load_key_from_file_select(LfRfid* app) { DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, LFRFID_APP_EXTENSION, &I_125_10px); + browser_options.base_path = LFRFID_APP_FOLDER; // Input events and views are managed by file_browser bool result = diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index d9070ba8..736bcf36 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -454,6 +454,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sub1_10px); + browser_options.base_path = SUBGHZ_APP_FOLDER; // Input events and views are managed by file_select bool res = dialog_file_browser_show( diff --git a/applications/plugins/music_player/music_player.c b/applications/plugins/music_player/music_player.c index 28872284..07d4e2df 100644 --- a/applications/plugins/music_player/music_player.c +++ b/applications/plugins/music_player/music_player.c @@ -313,6 +313,7 @@ int32_t music_player_app(void* p) { dialog_file_browser_set_basic_options( &browser_options, MUSIC_PLAYER_APP_EXTENSION, &I_music_10px); browser_options.hide_ext = false; + browser_options.base_path = MUSIC_PLAYER_APP_PATH_FOLDER; DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options); diff --git a/applications/plugins/picopass/picopass_device.c b/applications/plugins/picopass/picopass_device.c index 199b79e9..fd8ddbfb 100644 --- a/applications/plugins/picopass/picopass_device.c +++ b/applications/plugins/picopass/picopass_device.c @@ -231,6 +231,7 @@ bool picopass_file_select(PicopassDevice* dev) { DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, PICOPASS_APP_EXTENSION, &I_Nfc_10px); + browser_options.base_path = PICOPASS_APP_FOLDER; bool res = dialog_file_browser_show( dev->dialogs, dev->load_path, picopass_app_folder, &browser_options); diff --git a/applications/services/dialogs/dialogs.c b/applications/services/dialogs/dialogs.c index 3c658888..3908ca31 100644 --- a/applications/services/dialogs/dialogs.c +++ b/applications/services/dialogs/dialogs.c @@ -14,6 +14,7 @@ void dialog_file_browser_set_basic_options( options->hide_ext = true; options->item_loader_callback = NULL; options->item_loader_context = NULL; + options->base_path = NULL; } static DialogsApp* dialogs_app_alloc() { diff --git a/applications/services/dialogs/dialogs.h b/applications/services/dialogs/dialogs.h index 97783eb0..4c1b675a 100644 --- a/applications/services/dialogs/dialogs.h +++ b/applications/services/dialogs/dialogs.h @@ -18,6 +18,7 @@ typedef struct DialogsApp DialogsApp; /** * File browser dialog extra options * @param extension file extension to be offered for selection + * @param base_path root folder path for navigation with back key * @param skip_assets true - do not show assets folders * @param hide_dot_files true - hide dot files * @param icon file icon pointer, NULL for default icon @@ -27,6 +28,7 @@ typedef struct DialogsApp DialogsApp; */ typedef struct { const char* extension; + const char* base_path; bool skip_assets; bool hide_dot_files; const Icon* icon; diff --git a/applications/services/dialogs/dialogs_api.c b/applications/services/dialogs/dialogs_api.c index 91b3a1d0..5e2b0683 100644 --- a/applications/services/dialogs/dialogs_api.c +++ b/applications/services/dialogs/dialogs_api.c @@ -24,6 +24,7 @@ bool dialog_file_browser_show( .preselected_filename = path, .item_callback = options ? options->item_loader_callback : NULL, .item_callback_context = options ? options->item_loader_context : NULL, + .base_path = options ? options->base_path : NULL, }}; DialogsAppReturn return_data; diff --git a/applications/services/dialogs/dialogs_message.h b/applications/services/dialogs/dialogs_message.h index 45d36ba1..1c8c4fb5 100644 --- a/applications/services/dialogs/dialogs_message.h +++ b/applications/services/dialogs/dialogs_message.h @@ -17,6 +17,7 @@ typedef struct { FuriString* preselected_filename; FileBrowserLoadItemCallback item_callback; void* item_callback_context; + const char* base_path; } DialogsAppMessageDataFileBrowser; typedef struct { diff --git a/applications/services/dialogs/dialogs_module_file_browser.c b/applications/services/dialogs/dialogs_module_file_browser.c index e03434cf..8d486dba 100644 --- a/applications/services/dialogs/dialogs_module_file_browser.c +++ b/applications/services/dialogs/dialogs_module_file_browser.c @@ -40,6 +40,7 @@ bool dialogs_app_process_module_file_browser(const DialogsAppMessageDataFileBrow file_browser_configure( file_browser, data->extension, + data->base_path, data->skip_assets, data->hide_dot_files, data->file_icon, diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index f20f950f..a5daa91e 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -83,6 +83,7 @@ struct FileBrowser { View* view; BrowserWorker* worker; const char* ext_filter; + const char* base_path; bool skip_assets; bool hide_dot_files; bool hide_ext; @@ -163,6 +164,7 @@ View* file_browser_get_view(FileBrowser* browser) { void file_browser_configure( FileBrowser* browser, const char* extension, + const char* base_path, bool skip_assets, bool hide_dot_files, const Icon* file_icon, @@ -172,6 +174,7 @@ void file_browser_configure( browser->ext_filter = extension; browser->skip_assets = skip_assets; browser->hide_ext = hide_ext; + browser->base_path = base_path; browser->hide_dot_files = hide_dot_files; with_view_model( @@ -187,7 +190,11 @@ void file_browser_configure( void file_browser_start(FileBrowser* browser, FuriString* path) { furi_assert(browser); browser->worker = file_browser_worker_alloc( - path, browser->ext_filter, browser->skip_assets, browser->hide_dot_files); + path, + browser->base_path, + browser->ext_filter, + browser->skip_assets, + browser->hide_dot_files); file_browser_worker_set_callback_context(browser->worker, browser); file_browser_worker_set_folder_callback(browser->worker, browser_folder_open_cb); file_browser_worker_set_list_callback(browser->worker, browser_list_load_cb); diff --git a/applications/services/gui/modules/file_browser.h b/applications/services/gui/modules/file_browser.h index 377d4d9b..879d62c4 100644 --- a/applications/services/gui/modules/file_browser.h +++ b/applications/services/gui/modules/file_browser.h @@ -29,6 +29,7 @@ View* file_browser_get_view(FileBrowser* browser); void file_browser_configure( FileBrowser* browser, const char* extension, + const char* base_path, bool skip_assets, bool hide_dot_files, const Icon* file_icon, diff --git a/applications/services/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c index fb45a384..d8b515d0 100644 --- a/applications/services/gui/modules/file_browser_worker.c +++ b/applications/services/gui/modules/file_browser_worker.c @@ -371,6 +371,7 @@ static int32_t browser_worker(void* context) { BrowserWorker* file_browser_worker_alloc( FuriString* path, + const char* base_path, const char* filter_ext, bool skip_assets, bool hide_dot_files) { @@ -381,12 +382,13 @@ BrowserWorker* file_browser_worker_alloc( browser->filter_extension = furi_string_alloc_set(filter_ext); browser->skip_assets = skip_assets; browser->hide_dot_files = hide_dot_files; - browser->path_start = furi_string_alloc_set(path); + browser->path_current = furi_string_alloc_set(path); browser->path_next = furi_string_alloc_set(path); - if(browser_path_is_file(browser->path_start)) { - browser_path_trim(browser->path_start); + browser->path_start = furi_string_alloc(); + if(base_path) { + furi_string_set_str(browser->path_start, base_path); } browser->thread = furi_thread_alloc_ex("BrowserWorker", 2048, browser_worker, browser); diff --git a/applications/services/gui/modules/file_browser_worker.h b/applications/services/gui/modules/file_browser_worker.h index ca143d66..3b4be6aa 100644 --- a/applications/services/gui/modules/file_browser_worker.h +++ b/applications/services/gui/modules/file_browser_worker.h @@ -23,6 +23,7 @@ typedef void (*BrowserWorkerLongLoadCallback)(void* context); BrowserWorker* file_browser_worker_alloc( FuriString* path, + const char* base_path, const char* filter_ext, bool skip_assets, bool hide_dot_files); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index bdd9589e..cf474c54 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -106,6 +106,7 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e .hide_ext = true, .item_loader_callback = favorite_fap_selector_item_callback, .item_loader_context = app, + .base_path = EXT_PATH("apps"), }; if(primary_favorite) { // Select favorite fap in file browser diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 38f21902..1ce76845 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,9.0,, +Version,+,10.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -806,14 +806,14 @@ Function,-,fgetpos,int,"FILE*, fpos_t*" Function,-,fgets,char*,"char*, int, FILE*" Function,-,fgets_unlocked,char*,"char*, int, FILE*" Function,+,file_browser_alloc,FileBrowser*,FuriString* -Function,+,file_browser_configure,void,"FileBrowser*, const char*, _Bool, _Bool, const Icon*, _Bool" +Function,+,file_browser_configure,void,"FileBrowser*, const char*, const char*, _Bool, _Bool, const Icon*, _Bool" Function,+,file_browser_free,void,FileBrowser* Function,+,file_browser_get_view,View*,FileBrowser* Function,+,file_browser_set_callback,void,"FileBrowser*, FileBrowserCallback, void*" Function,+,file_browser_set_item_callback,void,"FileBrowser*, FileBrowserLoadItemCallback, void*" Function,+,file_browser_start,void,"FileBrowser*, FuriString*" Function,+,file_browser_stop,void,FileBrowser* -Function,+,file_browser_worker_alloc,BrowserWorker*,"FuriString*, const char*, _Bool, _Bool" +Function,+,file_browser_worker_alloc,BrowserWorker*,"FuriString*, const char*, const char*, _Bool, _Bool" Function,+,file_browser_worker_folder_enter,void,"BrowserWorker*, FuriString*, int32_t" Function,+,file_browser_worker_folder_exit,void,BrowserWorker* Function,+,file_browser_worker_folder_refresh,void,"BrowserWorker*, int32_t" diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index e18f0945..3ab10a4f 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -1212,6 +1212,7 @@ bool nfc_file_select(NfcDevice* dev) { .hide_ext = true, .item_loader_callback = NULL, .item_loader_context = NULL, + .base_path = NFC_APP_FOLDER, }; bool res =