#include "../desktop_settings_app.h"
#include "applications.h"
#include "desktop_settings_scene.h"
#include "desktop_settings_scene_i.h"
#include <flipper_application/flipper_application.h>
#include <storage/storage.h>
#include <dialogs/dialogs.h>
#define APPS_COUNT (FLIPPER_APPS_COUNT + FLIPPER_EXTERNAL_APPS_COUNT)
#define DEFAULT_INDEX (0)
#define EXTERNAL_BROWSER_NAME ("( ) Apps Menu (Default)")
#define EXTERNAL_BROWSER_NAME_SELECTED ("(*) Apps Menu (Default)")
#define PASSPORT_NAME ("( ) Passport (Default)")
#define PASSPORT_NAME_SELECTED ("(*) Passport (Default)")
#define SELECTED_PREFIX ("(*) ")
#define NOT_SELECTED_PREFIX ("( ) ")
#define EXTERNAL_APPLICATION_INDEX (1)
#define EXTERNAL_APPLICATION_NAME ("( ) [Select App]")
#define EXTERNAL_APPLICATION_NAME_SELECTED ("(*) [Select App]")
#define PRESELECTED_SPECIAL 0xffffffff
static const char* favorite_fap_get_app_name(size_t i) {
const char* name;
if(i < FLIPPER_APPS_COUNT) {
name = FLIPPER_APPS[i].name;
} else {
name = FLIPPER_EXTERNAL_APPS[i - FLIPPER_APPS_COUNT].name;
}
return name;
}
static bool favorite_fap_selector_item_callback(
FuriString* file_path,
void* context,
uint8_t** icon_ptr,
FuriString* item_name) {
UNUSED(context);
Storage* storage = furi_record_open(RECORD_STORAGE);
bool success = flipper_application_load_name_and_icon(file_path, storage, icon_ptr, item_name);
furi_record_close(RECORD_STORAGE);
return success;
}
static bool favorite_fap_selector_file_exists(char* file_path) {
Storage* storage = furi_record_open(RECORD_STORAGE);
bool exists = storage_file_exists(storage, file_path);
furi_record_close(RECORD_STORAGE);
return exists;
}
static void desktop_settings_scene_favorite_submenu_callback(void* context, uint32_t index) {
DesktopSettingsApp* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, index);
}
void desktop_settings_scene_favorite_on_enter(void* context) {
DesktopSettingsApp* app = context;
Submenu* submenu = app->submenu;
submenu_reset(submenu);
uint32_t favorite_id =
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite);
uint32_t pre_select_item = PRESELECTED_SPECIAL;
FavoriteApp* curr_favorite_app = NULL;
bool default_passport = false;
if((favorite_id & SCENE_STATE_SET_DUMMY_APP) == 0) {
furi_assert(favorite_id < FavoriteAppNumber);
curr_favorite_app = &app->settings.favorite_apps[favorite_id];
if(favorite_id == FavoriteAppRightShort) {
default_passport = true;
}
} else {
favorite_id &= ~(SCENE_STATE_SET_DUMMY_APP);
furi_assert(favorite_id < DummyAppNumber);
curr_favorite_app = &app->settings.dummy_apps[favorite_id];
default_passport = true;
favorite_id |= SCENE_STATE_SET_DUMMY_APP;
}
// Special case: Application browser
submenu_add_item(
submenu,
default_passport ? (PASSPORT_NAME) : (EXTERNAL_BROWSER_NAME),
DEFAULT_INDEX,
desktop_settings_scene_favorite_submenu_callback,
app);
// Special case: Specific application
submenu_add_item(
submenu,
EXTERNAL_APPLICATION_NAME,
EXTERNAL_APPLICATION_INDEX,
desktop_settings_scene_favorite_submenu_callback,
app);
FuriString* full_name = furi_string_alloc();
for(size_t i = 0; i < APPS_COUNT; i++) {
const char* name = favorite_fap_get_app_name(i);
// Add the prefix
furi_string_reset(full_name);
if(!strcmp(name, curr_favorite_app->name_or_path)) {
furi_string_set_str(full_name, SELECTED_PREFIX);
} else {
furi_string_set_str(full_name, NOT_SELECTED_PREFIX);
}
furi_string_cat_str(full_name, name);
submenu_add_item(
submenu,
furi_string_get_cstr(full_name),
i + 2,
desktop_settings_scene_favorite_submenu_callback,
app);
// Select favorite item in submenu
if(!strcmp(name, curr_favorite_app->name_or_path)) {
pre_select_item = i + 2;
}
}
if(pre_select_item == PRESELECTED_SPECIAL) {
if(curr_favorite_app->name_or_path[0] == '\0') {
pre_select_item = DEFAULT_INDEX;
submenu_change_item_label(
submenu,
DEFAULT_INDEX,
default_passport ? (PASSPORT_NAME_SELECTED) : (EXTERNAL_BROWSER_NAME_SELECTED));
} else {
pre_select_item = EXTERNAL_APPLICATION_INDEX;
submenu_change_item_label(
submenu, EXTERNAL_APPLICATION_INDEX, EXTERNAL_APPLICATION_NAME_SELECTED);
}
}
switch(favorite_id) {
case SCENE_STATE_SET_FAVORITE_APP | FavoriteAppLeftShort:
submenu_set_header(submenu, "Left - Press");
break;
case SCENE_STATE_SET_FAVORITE_APP | FavoriteAppLeftLong:
submenu_set_header(submenu, "Left - Hold");
break;
case SCENE_STATE_SET_FAVORITE_APP | FavoriteAppRightShort:
submenu_set_header(submenu, "Right - Press");
break;
case SCENE_STATE_SET_FAVORITE_APP | FavoriteAppRightLong:
submenu_set_header(submenu, "Right - Hold");
break;
case SCENE_STATE_SET_DUMMY_APP | DummyAppLeft:
submenu_set_header(submenu, "Left - Press");
break;
case SCENE_STATE_SET_DUMMY_APP | DummyAppRight:
submenu_set_header(submenu, "Right - Press");
break;
case SCENE_STATE_SET_DUMMY_APP | DummyAppDown:
submenu_set_header(submenu, "Down - Press");
break;
case SCENE_STATE_SET_DUMMY_APP | DummyAppOk:
submenu_set_header(submenu, "Middle - Press");
break;
default:
break;
}
submenu_set_selected_item(submenu, pre_select_item); // If set during loop, visual glitch.
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
}
bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent event) {
DesktopSettingsApp* app = context;
bool consumed = false;
FuriString* temp_path = furi_string_alloc_set_str(EXT_PATH("apps"));
uint32_t favorite_id =
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite);
FavoriteApp* curr_favorite_app = NULL;
if((favorite_id & SCENE_STATE_SET_DUMMY_APP) == 0) {
furi_assert(favorite_id < FavoriteAppNumber);
curr_favorite_app = &app->settings.favorite_apps[favorite_id];
} else {
favorite_id &= ~(SCENE_STATE_SET_DUMMY_APP);
furi_assert(favorite_id < DummyAppNumber);
curr_favorite_app = &app->settings.dummy_apps[favorite_id];
}
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == DEFAULT_INDEX) {
curr_favorite_app->name_or_path[0] = '\0';
consumed = true;
} else if(event.event == EXTERNAL_APPLICATION_INDEX) {
const DialogsFileBrowserOptions browser_options = {
.extension = ".fap",
.icon = &I_unknown_10px,
.skip_assets = true,
.hide_ext = true,
.item_loader_callback = favorite_fap_selector_item_callback,
.item_loader_context = app,
.base_path = EXT_PATH("apps"),
};
// Select favorite fap in file browser
if(favorite_fap_selector_file_exists(curr_favorite_app->name_or_path)) {
furi_string_set_str(temp_path, curr_favorite_app->name_or_path);
}
if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) {
submenu_reset(app->submenu); // Prevent menu from being shown when we exiting scene
strncpy(
curr_favorite_app->name_or_path,
furi_string_get_cstr(temp_path),
MAX_APP_LENGTH);
consumed = true;
}
} else {
size_t app_index = event.event - 2;
const char* name = favorite_fap_get_app_name(app_index);
if(name) strncpy(curr_favorite_app->name_or_path, name, MAX_APP_LENGTH);
consumed = true;
}
if(consumed) {
scene_manager_previous_scene(app->scene_manager);
};
consumed = true;
DESKTOP_SETTINGS_SAVE(&app->settings);
}
furi_string_free(temp_path);
return consumed;
}
void desktop_settings_scene_favorite_on_exit(void* context) {
DesktopSettingsApp* app = context;
submenu_reset(app->submenu);
}
↑ V1037 Two or more case-branches perform the same actions. Check lines: 151, 160
↑ V1037 Two or more case-branches perform the same actions. Check lines: 145, 157