diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index fe1a2344a..8ecf0e936 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -468,11 +468,11 @@ void desktop_run_keybind(Desktop* instance, InputType _type, InputKey _key) { if(!strnlen(keybind, MAX_KEYBIND_LENGTH)) return; if(!strncmp(keybind, "Apps Menu", MAX_KEYBIND_LENGTH)) { - loader_start_with_gui_error(instance->loader, LOADER_APPLICATIONS_NAME, NULL); + loader_start_detached_with_gui_error(instance->loader, LOADER_APPLICATIONS_NAME, NULL); } else if(!strncmp(keybind, "Archive", MAX_KEYBIND_LENGTH)) { view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventOpenArchive); } else if(!strncmp(keybind, "Device Info", MAX_KEYBIND_LENGTH)) { - loader_start_with_gui_error(instance->loader, "Power", "about_battery"); + loader_start_detached_with_gui_error(instance->loader, "Power", "about_battery"); } else if(!strncmp(keybind, "Lock Menu", MAX_KEYBIND_LENGTH)) { view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventOpenLockMenu); } else if(!strncmp(keybind, "Lock Keypad", MAX_KEYBIND_LENGTH)) { @@ -480,7 +480,7 @@ void desktop_run_keybind(Desktop* instance, InputType _type, InputKey _key) { } else if(!strncmp(keybind, "Lock with PIN", MAX_KEYBIND_LENGTH)) { view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventLockWithPin); } else { - loader_start_with_gui_error(instance->loader, keybind, NULL); + loader_start_detached_with_gui_error(instance->loader, keybind, NULL); } } diff --git a/applications/services/desktop/scenes/desktop_scene_lock_menu.c b/applications/services/desktop/scenes/desktop_scene_lock_menu.c index d47a79319..bcc8eee20 100644 --- a/applications/services/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/services/desktop/scenes/desktop_scene_lock_menu.c @@ -122,7 +122,7 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { break; case DesktopLockMenuEventXtreme: desktop_scene_lock_menu_save_settings(desktop); - loader_start_with_gui_error(desktop->loader, "Xtreme", NULL); + loader_start_detached_with_gui_error(desktop->loader, "Xtreme", NULL); consumed = true; break; case DesktopLockMenuEventStealthModeOn: diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index 7733c3237..35809c104 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -57,6 +57,15 @@ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const return status; } +void loader_start_detached_with_gui_error(Loader* loader, const char* name, const char* args) { + LoaderMessage message; + + message.type = LoaderMessageTypeStartByNameDetachedWithGuiError; + message.start.name = name; + message.start.args = args; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); +} + bool loader_lock(Loader* loader) { LoaderMessage message; LoaderMessageBoolResult result; @@ -569,6 +578,32 @@ int32_t loader_srv(void* p) { loader, message.start.name, message.start.args, message.start.error_message); api_lock_unlock(message.api_lock); break; + case LoaderMessageTypeStartByNameDetachedWithGuiError: { + FuriString* error_message = furi_string_alloc(); + LoaderStatus status = loader_do_start_by_name( + loader, message.start.name, message.start.args, error_message); + if(status == LoaderStatusErrorUnknownApp || status == LoaderStatusErrorInternal) { + DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop); + dialog_message_set_buttons(message, NULL, NULL, NULL); + + furi_string_replace(error_message, ":", "\n"); + dialog_message_set_text( + message, + furi_string_get_cstr(error_message), + 64, + 32, + AlignCenter, + AlignCenter); + + dialog_message_show(dialogs, message); + dialog_message_free(message); + furi_record_close(RECORD_DIALOGS); + } + furi_string_free(error_message); + break; + } case LoaderMessageTypeShowMenu: loader_do_menu_show(loader, false); break; diff --git a/applications/services/loader/loader.h b/applications/services/loader/loader.h index f88439593..0073df3de 100644 --- a/applications/services/loader/loader.h +++ b/applications/services/loader/loader.h @@ -46,6 +46,14 @@ LoaderStatus */ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args); +/** + * @brief Start application detached with GUI error message + * @param[in] instance loader instance + * @param[in] name application name + * @param[in] args application arguments + */ +void loader_start_detached_with_gui_error(Loader* loader, const char* name, const char* args); + /** * @brief Lock application start * @param[in] instance loader instance diff --git a/applications/services/loader/loader_i.h b/applications/services/loader/loader_i.h index cbe01c7f3..5ed0441ba 100644 --- a/applications/services/loader/loader_i.h +++ b/applications/services/loader/loader_i.h @@ -25,6 +25,7 @@ struct Loader { typedef enum { LoaderMessageTypeStartByName, + LoaderMessageTypeStartByNameDetachedWithGuiError, LoaderMessageTypeAppClosed, LoaderMessageTypeShowMenu, LoaderMessageTypeShowSettings, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 00f9ee8ea..ba1c2d6b5 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1928,6 +1928,7 @@ Function,+,loader_lock,_Bool,Loader* Function,+,loader_show_menu,void,Loader* Function,+,loader_show_settings,void,Loader* Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*, FuriString*" +Function,+,loader_start_detached_with_gui_error,void,"Loader*, const char*, const char*" Function,+,loader_start_with_gui_error,LoaderStatus,"Loader*, const char*, const char*" Function,+,loader_unlock,void,Loader* Function,+,loading_alloc,Loading*,