diff --git a/CHANGELOG.md b/CHANGELOG.md index 367cc2030..0e0812fb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +### Breaking Changes: +- Desktop: Settings restructured due to LFS removal + - You might need to reconfigure Desktop Settings (PIN code, auto lock, show clock) + - Desktop Keybinds should transfer correctly automatically + ### Added: - OFW: RFID: Add GProxII support (by @BarTenderNZ) - OFW: iButton: Support ID writing (by @Astrrra) @@ -10,6 +15,8 @@ - NFC Playlist: Fix extension check and error messages (by @acegoal07) - Various app fixes for `-Wundef` option (by @Willy-JL) - BadKB: Lower BLE conn interval like base HID profile (by @Willy-JL) +- Desktop: Refactor Keybinds, no more 63 character limit, keybinds only loaded when pressed to save RAM (by @Willy-JL) +- Settings: Statusbar Clock and Left Handed options show in normal Settings app like OFW (by @Willy-JL) - Services: Big cleanup of services and settings handling (by @Willy-JL) - OFW: NFC: Refactor detected protocols list (by @Astrrra) - OFW: CCID: App refactor (by @kidbomb) diff --git a/applications/main/momentum_app/momentum_app.c b/applications/main/momentum_app/momentum_app.c index b0459c4e5..f11728b44 100644 --- a/applications/main/momentum_app/momentum_app.c +++ b/applications/main/momentum_app/momentum_app.c @@ -26,6 +26,10 @@ bool momentum_app_apply(MomentumApp* app) { stream_free(stream); } + if(app->save_desktop) { + desktop_api_set_settings(app->desktop, &app->desktop_settings); + } + if(app->save_subghz_freqs) { FlipperFormat* file = flipper_format_file_alloc(storage); do { @@ -181,6 +185,7 @@ static void momentum_app_push_mainmenu_app(MomentumApp* app, FuriString* label, MomentumApp* momentum_app_alloc() { MomentumApp* app = malloc(sizeof(MomentumApp)); app->gui = furi_record_open(RECORD_GUI); + app->desktop = furi_record_open(RECORD_DESKTOP); app->dialogs = furi_record_open(RECORD_DIALOGS); app->expansion = furi_record_open(RECORD_EXPANSION); app->notification = furi_record_open(RECORD_NOTIFICATION); @@ -323,6 +328,8 @@ MomentumApp* momentum_app_alloc() { file_stream_close(stream); stream_free(stream); + desktop_api_get_settings(app->desktop, &app->desktop_settings); + FlipperFormat* file = flipper_format_file_alloc(storage); FrequencyList_init(app->subghz_static_freqs); FrequencyList_init(app->subghz_hopper_freqs); @@ -446,6 +453,7 @@ void momentum_app_free(MomentumApp* app) { furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_EXPANSION); furi_record_close(RECORD_DIALOGS); + furi_record_close(RECORD_DESKTOP); furi_record_close(RECORD_GUI); free(app); } diff --git a/applications/main/momentum_app/momentum_app.h b/applications/main/momentum_app/momentum_app.h index c346d8d78..53a96b4ad 100644 --- a/applications/main/momentum_app/momentum_app.h +++ b/applications/main/momentum_app/momentum_app.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -37,6 +38,7 @@ ARRAY_DEF(CharList, char*) typedef struct { Gui* gui; + Desktop* desktop; DialogsApp* dialogs; Expansion* expansion; NotificationApp* notification; @@ -54,6 +56,7 @@ typedef struct { CharList_t mainmenu_app_labels; CharList_t mainmenu_app_exes; uint8_t mainmenu_app_index; + DesktopSettings desktop_settings; bool subghz_use_defaults; FrequencyList_t subghz_static_freqs; uint8_t subghz_static_index; @@ -70,6 +73,7 @@ typedef struct { FuriString* version_tag; bool save_mainmenu_apps; + bool save_desktop; bool save_subghz_freqs; bool save_subghz; bool save_name; diff --git a/applications/main/momentum_app/scenes/momentum_app_scene_interface_statusbar.c b/applications/main/momentum_app/scenes/momentum_app_scene_interface_statusbar.c index 618cc5f80..555e3c954 100644 --- a/applications/main/momentum_app/scenes/momentum_app_scene_interface_statusbar.c +++ b/applications/main/momentum_app/scenes/momentum_app_scene_interface_statusbar.c @@ -36,8 +36,8 @@ static void momentum_app_scene_interface_statusbar_statusbar_clock_changed(Varia MomentumApp* app = variable_item_get_context(item); bool value = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, value ? "ON" : "OFF"); - momentum_settings.statusbar_clock = value; - app->save_settings = true; + app->desktop_settings.display_clock = value; + app->save_desktop = true; } static void momentum_app_scene_interface_statusbar_status_icons_changed(VariableItem* item) { @@ -84,8 +84,8 @@ void momentum_app_scene_interface_statusbar_on_enter(void* context) { 2, momentum_app_scene_interface_statusbar_statusbar_clock_changed, app); - variable_item_set_current_value_index(item, momentum_settings.statusbar_clock); - variable_item_set_current_value_text(item, momentum_settings.statusbar_clock ? "ON" : "OFF"); + variable_item_set_current_value_index(item, app->desktop_settings.display_clock); + variable_item_set_current_value_text(item, app->desktop_settings.display_clock ? "ON" : "OFF"); item = variable_item_list_add( var_item_list, diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 6a65e3841..5917cfb7a 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -74,13 +74,13 @@ static void desktop_clock_reconfigure(Desktop* desktop) { desktop_clock_update(desktop); - if(momentum_settings.statusbar_clock) { + if(desktop->settings.display_clock) { furi_timer_start(desktop->update_clock_timer, furi_ms_to_ticks(1000)); } else { furi_timer_stop(desktop->update_clock_timer); } - view_port_enabled_set(desktop->clock_viewport, momentum_settings.statusbar_clock); + view_port_enabled_set(desktop->clock_viewport, desktop->settings.display_clock); } static void desktop_clock_draw_callback(Canvas* canvas, void* context) { @@ -146,6 +146,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { desktop_apply_settings(desktop); } else if(event == DesktopGlobalReloadSettings) { + desktop_keybinds_migrate(desktop); desktop_settings_load(&desktop->settings); desktop_apply_settings(desktop); @@ -252,6 +253,7 @@ static void desktop_init_settings(Desktop* desktop) { return; } + desktop_keybinds_migrate(desktop); desktop_settings_load(&desktop->settings); desktop_apply_settings(desktop); } @@ -495,55 +497,6 @@ void desktop_api_set_settings(Desktop* instance, const DesktopSettings* settings view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopGlobalSaveSettings); } -static const KeybindType keybind_types[] = { - [InputTypeShort] = KeybindTypePress, - [InputTypeLong] = KeybindTypeHold, -}; - -static const KeybindKey keybind_keys[] = { - [InputKeyUp] = KeybindKeyUp, - [InputKeyDown] = KeybindKeyDown, - [InputKeyRight] = KeybindKeyRight, - [InputKeyLeft] = KeybindKeyLeft, -}; - -void desktop_run_keybind(Desktop* instance, InputType _type, InputKey _key) { - if(_type != InputTypeShort && _type != InputTypeLong) return; - if(_key != InputKeyUp && _key != InputKeyDown && _key != InputKeyRight && _key != InputKeyLeft) - return; - - KeybindType type = keybind_types[_type]; - KeybindKey key = keybind_keys[_key]; - const char* keybind = instance->keybinds[type][key].data; - if(!strnlen(keybind, MAX_KEYBIND_LENGTH)) return; - - if(!strncmp(keybind, "Apps Menu", MAX_KEYBIND_LENGTH)) { - 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, "Clock", MAX_KEYBIND_LENGTH)) { - loader_start_detached_with_gui_error( - instance->loader, EXT_PATH("apps/Tools/nightstand.fap"), ""); - } else if(!strncmp(keybind, "Device Info", MAX_KEYBIND_LENGTH)) { - 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)) { - view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventLockKeypad); - } else if(!strncmp(keybind, "Lock with PIN", MAX_KEYBIND_LENGTH)) { - view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventLockWithPin); - } else if(!strncmp(keybind, "Wipe Device", MAX_KEYBIND_LENGTH)) { - loader_start_detached_with_gui_error(instance->loader, "Storage", "wipe"); - } else { - if(storage_common_exists(furi_record_open(RECORD_STORAGE), keybind)) { - run_with_default_app(keybind); - } else { - loader_start_detached_with_gui_error(instance->loader, keybind, NULL); - } - furi_record_close(RECORD_STORAGE); - } -} - /* * Application thread */ diff --git a/applications/services/desktop/desktop.h b/applications/services/desktop/desktop.h index de3283af9..9768a59cf 100644 --- a/applications/services/desktop/desktop.h +++ b/applications/services/desktop/desktop.h @@ -22,5 +22,3 @@ FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance); void desktop_api_get_settings(Desktop* instance, DesktopSettings* settings); void desktop_api_set_settings(Desktop* instance, const DesktopSettings* settings); - -void desktop_run_keybind(Desktop* instance, InputType _type, InputKey _key); diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index 9ab77d90b..0aaee4d36 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -2,6 +2,7 @@ #include "desktop.h" #include "desktop_settings.h" +#include "desktop_keybinds.h" #include "animations/animation_manager.h" #include "views/desktop_view_pin_timeout.h" diff --git a/applications/services/desktop/desktop_keybinds.c b/applications/services/desktop/desktop_keybinds.c new file mode 100644 index 000000000..8feee7764 --- /dev/null +++ b/applications/services/desktop/desktop_keybinds.c @@ -0,0 +1,215 @@ +#include "desktop_keybinds.h" +#include "desktop_keybinds_filename.h" +#include "desktop_i.h" + +#include +#include + +#define TAG "DesktopKeybinds" + +#define OLD_DESKTOP_KEYBINDS_VER (1) +#define OLD_DESKTOP_KEYBINDS_MAGIC (0x14) +#define OLD_DESKTOP_KEYBINDS_PATH INT_PATH(".desktop.keybinds") // Moved from .config by migrate +#define OLD_MAX_KEYBIND_LENGTH (64) + +typedef struct { + char data[OLD_MAX_KEYBIND_LENGTH]; +} OldKeybind; + +typedef OldKeybind OldKeybinds[DesktopKeybindTypeMAX][DesktopKeybindKeyMAX]; + +void desktop_keybinds_migrate(Desktop* desktop) { + OldKeybinds old; + const bool success = saved_struct_load( + OLD_DESKTOP_KEYBINDS_PATH, + &old, + sizeof(old), + OLD_DESKTOP_KEYBINDS_MAGIC, + OLD_DESKTOP_KEYBINDS_VER); + + if(success) { + DesktopKeybinds new; + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + FuriString* keybind = furi_string_alloc_set(old[type][key]); + if(furi_string_equal(keybind, EXT_PATH("apps/Misc/nightstand.fap"))) { + furi_string_set(keybind, "Clock"); + } else if(furi_string_equal(keybind, "RFID")) { + furi_string_set(keybind, "125 kHz RFID"); + } else if(furi_string_equal(keybind, "SubGHz")) { + furi_string_set(keybind, "Sub-GHz"); + } else if(furi_string_equal(keybind, "Xtreme")) { + furi_string_set(keybind, "Momentum"); + } + new[type][key] = keybind; + } + } + desktop_keybinds_save(desktop, &new); + desktop_keybinds_free(&new); + } + + storage_common_remove(desktop->storage, OLD_DESKTOP_KEYBINDS_PATH); +} + +const char* desktop_keybinds_defaults[DesktopKeybindTypeMAX][DesktopKeybindKeyMAX] = { + [DesktopKeybindTypePress] = + { + [DesktopKeybindKeyUp] = "Lock Menu", + [DesktopKeybindKeyDown] = "Archive", + [DesktopKeybindKeyRight] = "Passport", + [DesktopKeybindKeyLeft] = "Clock", + }, + [DesktopKeybindTypeHold] = + { + [DesktopKeybindKeyUp] = "", + [DesktopKeybindKeyDown] = "", + [DesktopKeybindKeyRight] = "Device Info", + [DesktopKeybindKeyLeft] = "Lock with PIN", + }, +}; + +const char* desktop_keybind_types[DesktopKeybindTypeMAX] = { + [DesktopKeybindTypePress] = "Press", + [DesktopKeybindTypeHold] = "Hold", +}; + +const char* desktop_keybind_keys[DesktopKeybindKeyMAX] = { + [DesktopKeybindKeyUp] = "Up", + [DesktopKeybindKeyDown] = "Down", + [DesktopKeybindKeyRight] = "Right", + [DesktopKeybindKeyLeft] = "Left", +}; + +static FuriString* + desktop_keybinds_load_one(Desktop* desktop, DesktopKeybindType type, DesktopKeybindKey key) { + bool success = false; + FuriString* keybind = furi_string_alloc(); + FlipperFormat* file = flipper_format_file_alloc(desktop->storage); + + if(flipper_format_file_open_existing(file, DESKTOP_KEYBINDS_PATH)) { + FuriString* keybind_name = furi_string_alloc_printf( + keybind_name, "%s%s", desktop_keybind_types[type], desktop_keybind_keys[type]); + success = flipper_format_read_string( + file, furi_string_get_cstr(keybind_name), keybinds[type][key]); + furi_string_free(keybind_name); + } + + flipper_format_free(file); + if(!success) { + FURI_LOG_W(TAG, "Failed to load file, using defaults"); + furi_string_set(keybind, desktop_keybinds_defaults[type][key]); + } + return keybind; +} + +void desktop_keybinds_load(Desktop* desktop, DesktopKeybinds* keybinds) { + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + keybinds[type][key] = furi_string_alloc_set(desktop_keybinds_defaults[type][key]); + } + } + + FlipperFormat* file = flipper_format_file_alloc(desktop->storage); + FuriString* keybind_name = furi_string_alloc(); + + if(flipper_format_file_open_existing(file, DESKTOP_KEYBINDS_PATH)) { + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + furi_string_printf( + keybind_name, "%s%s", desktop_keybind_types[type], desktop_keybind_keys[type]); + if(!flipper_format_read_string( + file, furi_string_get_cstr(keybind_name), keybinds[type][key])) { + furi_string_set(keybinds[type][key], desktop_keybinds_defaults[type][key]); + goto fail; + } + } + } + } else { + fail: + FURI_LOG_W(TAG, "Failed to load file, using defaults"); + } + + furi_string_free(keybind_name); + flipper_format_free(file); +} + +void desktop_keybinds_save(Desktop* desktop, const DesktopKeybinds* keybinds) { + FlipperFormat* file = flipper_format_file_alloc(desktop->storage); + FuriString* keybind_name = furi_string_alloc(); + + if(flipper_format_file_open_always(file, DESKTOP_KEYBINDS_PATH)) { + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + furi_string_printf( + keybind_name, "%s%s", desktop_keybind_types[type], desktop_keybind_keys[type]); + if(!flipper_format_write_string_cstr( + file, + furi_string_get_cstr(keybind_name), + furi_string_get_cstr(keybinds[type][key]))) { + goto fail; + } + } + } + } else { + fail: + FURI_LOG_E(TAG, "Failed to save file"); + } + + furi_string_free(keybind_name); + flipper_format_free(file); +} + +void desktop_keybinds_free(DesktopKeybinds* keybinds) { + for(DesktopKeybindType type = 0; type < DesktopKeybindTypeMAX; type++) { + for(DesktopKeybindKey key = 0; key < DesktopKeybindKeyMAX; key++) { + furi_string_free(keybinds[type][key]); + } + } +} + +static const DesktopKeybindType keybind_types[DesktopKeybindTypeMAX] = { + [InputTypeShort] = DesktopKeybindTypePress, + [InputTypeLong] = DesktopKeybindTypeHold, +}; + +static const DesktopKeybindKey keybind_keys[DesktopKeybindKeyMAX] = { + [InputKeyUp] = DesktopKeybindKeyUp, + [InputKeyDown] = DesktopKeybindKeyDown, + [InputKeyRight] = DesktopKeybindKeyRight, + [InputKeyLeft] = DesktopKeybindKeyLeft, +}; + +void desktop_run_keybind(Desktop* desktop, InputType _type, InputKey _key) { + if(_type != InputTypeShort && _type != InputTypeLong) return; + if(_key != InputKeyUp && _key != InputKeyDown && _key != InputKeyRight && _key != InputKeyLeft) + return; + + DesktopKeybindType type = keybind_types[_type]; + DesktopKeybindKey key = keybind_keys[_key]; + FuriString* keybind = desktop_keybinds_load_one(desktop, type, key); + + if(furi_string_equal(keybind, "Apps Menu")) { + loader_start_detached_with_gui_error(instance->loader, LOADER_APPLICATIONS_NAME, NULL); + } else if(furi_string_equal(keybind, "Archive")) { + view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventOpenArchive); + } else if(furi_string_equal(keybind, "Clock")) { + loader_start_detached_with_gui_error( + instance->loader, EXT_PATH("apps/Tools/nightstand.fap"), ""); + } else if(furi_string_equal(keybind, "Device Info")) { + loader_start_detached_with_gui_error(instance->loader, "Power", "about_battery"); + } else if(furi_string_equal(keybind, "Lock Menu")) { + view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventOpenLockMenu); + } else if(furi_string_equal(keybind, "Lock Keypad")) { + view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventLockKeypad); + } else if(furi_string_equal(keybind, "Lock with PIN")) { + view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopMainEventLockWithPin); + } else if(furi_string_equal(keybind, "Wipe Device")) { + loader_start_detached_with_gui_error(instance->loader, "Storage", "wipe"); + } else { + if(storage_common_exists(desktop->storage, keybind)) { + run_with_default_app(keybind); + } else { + loader_start_detached_with_gui_error(instance->loader, keybind, NULL); + } + } +} diff --git a/applications/services/desktop/desktop_keybinds.h b/applications/services/desktop/desktop_keybinds.h new file mode 100644 index 000000000..dfc54f054 --- /dev/null +++ b/applications/services/desktop/desktop_keybinds.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#include "desktop.h" + +typedef enum { + DesktopKeybindTypePress, + DesktopKeybindTypeHold, + DesktopKeybindTypeMAX, +} DesktopKeybindType; + +typedef enum { + DesktopKeybindKeyUp, + DesktopKeybindKeyDown, + DesktopKeybindKeyRight, + DesktopKeybindKeyLeft, + DesktopKeybindKeyMAX, +} DesktopKeybindKey; + +typedef FuriString* DesktopKeybinds[DesktopKeybindTypeMAX][DesktopKeybindKeyMAX]; + +void desktop_keybinds_migrate(Desktop* desktop); +void desktop_keybinds_load(Desktop* desktop, DesktopKeybinds* keybinds); +void desktop_keybinds_save(Desktop* desktop, const DesktopKeybinds* keybinds); +void desktop_keybinds_free(DesktopKeybinds* keybinds); +void desktop_run_keybind(Desktop* desktop, InputType _type, InputKey _key); diff --git a/applications/services/desktop/desktop_keybinds_filename.h b/applications/services/desktop/desktop_keybinds_filename.h new file mode 100644 index 000000000..b68b65870 --- /dev/null +++ b/applications/services/desktop/desktop_keybinds_filename.h @@ -0,0 +1,3 @@ +#pragma once + +#define DESKTOP_KEYBINDS_PATH INT_PATH(".desktop_keybinds.txt") diff --git a/applications/services/desktop/desktop_settings.c b/applications/services/desktop/desktop_settings.c index c3c80b34d..d3722d589 100644 --- a/applications/services/desktop/desktop_settings.c +++ b/applications/services/desktop/desktop_settings.c @@ -1,50 +1,42 @@ #include "desktop_settings.h" +#include "desktop_settings_filename.h" -bool DESKTOP_SETTINGS_SAVE(DesktopSettings* x) { - return saved_struct_save( +#include +#include + +#define TAG "DesktopSettings" + +#define DESKTOP_SETTINGS_VER (11) +#define DESKTOP_SETTINGS_MAGIC (0x13) // Different from OFW 0x17 + +void desktop_settings_load(DesktopSettings* settings) { + furi_assert(settings); + + const bool success = saved_struct_load( DESKTOP_SETTINGS_PATH, - x, + settings, sizeof(DesktopSettings), DESKTOP_SETTINGS_MAGIC, DESKTOP_SETTINGS_VER); -} -bool DESKTOP_SETTINGS_LOAD(DesktopSettings* x) { - return saved_struct_load( - DESKTOP_SETTINGS_PATH, - x, - sizeof(DesktopSettings), - DESKTOP_SETTINGS_MAGIC, - DESKTOP_SETTINGS_VER); -} - -bool DESKTOP_KEYBINDS_SAVE(Keybinds* x, size_t size) { - return saved_struct_save( - DESKTOP_KEYBINDS_PATH, x, size, DESKTOP_KEYBINDS_MAGIC, DESKTOP_KEYBINDS_VER); -} - -bool DESKTOP_KEYBINDS_LOAD(Keybinds* x, size_t size) { - bool ok = saved_struct_load( - DESKTOP_KEYBINDS_PATH, x, size, DESKTOP_KEYBINDS_MAGIC, DESKTOP_KEYBINDS_VER); - if(ok) { - for(KeybindType i = 0; i < KeybindTypeCount; i++) { - for(KeybindKey j = 0; j < KeybindKeyCount; j++) { - char* keybind = (*x)[i][j].data; - if(!strncmp(keybind, EXT_PATH("apps/Misc/nightstand.fap"), MAX_KEYBIND_LENGTH)) { - strcpy(keybind, "Clock"); - } - } - } - } else { - memset(x, 0, size); - strcpy((*x)[KeybindTypePress][KeybindKeyUp].data, "Lock Menu"); - strcpy((*x)[KeybindTypePress][KeybindKeyDown].data, "Archive"); - strcpy((*x)[KeybindTypePress][KeybindKeyRight].data, "Passport"); - strcpy((*x)[KeybindTypePress][KeybindKeyLeft].data, "Clock"); - strcpy((*x)[KeybindTypeHold][KeybindKeyUp].data, ""); - strcpy((*x)[KeybindTypeHold][KeybindKeyDown].data, ""); - strcpy((*x)[KeybindTypeHold][KeybindKeyRight].data, "Device Info"); - strcpy((*x)[KeybindTypeHold][KeybindKeyLeft].data, "Lock with PIN"); + if(!success) { + FURI_LOG_W(TAG, "Failed to load file, using defaults"); + memset(settings, 0, sizeof(DesktopSettings)); + desktop_settings_save(settings); + } +} + +void desktop_settings_save(const DesktopSettings* settings) { + furi_assert(settings); + + const bool success = saved_struct_save( + DESKTOP_SETTINGS_PATH, + settings, + sizeof(DesktopSettings), + DESKTOP_SETTINGS_MAGIC, + DESKTOP_SETTINGS_VER); + + if(!success) { + FURI_LOG_E(TAG, "Failed to save file"); } - return ok; } diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 420801ba6..4ca923bee 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -1,70 +1,12 @@ #pragma once -#include #include -#include -#include -#include - -#define DESKTOP_SETTINGS_VER (11) - -#define DESKTOP_SETTINGS_PATH INT_PATH(".desktop.settings") -#define DESKTOP_SETTINGS_MAGIC (0x17) - -#define DESKTOP_KEYBINDS_VER (1) - -#define DESKTOP_KEYBINDS_PATH CFG_PATH("desktop.keybinds") -#define DESKTOP_KEYBINDS_MAGIC (0x14) - -#define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup" - -#define MAX_PIN_SIZE 10 -#define MIN_PIN_SIZE 4 -#define MAX_KEYBIND_LENGTH 64 typedef struct { - InputKey data[MAX_PIN_SIZE]; - uint8_t length; -} PinCode; - -typedef struct { - char data[MAX_KEYBIND_LENGTH]; -} Keybind; - -typedef enum { - KeybindTypePress, - KeybindTypeHold, - KeybindTypeCount, -} KeybindType; - -typedef enum { - KeybindKeyUp, - KeybindKeyDown, - KeybindKeyRight, - KeybindKeyLeft, - KeybindKeyCount, -} KeybindKey; - -typedef struct { - PinCode pin_code; uint32_t auto_lock_delay_ms; bool auto_lock_with_pin; + uint8_t display_clock; } DesktopSettings; -typedef Keybind Keybinds[KeybindTypeCount][KeybindKeyCount]; - -#ifdef __cplusplus -extern "C" { -#endif - -bool DESKTOP_SETTINGS_SAVE(DesktopSettings* x); - -bool DESKTOP_SETTINGS_LOAD(DesktopSettings* x); - -bool DESKTOP_KEYBINDS_SAVE(Keybinds* x, size_t size); - -bool DESKTOP_KEYBINDS_LOAD(Keybinds* x, size_t size); - -#ifdef __cplusplus -} -#endif +void desktop_settings_load(DesktopSettings* settings); +void desktop_settings_save(const DesktopSettings* settings); diff --git a/applications/services/desktop/desktop_settings_filename.h b/applications/services/desktop/desktop_settings_filename.h new file mode 100644 index 000000000..7930dd90f --- /dev/null +++ b/applications/services/desktop/desktop_settings_filename.h @@ -0,0 +1,5 @@ +#pragma once + +#define DESKTOP_SETTINGS_FILE_NAME ".desktop.settings" + +#define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) diff --git a/applications/services/desktop/helpers/pin_code.h b/applications/services/desktop/helpers/pin_code.h index 848c915b6..4b6615105 100644 --- a/applications/services/desktop/helpers/pin_code.h +++ b/applications/services/desktop/helpers/pin_code.h @@ -5,6 +5,8 @@ #define DESKTOP_PIN_CODE_MAX_LEN (10) +#define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup" + typedef struct { uint8_t data[DESKTOP_PIN_CODE_MAX_LEN]; uint8_t length; diff --git a/applications/settings/desktop_settings/desktop_settings_app.c b/applications/settings/desktop_settings/desktop_settings_app.c index 53d5a9452..81b055def 100644 --- a/applications/settings/desktop_settings/desktop_settings_app.c +++ b/applications/settings/desktop_settings/desktop_settings_app.c @@ -33,40 +33,20 @@ static bool desktop_settings_back_event_callback(void* context) { return scene_manager_handle_back_event(app->scene_manager); } -const char* desktop_settings_app_get_keybind(DesktopSettingsApp* app) { - KeybindType type = +FuriString* desktop_settings_app_get_keybind(DesktopSettingsApp* app) { + DesktopKeybindType type = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneKeybindsType); - KeybindKey key = + DesktopKeybindKey key = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneKeybindsKey); - return app->desktop->keybinds[type][key].data; + return app->keybinds[type][key]; } -bool desktop_settings_app_set_keybind(DesktopSettingsApp* app, const char* value) { - if(strnlen(value, MAX_KEYBIND_LENGTH) == MAX_KEYBIND_LENGTH) { - // No NULL terminator, value is too long for keybind - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_header(message, "Keybind Too Long", 64, 0, AlignCenter, AlignTop); - dialog_message_set_buttons(message, NULL, "Ok", NULL); - dialog_message_set_text( - message, - "Keybinds are max 63 chars.\n" - "Shorten the file path or\n" - "choose something else.", - 64, - 32, - AlignCenter, - AlignCenter); - dialog_message_show(app->dialogs, message); - dialog_message_free(message); - return false; - } - KeybindType type = +void desktop_settings_app_set_keybind(DesktopSettingsApp* app, const char* value) { + DesktopKeybindType type = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneKeybindsType); - KeybindKey key = + DesktopKeybindKey key = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneKeybindsKey); - strlcpy(app->desktop->keybinds[type][key].data, value, MAX_KEYBIND_LENGTH); - DESKTOP_KEYBINDS_SAVE(&app->desktop->keybinds, sizeof(app->desktop->keybinds)); - return true; + furi_string_set(app->keybinds[type][key], value); } DesktopSettingsApp* desktop_settings_app_alloc(void) { @@ -150,6 +130,7 @@ extern int32_t desktop_settings_app(void* p) { Desktop* desktop = furi_record_open(RECORD_DESKTOP); desktop_api_get_settings(desktop, &app->settings); + desktop_keybinds_load(desktop, &app->keybinds); if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) { scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); @@ -159,6 +140,8 @@ extern int32_t desktop_settings_app(void* p) { view_dispatcher_run(app->view_dispatcher); + desktop_keybinds_save(desktop, &app->keybinds); + desktop_keybinds_free(&app->keybinds); desktop_api_set_settings(desktop, &app->settings); furi_record_close(RECORD_DESKTOP); diff --git a/applications/settings/desktop_settings/desktop_settings_app.h b/applications/settings/desktop_settings/desktop_settings_app.h index cc583802d..9dee1a8b0 100644 --- a/applications/settings/desktop_settings/desktop_settings_app.h +++ b/applications/settings/desktop_settings/desktop_settings_app.h @@ -38,6 +38,7 @@ extern const size_t EXTRA_KEYBINDS_COUNT; typedef struct { DesktopSettings settings; + DesktopKeybinds keybinds; Gui* gui; DialogsApp* dialogs; @@ -57,5 +58,5 @@ typedef struct { uint32_t pin_menu_idx; } DesktopSettingsApp; -const char* desktop_settings_app_get_keybind(DesktopSettingsApp* app); -bool desktop_settings_app_set_keybind(DesktopSettingsApp* app, const char* value); +FuriString* desktop_settings_app_get_keybind(DesktopSettingsApp* app); +void desktop_settings_app_set_keybind(DesktopSettingsApp* app, const char* value); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c index 40f4fc656..c7d96c013 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action.c @@ -6,16 +6,13 @@ static void desktop_settings_scene_keybinds_action_submenu_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; - if(desktop_settings_app_set_keybind(app, (const char*)index)) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, DesktopSettingsAppSceneStart); - } + desktop_settings_app_set_keybind(app, (const char*)index); } void desktop_settings_scene_keybinds_action_on_enter(void* context) { DesktopSettingsApp* app = context; Submenu* submenu = app->submenu; - const char* keybind = desktop_settings_app_get_keybind(app); + FuriString* keybind = desktop_settings_app_get_keybind(app); submenu_reset(submenu); uint32_t pre_select_item = 0; @@ -32,7 +29,7 @@ void desktop_settings_scene_keybinds_action_on_enter(void* context) { app); // Select keybind item in submenu - if(!strncmp(FLIPPER_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, FLIPPER_APPS[i].name)) { pre_select_item = (uint32_t)FLIPPER_APPS[i].name; } } @@ -45,7 +42,7 @@ void desktop_settings_scene_keybinds_action_on_enter(void* context) { app); // Select keybind item in submenu - if(!strncmp(FLIPPER_EXTERNAL_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, FLIPPER_EXTERNAL_APPS[i].name)) { pre_select_item = (uint32_t)FLIPPER_EXTERNAL_APPS[i].name; } } @@ -59,7 +56,7 @@ void desktop_settings_scene_keybinds_action_on_enter(void* context) { app); // Select keybind item in submenu - if(!strncmp(EXTRA_KEYBINDS[i], keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, EXTRA_KEYBINDS[i])) { pre_select_item = (uint32_t)EXTRA_KEYBINDS[i]; } } diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c index d0e8ac74d..0ac50faf8 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_action_type.c @@ -23,7 +23,7 @@ static void DesktopSettingsApp* app = context; scene_manager_set_scene_state( app->scene_manager, DesktopSettingsAppSceneKeybindsActionType, index); - const char* keybind = desktop_settings_app_get_keybind(app); + FuriString* keybind = desktop_settings_app_get_keybind(app); switch(index) { case DesktopSettingsAppKeybindActionTypeMainApp: @@ -55,24 +55,18 @@ static void .base_path = base_path, }; FuriString* temp_path = furi_string_alloc_set_str(base_path); - if(storage_file_exists(furi_record_open(RECORD_STORAGE), keybind)) { - furi_string_set_str(temp_path, keybind); + if(storage_file_exists(furi_record_open(RECORD_STORAGE), furi_string_get_cstr(keybind))) { + furi_string_set(temp_path, keybind); } furi_record_close(RECORD_STORAGE); if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) { - if(desktop_settings_app_set_keybind(app, furi_string_get_cstr(temp_path))) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, DesktopSettingsAppSceneStart); - } + desktop_settings_app_set_keybind(app, furi_string_get_cstr(temp_path)); } furi_string_free(temp_path); break; } case DesktopSettingsAppKeybindActionTypeRemoveKeybind: - if(desktop_settings_app_set_keybind(app, "")) { - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, DesktopSettingsAppSceneStart); - } + desktop_settings_app_set_keybind(app, ""); break; default: break; @@ -82,7 +76,7 @@ static void void desktop_settings_scene_keybinds_action_type_on_enter(void* context) { DesktopSettingsApp* app = context; Submenu* submenu = app->submenu; - const char* keybind = desktop_settings_app_get_keybind(app); + FuriString* keybind = desktop_settings_app_get_keybind(app); submenu_add_item( submenu, @@ -123,34 +117,32 @@ void desktop_settings_scene_keybinds_action_type_on_enter(void* context) { app->scene_manager, DesktopSettingsAppSceneKeybindsActionType); if(selected == DesktopSettingsAppKeybindActionTypeRemoveKeybind) { for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { - if(!strncmp(FLIPPER_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, FLIPPER_APPS[i].name)) { selected = DesktopSettingsAppKeybindActionTypeMainApp; } } for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) { - if(!strncmp(FLIPPER_EXTERNAL_APPS[i].name, keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, FLIPPER_EXTERNAL_APPS[i].name)) { selected = DesktopSettingsAppKeybindActionTypeMainApp; } } - if(storage_file_exists(furi_record_open(RECORD_STORAGE), keybind)) { - FuriString* tmp = furi_string_alloc_set(keybind); - if(furi_string_end_with_str(tmp, ".fap")) { + if(storage_file_exists(furi_record_open(RECORD_STORAGE), furi_string_get_cstr(keybind))) { + if(furi_string_end_with_str(keybind, ".fap")) { selected = DesktopSettingsAppKeybindActionTypeExternalApp; } else { selected = DesktopSettingsAppKeybindActionTypeOpenFile; } - furi_string_free(tmp); } furi_record_close(RECORD_STORAGE); for(size_t i = 0; i < EXTRA_KEYBINDS_COUNT; i++) { - if(!strncmp(EXTRA_KEYBINDS[i], keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_equal(keybind, EXTRA_KEYBINDS[i])) { selected = DesktopSettingsAppKeybindActionTypeMoreActions; } } - if(!strnlen(keybind, MAX_KEYBIND_LENGTH)) { + if(furi_string_empty(keybind)) { selected = DesktopSettingsAppKeybindActionTypeRemoveKeybind; } } diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_key.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_key.c index 7ac1e72f5..a2a1f8a76 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_key.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_key.c @@ -13,21 +13,33 @@ void desktop_settings_scene_keybinds_key_on_enter(void* context) { Submenu* submenu = app->submenu; submenu_reset(submenu); - submenu_add_item( - submenu, "Up", KeybindKeyUp, desktop_settings_scene_keybinds_key_submenu_callback, app); - - submenu_add_item( - submenu, "Down", KeybindKeyDown, desktop_settings_scene_keybinds_key_submenu_callback, app); - submenu_add_item( submenu, - "Right", - KeybindKeyRight, + "Up", + DesktopKeybindKeyUp, desktop_settings_scene_keybinds_key_submenu_callback, app); submenu_add_item( - submenu, "Left", KeybindKeyLeft, desktop_settings_scene_keybinds_key_submenu_callback, app); + submenu, + "Down", + DesktopKeybindKeyDown, + desktop_settings_scene_keybinds_key_submenu_callback, + app); + + submenu_add_item( + submenu, + "Right", + DesktopKeybindKeyRight, + desktop_settings_scene_keybinds_key_submenu_callback, + app); + + submenu_add_item( + submenu, + "Left", + DesktopKeybindKeyLeft, + desktop_settings_scene_keybinds_key_submenu_callback, + app); submenu_set_header(submenu, "Keybind key:"); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_type.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_type.c index 645f88738..8d52e6ffa 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_type.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_keybinds_type.c @@ -16,14 +16,14 @@ void desktop_settings_scene_keybinds_type_on_enter(void* context) { submenu_add_item( submenu, "Press", - KeybindTypePress, + DesktopKeybindTypePress, desktop_settings_scene_keybinds_type_submenu_callback, app); submenu_add_item( submenu, "Hold", - KeybindTypeHold, + DesktopKeybindTypeHold, desktop_settings_scene_keybinds_type_submenu_callback, app); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 62ef77037..0edd48a58 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -10,6 +10,7 @@ typedef enum { DesktopSettingsResetKeybinds, DesktopSettingsAutoLockDelay, DesktopSettingsAutoLockPin, + DesktopSettingsClockDisplay, } DesktopSettingsEntry; #define AUTO_LOCK_DELAY_COUNT 9 @@ -27,11 +28,27 @@ static const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { static const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] = {0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000}; +#define CLOCK_ENABLE_COUNT 2 +const char* const clock_enable_text[CLOCK_ENABLE_COUNT] = { + "OFF", + "ON", +}; + +const uint32_t clock_enable_value[CLOCK_ENABLE_COUNT] = {0, 1}; + static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, index); } +static void desktop_settings_scene_start_clock_enable_changed(VariableItem* item) { + DesktopSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, clock_enable_text[index]); + app->settings.display_clock = index; +} + static void desktop_settings_scene_start_auto_lock_delay_changed(VariableItem* item) { DesktopSettingsApp* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -83,6 +100,18 @@ void desktop_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_index(item, app->settings.auto_lock_with_pin); variable_item_set_current_value_text(item, app->settings.auto_lock_with_pin ? "ON" : "OFF"); + item = variable_item_list_add( + variable_item_list, + "Show Clock", + CLOCK_ENABLE_COUNT, + desktop_settings_scene_start_clock_enable_changed, // + app); + + value_index = + value_index_uint32(app->settings.display_clock, clock_enable_value, CLOCK_ENABLE_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, clock_enable_text[value_index]); + variable_item_list_set_enter_callback( variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app); diff --git a/applications/settings/system/system_settings.c b/applications/settings/system/system_settings.c index cc96aa300..55b428d96 100644 --- a/applications/settings/system/system_settings.c +++ b/applications/settings/system/system_settings.c @@ -163,6 +163,21 @@ static void date_format_changed(VariableItem* item) { locale_set_date_format(date_format_value[index]); } +const char* const hand_mode[] = { + "Righty", + "Lefty", +}; + +static void hand_orient_changed(VariableItem* item) { + uint8_t index = variable_item_get_current_value_index(item); + variable_item_set_current_value_text(item, hand_mode[index]); + if(index) { + furi_hal_rtc_set_flag(FuriHalRtcFlagHandOrient); + } else { + furi_hal_rtc_reset_flag(FuriHalRtcFlagHandOrient); + } +} + const char* const sleep_method[] = { "Default", "Legacy", @@ -214,6 +229,12 @@ SystemSettings* system_settings_alloc(void) { uint8_t value_index; app->var_item_list = variable_item_list_alloc(); + item = variable_item_list_add( + app->var_item_list, "Hand Orient", COUNT_OF(hand_mode), hand_orient_changed, app); + value_index = furi_hal_rtc_is_flag_set(FuriHalRtcFlagHandOrient) ? 1 : 0; + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, hand_mode[value_index]); + item = variable_item_list_add( app->var_item_list, "Units", diff --git a/lib/momentum/settings.c b/lib/momentum/settings.c index 413c38d0e..315124c7c 100644 --- a/lib/momentum/settings.c +++ b/lib/momentum/settings.c @@ -23,7 +23,6 @@ MomentumSettings momentum_settings = { .lockscreen_prompt = true, // ON .lockscreen_transparent = false, // OFF .battery_icon = BatteryIconBarPercent, // Bar % - .statusbar_clock = false, // OFF .status_icons = true, // ON .bar_borders = true, // ON .bar_background = false, // OFF @@ -93,7 +92,6 @@ static const struct { {setting_bool(lockscreen_prompt)}, {setting_bool(lockscreen_transparent)}, {setting_enum(battery_icon, BatteryIconCount)}, - {setting_bool(statusbar_clock)}, {setting_bool(status_icons)}, {setting_bool(bar_borders)}, {setting_bool(bar_background)}, diff --git a/lib/momentum/settings.h b/lib/momentum/settings.h index 2f8e22d96..ee1341131 100644 --- a/lib/momentum/settings.h +++ b/lib/momentum/settings.h @@ -71,7 +71,6 @@ typedef struct { bool lockscreen_prompt; bool lockscreen_transparent; BatteryIcon battery_icon; - bool statusbar_clock; bool status_icons; bool bar_borders; bool bar_background;