Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion applications/main/archive/helpers/archive_apps.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#include "archive_apps.h"
#include "archive_browser.h"

static const char* known_apps[] = {
static const char* const known_apps[] = {
[ArchiveAppTypeU2f] = "u2f",
[ArchiveAppTypeSetting] = "setting",
};

ArchiveAppTypeEnum archive_get_app_type(const char* path) {
Expand Down Expand Up @@ -36,6 +37,8 @@ bool archive_app_is_available(void* context, const char* path) {

furi_record_close(RECORD_STORAGE);
return file_exists;
} else if(app == ArchiveAppTypeSetting) {
return true;
} else {
return false;
}
Expand All @@ -53,6 +56,9 @@ bool archive_app_read_dir(void* context, const char* path) {
if(app == ArchiveAppTypeU2f) {
archive_add_app_item(browser, "/app:u2f/U2F Token");
return true;
} else if(app == ArchiveAppTypeSetting) {
archive_add_app_item(browser, path);
return true;
} else {
return false;
}
Expand All @@ -75,6 +81,8 @@ void archive_app_delete_file(void* context, const char* path) {
if(archive_is_favorite("/app:u2f/U2F Token")) {
archive_favorites_delete("/app:u2f/U2F Token");
}
} else if(app == ArchiveAppTypeSetting) {
// can't delete a setting!
}

if(res) {
Expand Down
2 changes: 2 additions & 0 deletions applications/main/archive/helpers/archive_apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

typedef enum {
ArchiveAppTypeU2f,
ArchiveAppTypeSetting,
ArchiveAppTypeUnknown,
ArchiveAppsTotal,
} ArchiveAppTypeEnum;

static const ArchiveFileTypeEnum app_file_types[] = {
[ArchiveAppTypeU2f] = ArchiveFileTypeU2f,
[ArchiveAppTypeSetting] = ArchiveFileTypeSetting,
[ArchiveAppTypeUnknown] = ArchiveFileTypeUnknown,
};

Expand Down
5 changes: 3 additions & 2 deletions applications/main/archive/helpers/archive_browser.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#define TAB_DEFAULT ArchiveTabFavorites // Start tab
#define FILE_LIST_BUF_LEN 50

static const char* tab_default_paths[] = {
static const char* const tab_default_paths[] = {
[ArchiveTabFavorites] = "/app:favorites",
[ArchiveTabIButton] = EXT_PATH("ibutton"),
[ArchiveTabNFC] = EXT_PATH("nfc"),
Expand All @@ -20,7 +20,7 @@ static const char* tab_default_paths[] = {
[ArchiveTabBrowser] = STORAGE_EXT_PATH_PREFIX,
};

static const char* known_ext[] = {
static const char* const known_ext[] = {
[ArchiveFileTypeIButton] = ".ibtn",
[ArchiveFileTypeNFC] = ".nfc",
[ArchiveFileTypeSubGhz] = ".sub",
Expand All @@ -34,6 +34,7 @@ static const char* known_ext[] = {
[ArchiveFileTypeFolder] = "?",
[ArchiveFileTypeUnknown] = "*",
[ArchiveFileTypeAppOrJs] = ".fap|.js",
[ArchiveFileTypeSetting] = "?",
};

static const ArchiveFileTypeEnum known_type[] = {
Expand Down
46 changes: 45 additions & 1 deletion applications/main/archive/helpers/archive_favorites.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@

#include "archive_favorites.h"
#include "archive_files.h"
#include "archive_apps.h"
#include "archive_browser.h"

#include <dialogs/dialogs.h>

#define ARCHIVE_FAV_FILE_BUF_LEN 32

static bool archive_favorites_read_line(File* file, FuriString* str_result) {
Expand Down Expand Up @@ -337,3 +338,46 @@ void archive_favorites_save(void* context) {
storage_file_free(file);
furi_record_close(RECORD_STORAGE);
}

void archive_favorites_handle_setting_pin_unpin(const char* app_name, const char* setting) {
DialogMessage* message = dialog_message_alloc();

FuriString* setting_path = furi_string_alloc_set_str(app_name);
if(setting) {
furi_string_push_back(setting_path, '/');
furi_string_cat_str(setting_path, setting);
}
const char* setting_path_str = furi_string_get_cstr(setting_path);

bool is_favorite = archive_is_favorite("/app:setting/%s", setting_path_str);
dialog_message_set_header(
message,
is_favorite ? "Unpin This Setting?" : "Pin This Setting?",
64,
0,
AlignCenter,
AlignTop);
dialog_message_set_text(
message,
is_favorite ? "It will no longer be\naccessible from the\nFavorites menu" :
"It will be accessible from the\nFavorites menu",
64,
32,
AlignCenter,
AlignCenter);
dialog_message_set_buttons(
message, is_favorite ? "Unpin" : "Go back", NULL, is_favorite ? "Keep pinned" : "Pin");

DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessageButton button = dialog_message_show(dialogs, message);
furi_record_close(RECORD_DIALOGS);

if(is_favorite && button == DialogMessageButtonLeft) {
archive_favorites_delete("/app:setting/%s", setting_path_str);
} else if(!is_favorite && button == DialogMessageButtonRight) {
archive_file_append(ARCHIVE_FAV_PATH, "/app:setting/%s\n", setting_path_str);
}

furi_string_free(setting_path);
dialog_message_free(message);
}
10 changes: 10 additions & 0 deletions applications/main/archive/helpers/archive_favorites.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,13 @@ bool archive_is_favorite(const char* format, ...) _ATTRIBUTE((__format__(__print
bool archive_favorites_rename(const char* src, const char* dst);
void archive_add_to_favorites(const char* file_path);
void archive_favorites_save(void* context);

/**
* Intended to be called by settings apps to handle long presses, as well as
* internally from within the archive
*
* @param app_name name of the referring application
* @param setting name of the setting, which will be both displayed to the user
* and passed to the application as an argument upon recall
*/
void archive_favorites_handle_setting_pin_unpin(const char* app_name, const char* setting);
1 change: 1 addition & 0 deletions applications/main/archive/helpers/archive_files.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ typedef enum {
ArchiveFileTypeFolder,
ArchiveFileTypeUnknown,
ArchiveFileTypeAppOrJs,
ArchiveFileTypeSetting,
ArchiveFileTypeLoading,
} ArchiveFileTypeEnum;

Expand Down
39 changes: 28 additions & 11 deletions applications/main/archive/scenes/archive_scene_browser.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,37 @@ static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selec
UNUSED(browser);
Loader* loader = furi_record_open(RECORD_LOADER);

const char* app_name = archive_get_flipper_app_name(selected->type);

if(app_name) {
if(selected->is_app) {
char* param = strrchr(furi_string_get_cstr(selected->path), '/');
if(param != NULL) {
param++;
}
loader_start_with_gui_error(loader, app_name, param);
if(selected->type == ArchiveFileTypeSetting) {
FuriString* app_name = furi_string_alloc_set(selected->path);
furi_string_right(app_name, furi_string_search_char(app_name, '/', 1) + 1);
size_t slash = furi_string_search_char(app_name, '/', 1);
if(slash != FURI_STRING_FAILURE) {
furi_string_left(app_name, slash);
FuriString* app_args =
furi_string_alloc_set_str(furi_string_get_cstr(app_name) + slash + 1);
loader_start_with_gui_error(
loader, furi_string_get_cstr(app_name), furi_string_get_cstr(app_args));
furi_string_free(app_args);
} else {
loader_start_with_gui_error(loader, app_name, furi_string_get_cstr(selected->path));
loader_start_with_gui_error(loader, furi_string_get_cstr(app_name), NULL);
}
furi_string_free(app_name);
} else {
loader_start_with_gui_error(loader, furi_string_get_cstr(selected->path), NULL);
const char* app_name = archive_get_flipper_app_name(selected->type);
if(app_name) {
if(selected->is_app) {
char* param = strrchr(furi_string_get_cstr(selected->path), '/');
if(param != NULL) {
param++;
}
loader_start_with_gui_error(loader, app_name, param);
} else {
loader_start_with_gui_error(
loader, app_name, furi_string_get_cstr(selected->path));
}
} else {
loader_start_with_gui_error(loader, furi_string_get_cstr(selected->path), NULL);
}
}

furi_record_close(RECORD_LOADER);
Expand Down
1 change: 1 addition & 0 deletions applications/main/archive/views/archive_browser_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ static const Icon* ArchiveItemIcons[] = {
[ArchiveFileTypeInfrared] = &I_ir_10px,
[ArchiveFileTypeBadUsb] = &I_badusb_10px,
[ArchiveFileTypeU2f] = &I_u2f_10px,
[ArchiveFileTypeSetting] = &I_settings_10px,
[ArchiveFileTypeUpdateManifest] = &I_update_10px,
[ArchiveFileTypeFolder] = &I_dir_10px,
[ArchiveFileTypeUnknown] = &I_unknown_10px,
Expand Down
50 changes: 41 additions & 9 deletions applications/services/gui/modules/submenu.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ struct Submenu {
typedef struct {
FuriString* label;
uint32_t index;
SubmenuItemCallback callback;
union {
SubmenuItemCallback callback;
SubmenuItemCallbackEx callback_ex;
};
void* callback_context;
bool has_extended_events;
} SubmenuItem;

static void SubmenuItem_init(SubmenuItem* item) {
Expand Down Expand Up @@ -57,7 +61,7 @@ typedef struct {

static void submenu_process_up(Submenu* submenu);
static void submenu_process_down(Submenu* submenu);
static void submenu_process_ok(Submenu* submenu);
static void submenu_process_ok(Submenu* submenu, InputType input_type);

static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
SubmenuModel* model = _model;
Expand Down Expand Up @@ -120,7 +124,10 @@ static bool submenu_view_input_callback(InputEvent* event, void* context) {
furi_assert(submenu);
bool consumed = false;

if(event->type == InputTypeShort) {
if(event->key == InputKeyOk) {
consumed = true;
submenu_process_ok(submenu, event->type);
} else if(event->type == InputTypeShort) {
switch(event->key) {
case InputKeyUp:
consumed = true;
Expand All @@ -130,10 +137,6 @@ static bool submenu_view_input_callback(InputEvent* event, void* context) {
consumed = true;
submenu_process_down(submenu);
break;
case InputKeyOk:
consumed = true;
submenu_process_ok(submenu);
break;
default:
break;
}
Expand Down Expand Up @@ -211,6 +214,31 @@ void submenu_add_item(
item->index = index;
item->callback = callback;
item->callback_context = callback_context;
item->has_extended_events = false;
},
true);
}

void submenu_add_item_ex(
Submenu* submenu,
const char* label,
uint32_t index,
SubmenuItemCallbackEx callback,
void* callback_context) {
SubmenuItem* item = NULL;
furi_check(label);
furi_check(submenu);

with_view_model(
submenu->view,
SubmenuModel * model,
{
item = SubmenuItemArray_push_new(model->items);
furi_string_set_str(item->label, label);
item->index = index;
item->callback_ex = callback;
item->callback_context = callback_context;
item->has_extended_events = true;
},
true);
}
Expand Down Expand Up @@ -357,7 +385,7 @@ void submenu_process_down(Submenu* submenu) {
true);
}

void submenu_process_ok(Submenu* submenu) {
void submenu_process_ok(Submenu* submenu, InputType input_type) {
SubmenuItem* item = NULL;

with_view_model(
Expand All @@ -371,8 +399,12 @@ void submenu_process_ok(Submenu* submenu) {
},
true);

if(item && item->callback) {
if(!item) return;

if(!item->has_extended_events && input_type == InputTypeShort && item->callback) {
item->callback(item->callback_context, item->index);
} else if(item->has_extended_events && item->callback_ex) {
item->callback_ex(item->callback_context, input_type, item->index);
}
}

Expand Down
17 changes: 17 additions & 0 deletions applications/services/gui/modules/submenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extern "C" {
/** Submenu anonymous structure */
typedef struct Submenu Submenu;
typedef void (*SubmenuItemCallback)(void* context, uint32_t index);
typedef void (*SubmenuItemCallbackEx)(void* context, InputType input_type, uint32_t index);

/** Allocate and initialize submenu
*
Expand Down Expand Up @@ -53,6 +54,22 @@ void submenu_add_item(
SubmenuItemCallback callback,
void* callback_context);

/** Add item to submenu with extended press events
*
* @param submenu Submenu instance
* @param label menu item label
* @param index menu item index, used for callback, may be
* the same with other items
* @param callback menu item extended callback
* @param callback_context menu item callback context
*/
void submenu_add_item_ex(
Submenu* submenu,
const char* label,
uint32_t index,
SubmenuItemCallbackEx callback,
void* callback_context);

/** Change label of an existing item
*
* @param submenu Submenu instance
Expand Down
15 changes: 11 additions & 4 deletions applications/services/loader/loader_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <gui/modules/submenu.h>
#include <assets_icons.h>
#include <applications.h>
#include <archive/helpers/archive_favorites.h>

#include "loader.h"
#include "loader_menu.h"
Expand Down Expand Up @@ -71,10 +72,16 @@ static void loader_menu_applications_callback(void* context, uint32_t index) {
loader_menu_start(name);
}

static void loader_menu_settings_menu_callback(void* context, uint32_t index) {
static void
loader_menu_settings_menu_callback(void* context, InputType input_type, uint32_t index) {
UNUSED(context);
const char* name = FLIPPER_SETTINGS_APPS[index].name;
loader_menu_start(name);
if(input_type == InputTypeShort) {
const char* name = FLIPPER_SETTINGS_APPS[index].name;
loader_menu_start(name);
} else if(input_type == InputTypeLong) {
const char* name = FLIPPER_SETTINGS_APPS[index].name;
archive_favorites_handle_setting_pin_unpin(name, NULL);
}
}

static void loader_menu_switch_to_settings(void* context, uint32_t index) {
Expand Down Expand Up @@ -128,7 +135,7 @@ static void loader_menu_build_menu(LoaderMenuApp* app, LoaderMenu* menu) {

static void loader_menu_build_submenu(LoaderMenuApp* app, LoaderMenu* loader_menu) {
for(size_t i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) {
submenu_add_item(
submenu_add_item_ex(
app->settings_menu,
FLIPPER_SETTINGS_APPS[i].name,
i,
Expand Down
Loading
Loading