Desktop settings merge and refactor, keybinds improvements

- Keybinds in own code helper files
- Keybinds as flipper format, loaded only when ran, no limit on length
- Migrate from old keybinds
- Merge desktop settings refactors after LFS removal PR
- Statusbar clock setting in desktop settings like OFW
- Hand orient setting in system settings like OFW
This commit is contained in:
Willy-JL
2024-08-08 05:18:20 +02:00
parent 7905b829cf
commit 2b77091cac
24 changed files with 420 additions and 231 deletions

View File

@@ -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
*/

View File

@@ -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);

View File

@@ -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"

View File

@@ -0,0 +1,215 @@
#include "desktop_keybinds.h"
#include "desktop_keybinds_filename.h"
#include "desktop_i.h"
#include <flipper_format/flipper_format.h>
#include <storage/storage.h>
#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);
}
}
}

View File

@@ -0,0 +1,27 @@
#pragma once
#include <furi/core/string.h>
#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);

View File

@@ -0,0 +1,3 @@
#pragma once
#define DESKTOP_KEYBINDS_PATH INT_PATH(".desktop_keybinds.txt")

View File

@@ -1,50 +1,42 @@
#include "desktop_settings.h"
#include "desktop_settings_filename.h"
bool DESKTOP_SETTINGS_SAVE(DesktopSettings* x) {
return saved_struct_save(
#include <saved_struct.h>
#include <storage/storage.h>
#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;
}

View File

@@ -1,70 +1,12 @@
#pragma once
#include <furi_hal.h>
#include <stdint.h>
#include <stdbool.h>
#include <toolbox/saved_struct.h>
#include <storage/storage.h>
#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);

View File

@@ -0,0 +1,5 @@
#pragma once
#define DESKTOP_SETTINGS_FILE_NAME ".desktop.settings"
#define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME)

View File

@@ -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;