diff --git a/applications/external b/applications/external index e2762e90d..e896285c5 160000 --- a/applications/external +++ b/applications/external @@ -1 +1 @@ -Subproject commit e2762e90dc1afa490f0de5fd3865de31ca8358ac +Subproject commit e896285c57caf626f759241a6dd1b5758943305d diff --git a/applications/main/archive/helpers/archive_favorites.c b/applications/main/archive/helpers/archive_favorites.c index db0700386..fad900e69 100644 --- a/applications/main/archive/helpers/archive_favorites.c +++ b/applications/main/archive/helpers/archive_favorites.c @@ -104,9 +104,9 @@ static bool archive_favourites_rescan() { furi_string_free(buffer); storage_file_close(file); - if(storage_common_move(storage, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH) == FSE_NOT_EXIST) { - storage_common_remove(storage, ARCHIVE_FAV_PATH); - } + storage_common_remove(storage, ARCHIVE_FAV_PATH); + storage_common_rename(storage, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH); + storage_common_remove(storage, ARCHIVE_FAV_TEMP_PATH); storage_file_free(file); furi_record_close(RECORD_STORAGE); @@ -203,9 +203,9 @@ bool archive_favorites_delete(const char* format, ...) { furi_string_free(filename); storage_file_close(file); - if(storage_common_move(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH) == FSE_NOT_EXIST) { - storage_common_remove(fs_api, ARCHIVE_FAV_PATH); - } + storage_common_remove(fs_api, ARCHIVE_FAV_PATH); + storage_common_rename(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH); + storage_common_remove(fs_api, ARCHIVE_FAV_TEMP_PATH); storage_file_free(file); furi_record_close(RECORD_STORAGE); @@ -282,9 +282,9 @@ bool archive_favorites_rename(const char* src, const char* dst) { furi_string_free(path); storage_file_close(file); - if(storage_common_move(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH) == FSE_NOT_EXIST) { - storage_common_remove(fs_api, ARCHIVE_FAV_PATH); - } + storage_common_remove(fs_api, ARCHIVE_FAV_PATH); + storage_common_rename(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH); + storage_common_remove(fs_api, ARCHIVE_FAV_TEMP_PATH); storage_file_free(file); furi_record_close(RECORD_STORAGE); @@ -310,9 +310,9 @@ void archive_favorites_save(void* context) { archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", furi_string_get_cstr(item->path)); } - if(storage_common_move(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH) == FSE_NOT_EXIST) { - storage_common_remove(fs_api, ARCHIVE_FAV_PATH); - } + storage_common_remove(fs_api, ARCHIVE_FAV_PATH); + storage_common_rename(fs_api, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH); + storage_common_remove(fs_api, ARCHIVE_FAV_TEMP_PATH); storage_file_free(file); furi_record_close(RECORD_STORAGE); diff --git a/applications/main/archive/helpers/archive_files.c b/applications/main/archive/helpers/archive_files.c index e839fc772..3e78c0d1b 100644 --- a/applications/main/archive/helpers/archive_files.c +++ b/applications/main/archive/helpers/archive_files.c @@ -178,7 +178,7 @@ FS_Error archive_copy_rename_file_or_dir( if(copy) { error = storage_common_copy(fs_api, src_path, furi_string_get_cstr(dst_path)); } else { - error = storage_common_rename(fs_api, src_path, furi_string_get_cstr(dst_path)); + error = storage_common_rename_safe(fs_api, src_path, furi_string_get_cstr(dst_path)); } } furi_record_close(RECORD_STORAGE); diff --git a/applications/main/bad_kb/bad_kb_app.c b/applications/main/bad_kb/bad_kb_app.c index 1c3156bcd..d5a1ae27c 100644 --- a/applications/main/bad_kb/bad_kb_app.c +++ b/applications/main/bad_kb/bad_kb_app.c @@ -108,6 +108,17 @@ static void bad_kb_save_settings(BadKbApp* app) { furi_record_close(RECORD_STORAGE); } +void bad_kb_app_show_loading_popup(BadKbApp* app, bool show) { + if(show) { + // Raise timer priority so that animations can play + furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated); + view_dispatcher_switch_to_view(app->view_dispatcher, BadKbAppViewLoading); + } else { + // Restore default timer priority + furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal); + } +} + BadKbApp* bad_kb_app_alloc(char* arg) { BadKbApp* app = malloc(sizeof(BadKbApp)); @@ -119,11 +130,6 @@ BadKbApp* bad_kb_app_alloc(char* arg) { furi_string_set(app->file_path, arg); } - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_rename(storage, EXT_PATH("badusb"), BAD_KB_APP_BASE_FOLDER); - storage_simply_mkdir(storage, BAD_KB_APP_BASE_FOLDER); - furi_record_close(RECORD_STORAGE); - bad_kb_load_settings(app); app->gui = furi_record_open(RECORD_GUI); @@ -184,6 +190,10 @@ BadKbApp* bad_kb_app_alloc(char* arg) { view_dispatcher_add_view( app->view_dispatcher, BadKbAppViewByteInput, byte_input_get_view(app->byte_input)); + app->loading = loading_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, BadKbAppViewLoading, loading_get_view(app->loading)); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); app->conn_mode = BadKbConnModeNone; @@ -230,6 +240,10 @@ void bad_kb_app_free(BadKbApp* app) { view_dispatcher_remove_view(app->view_dispatcher, BadKbAppViewByteInput); byte_input_free(app->byte_input); + // Loading + view_dispatcher_remove_view(app->view_dispatcher, BadKbAppViewLoading); + loading_free(app->loading); + // View dispatcher view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); diff --git a/applications/main/bad_kb/bad_kb_app.h b/applications/main/bad_kb/bad_kb_app.h index e2786d301..08945b832 100644 --- a/applications/main/bad_kb/bad_kb_app.h +++ b/applications/main/bad_kb/bad_kb_app.h @@ -23,5 +23,8 @@ typedef enum { BadKbAppViewWork, BadKbAppViewVarItemList, BadKbAppViewByteInput, - BadKbAppViewTextInput + BadKbAppViewTextInput, + BadKbAppViewLoading, } BadKbAppView; + +void bad_kb_app_show_loading_popup(BadKbApp* app, bool show); diff --git a/applications/main/bad_kb/helpers/ducky_script.h b/applications/main/bad_kb/helpers/ducky_script.h index 7ed928efe..a4a3ef7b4 100644 --- a/applications/main/bad_kb/helpers/ducky_script.h +++ b/applications/main/bad_kb/helpers/ducky_script.h @@ -13,6 +13,7 @@ extern "C" { #include #include #include +#include #include "../views/bad_kb_view.h" #include "../bad_kb_paths.h" @@ -137,6 +138,7 @@ struct BadKbApp { VariableItemList* var_item_list; TextInput* text_input; ByteInput* byte_input; + Loading* loading; char usb_name_buf[BAD_KB_USB_LEN]; uint16_t usb_vidpid_buf[2]; char bt_name_buf[BAD_KB_NAME_LEN]; diff --git a/applications/main/bad_kb/scenes/bad_kb_scene_file_select.c b/applications/main/bad_kb/scenes/bad_kb_scene_file_select.c index 635b4f318..3dd9f669c 100644 --- a/applications/main/bad_kb/scenes/bad_kb_scene_file_select.c +++ b/applications/main/bad_kb/scenes/bad_kb_scene_file_select.c @@ -6,6 +6,32 @@ static bool bad_kb_file_select(BadKbApp* bad_kb) { furi_assert(bad_kb); + bad_kb_app_show_loading_popup(bad_kb, true); + Storage* storage = furi_record_open(RECORD_STORAGE); + if(storage_dir_exists(storage, EXT_PATH("badusb"))) { + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_header(message, "Migrate BadUSB?", 64, 0, AlignCenter, AlignTop); + dialog_message_set_buttons(message, "No", NULL, "Yes"); + dialog_message_set_text( + message, + "A badusb folder was found!\n" + "XFW uses the badkb folder.\n" + "Want to transfer the files?", + 64, + 32, + AlignCenter, + AlignCenter); + DialogMessageButton res = dialog_message_show(furi_record_open(RECORD_DIALOGS), message); + dialog_message_free(message); + furi_record_close(RECORD_DIALOGS); + if(res == DialogMessageButtonRight) { + storage_common_migrate(storage, EXT_PATH("badusb"), BAD_KB_APP_BASE_FOLDER); + } + } + storage_simply_mkdir(storage, BAD_KB_APP_BASE_FOLDER); + furi_record_close(RECORD_STORAGE); + bad_kb_app_show_loading_popup(bad_kb, false); + DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options( &browser_options, BAD_KB_APP_SCRIPT_EXTENSION, &I_badkb_10px); diff --git a/applications/main/ibutton/scenes/ibutton_scene_write.c b/applications/main/ibutton/scenes/ibutton_scene_write.c index 180f53e59..80bf13447 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_write.c +++ b/applications/main/ibutton/scenes/ibutton_scene_write.c @@ -42,7 +42,7 @@ void ibutton_scene_write_on_enter(void* context) { furi_string_printf( tmp, - "[%s]\n%s", + "[%s]\n%s ", ibutton_protocols_get_name(ibutton->protocols, protocol_id), ibutton->key_name); diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 8811063eb..e93a90183 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -109,6 +109,15 @@ App( sources=["plugins/supported_cards/kazan.c"], ) +App( + appid="sonicare_parser", + apptype=FlipperAppType.PLUGIN, + entry_point="sonicare_plugin_ep", + targets=["f7"], + requires=["nfc"], + sources=["plugins/supported_cards/sonicare.c"], +) + App( appid="nfc_start", targets=["f7"], diff --git a/applications/main/nfc/helpers/protocol_support/st25tb/mykey.c b/applications/main/nfc/helpers/protocol_support/st25tb/mykey.c index 5b75e10f2..61ac4e179 100644 --- a/applications/main/nfc/helpers/protocol_support/st25tb/mykey.c +++ b/applications/main/nfc/helpers/protocol_support/st25tb/mykey.c @@ -1,7 +1,7 @@ #include "mykey.h" uint32_t encode_decode_block(uint32_t input) { - /* + /* * Swap all values using XOR * 32 bit: 1111222233334444 */ @@ -14,13 +14,11 @@ uint32_t encode_decode_block(uint32_t input) { return input; } - - -void endian_swap_uint8_array(uint8_t *array, size_t size) { +void endian_swap_uint8_array(uint8_t* array, size_t size) { size_t i; uint8_t temp; - for (i = 0; i < size / 2; i++) { + for(i = 0; i < size / 2; i++) { temp = array[i]; array[i] = array[size - 1 - i]; array[size - 1 - i] = temp; @@ -42,7 +40,7 @@ uint32_t get_block(uint32_t block) { return encode_decode_block(st25tb_get_block_value(block)); } -//decode for credit +//decode for credit uint32_t get_xored_block(uint32_t block, uint32_t key) { return encode_decode_block(st25tb_get_block_value(block) ^ key); } \ No newline at end of file diff --git a/applications/main/nfc/helpers/protocol_support/st25tb/mykey.h b/applications/main/nfc/helpers/protocol_support/st25tb/mykey.h index 70d3d4403..bdd3da3e9 100644 --- a/applications/main/nfc/helpers/protocol_support/st25tb/mykey.h +++ b/applications/main/nfc/helpers/protocol_support/st25tb/mykey.h @@ -19,11 +19,13 @@ typedef enum { } LockIdStatus; #define get_uid(uid) ((uid)[7] | ((uid)[6] << 8) | ((uid)[5] << 16) | ((uid)[4] << 24)) -#define new_get_count_down_counter(b6) (~(b6 << 24 | (b6 & 0x0000FF00) << 8 | (b6 & 0x00FF0000) >> 8 | b6 >> 24)) +#define new_get_count_down_counter(b6) \ + (~(b6 << 24 | (b6 & 0x0000FF00) << 8 | (b6 & 0x00FF0000) >> 8 | b6 >> 24)) #define get_vendor(b1, b2) (get_block(b1) << 16 | (get_block(b2) & 0x0000FFFF)) #define get_master_key(uid, vendor_id) ((uid) * ((vendor_id) + 1)) #define get_is_bound(vendor_id) ((vendor_id) != MYKEY_DEFAULT_VENDOR_ID) -#define get_encryption_key(master_key, count_down_counter)((master_key) * ((count_down_counter) + 1)) +#define get_encryption_key(master_key, count_down_counter) \ + ((master_key) * ((count_down_counter) + 1)) uint32_t encode_decode_block(uint32_t input); uint32_t st25tb_get_block_value(uint32_t block); diff --git a/applications/main/nfc/helpers/protocol_support/st25tb/st25tb_render.c b/applications/main/nfc/helpers/protocol_support/st25tb/st25tb_render.c index 7d6fa9eda..474c1ffe4 100644 --- a/applications/main/nfc/helpers/protocol_support/st25tb/st25tb_render.c +++ b/applications/main/nfc/helpers/protocol_support/st25tb/st25tb_render.c @@ -12,15 +12,18 @@ void nfc_render_st25tb_info( } uint32_t _uid = get_uid(data->uid); - uint32_t _count_down_counter_new = new_get_count_down_counter(st25tb_get_block_value(data->blocks[6])); - uint32_t _vendor_id = get_vendor(data->blocks[MYKEY_BLOCK_VENDOR_ID_1], data->blocks[MYKEY_BLOCK_VENDOR_ID_2]); + uint32_t _count_down_counter_new = + new_get_count_down_counter(st25tb_get_block_value(data->blocks[6])); + uint32_t _vendor_id = + get_vendor(data->blocks[MYKEY_BLOCK_VENDOR_ID_1], data->blocks[MYKEY_BLOCK_VENDOR_ID_2]); uint32_t _master_key = get_master_key(_uid, _vendor_id); uint32_t _encryption_key = get_encryption_key(_master_key, _count_down_counter_new); uint16_t credit = get_xored_block(data->blocks[MYKEY_BLOCK_CURRENT_CREDIT], _encryption_key); uint16_t _previous_credit = get_block(data->blocks[MYKEY_BLOCK_PREVIOUS_CREDIT]); bool _is_bound = get_is_bound(_vendor_id); furi_string_cat_printf(str, "\nCurrent Credit: %d.%02d E", credit / 100, credit % 100); - furi_string_cat_printf(str, "\nPrevius Credit: %d.%02d E", _previous_credit / 100, _previous_credit % 100); + furi_string_cat_printf( + str, "\nPrevius Credit: %d.%02d E", _previous_credit / 100, _previous_credit % 100); furi_string_cat_printf(str, "\nIs Bound: %s \n", _is_bound ? "Yes" : "No"); if(format_type == NfcProtocolFormatTypeFull) { @@ -34,7 +37,11 @@ void nfc_render_st25tb_info( furi_string_cat_printf(str, "\nBlocks:"); for(size_t i = 0; i < st25tb_get_block_count(data->type); i += 2) { furi_string_cat_printf( - str, "\n %02X %08lX %08lX", i, st25tb_get_block_value(data->blocks[i]), st25tb_get_block_value(data->blocks[i + 1])); + str, + "\n %02X %08lX %08lX", + i, + st25tb_get_block_value(data->blocks[i]), + st25tb_get_block_value(data->blocks[i + 1])); } } } diff --git a/applications/main/nfc/plugins/supported_cards/sonicare.c b/applications/main/nfc/plugins/supported_cards/sonicare.c new file mode 100644 index 000000000..a52a6589f --- /dev/null +++ b/applications/main/nfc/plugins/supported_cards/sonicare.c @@ -0,0 +1,111 @@ +// Parser for Philips Sonicare toothbrush heads. +// Made by @Sil333033 +// Thanks to Cyrill Künzi for this research! https://kuenzi.dev/toothbrush/ + +#include "nfc_supported_card_plugin.h" + +#include +#include + +#define TAG "Sonicare" + +typedef enum { + SonicareHeadWhite, + SonicareHeadBlack, + SonicareHeadUnkown, +} SonicareHead; + +static SonicareHead sonicare_get_head_type(const MfUltralightData* data) { + // data.page[34].data got 4 bytes + // 31:32:31:34 for black (not sure) + // 31:31:31:31 for white (not sure) + // the data should be in here based on the research, but i cant find it. + // page 34 byte 0 is always 0x30 for the white brushes i have, so i guess thats white + // TODO: Get a black brush and test this + + if(data->page[34].data[0] == 0x30) { + return SonicareHeadWhite; + } else { + return SonicareHeadUnkown; + } +} + +static uint32_t sonicare_get_seconds_brushed(const MfUltralightData* data) { + uint32_t seconds_brushed = 0; + + seconds_brushed += data->page[36].data[0]; + seconds_brushed += data->page[36].data[1] << 8; + + return seconds_brushed; +} + +static bool sonicare_parse(const NfcDevice* device, FuriString* parsed_data) { + furi_assert(device); + furi_assert(parsed_data); + + const MfUltralightData* data = nfc_device_get_data(device, NfcProtocolMfUltralight); + + bool parsed = false; + + do { + // Check for NDEF link match + const char* test = "philips.com/nfcbrushheadtap"; + // Data is a array of arrays, cast to char array and compare + if(strncmp(test, (const char*)&data->page[5].data[3], strlen(test)) != 0) { + FURI_LOG_D(TAG, "Not a Philips Sonicare head"); + break; + } + + const SonicareHead head_type = sonicare_get_head_type(data); + const uint32_t seconds_brushed = sonicare_get_seconds_brushed(data); + + FuriString* head_type_str = furi_string_alloc(); + + switch(head_type) { + case SonicareHeadWhite: + furi_string_printf(head_type_str, "White"); + break; + case SonicareHeadBlack: + furi_string_printf(head_type_str, "Black"); + break; + case SonicareHeadUnkown: + default: + furi_string_printf(head_type_str, "Unknown"); + break; + } + + furi_string_printf( + parsed_data, + "\e#Philips Sonicare head\nColor: %s\nTime brushed: %02.0f:%02.0f:%02ld\n", + furi_string_get_cstr(head_type_str), + floor(seconds_brushed / 3600), + floor((seconds_brushed / 60) % 60), + seconds_brushed % 60); + + furi_string_free(head_type_str); + + parsed = true; + } while(false); + + return parsed; +} + +/* Actual implementation of app<>plugin interface */ +static const NfcSupportedCardsPlugin sonicare_plugin = { + .protocol = NfcProtocolMfUltralight, + .verify = NULL, + .read = NULL, + .parse = sonicare_parse, +}; + +/* Plugin descriptor to comply with basic plugin specification */ +static const FlipperAppPluginDescriptor sonicare_plugin_descriptor = { + .appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID, + .ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION, + .entry_point = &sonicare_plugin, +}; + +/* Plugin entry point - must return a pointer to const descriptor */ +const FlipperAppPluginDescriptor* sonicare_plugin_ep() { + return &sonicare_plugin_descriptor; +} diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_graphics.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_graphics.c index 0420af5f5..f0f77b9f5 100644 --- a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_graphics.c +++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_graphics.c @@ -5,7 +5,7 @@ enum VarItemListIndex { VarItemListIndexAnimSpeed, VarItemListIndexCycleAnims, VarItemListIndexUnlockAnims, - VarItemListIndexFallbackAnim, + VarItemListIndexCreditsAnim, }; void xtreme_app_scene_interface_graphics_var_item_list_callback(void* context, uint32_t index) { @@ -18,6 +18,10 @@ static void xtreme_app_scene_interface_graphics_asset_pack_changed(VariableItem* uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text( item, index == 0 ? "Default" : *CharList_get(app->asset_pack_names, index - 1)); + variable_item_set_locked( + variable_item_list_get(app->var_item_list, VarItemListIndexCreditsAnim), + index != 0, + "Credits\nare in\ndefault pack!"); strlcpy( xtreme_settings.asset_pack, index == 0 ? "" : *CharList_get(app->asset_pack_names, index - 1), @@ -66,8 +70,10 @@ static void xtreme_app_scene_interface_graphics_anim_speed_changed(VariableItem* const char* const cycle_anims_names[] = { "OFF", "Meta.txt", + "15 S", "30 S", "1 M", + "2 M", "5 M", "10 M", "15 M", @@ -81,8 +87,10 @@ const char* const cycle_anims_names[] = { const int32_t cycle_anims_values[COUNT_OF(cycle_anims_names)] = { -1, 0, + 15, 30, 60, + 120, 300, 600, 900, @@ -109,11 +117,11 @@ static void xtreme_app_scene_interface_graphics_unlock_anims_changed(VariableIte app->save_settings = true; } -static void xtreme_app_scene_interface_graphics_fallback_anim_changed(VariableItem* item) { +static void xtreme_app_scene_interface_graphics_credits_anim_changed(VariableItem* item) { XtremeApp* 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"); - xtreme_settings.fallback_anim = value; + xtreme_settings.credits_anim = value; app->save_settings = true; } @@ -171,10 +179,11 @@ void xtreme_app_scene_interface_graphics_on_enter(void* context) { var_item_list, "Credits Anim", 2, - xtreme_app_scene_interface_graphics_fallback_anim_changed, + xtreme_app_scene_interface_graphics_credits_anim_changed, app); - variable_item_set_current_value_index(item, xtreme_settings.fallback_anim); - variable_item_set_current_value_text(item, xtreme_settings.fallback_anim ? "ON" : "OFF"); + variable_item_set_current_value_index(item, xtreme_settings.credits_anim); + variable_item_set_current_value_text(item, xtreme_settings.credits_anim ? "ON" : "OFF"); + variable_item_set_locked(item, app->asset_pack_index != 0, "Credits\nare in\ndefault pack!"); variable_item_list_set_enter_callback( var_item_list, xtreme_app_scene_interface_graphics_var_item_list_callback, app); diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu.c index d9f973790..da3ab1040 100644 --- a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu.c +++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_mainmenu.c @@ -139,14 +139,28 @@ bool xtreme_app_scene_interface_mainmenu_on_event(void* context, SceneManagerEve app->mainmenu_app_labels, app->mainmenu_app_index, app->mainmenu_app_index + 1); CharList_remove_v( app->mainmenu_app_exes, app->mainmenu_app_index, app->mainmenu_app_index + 1); - if(app->mainmenu_app_index) app->mainmenu_app_index--; /* fall through */ - case VarItemListIndexMoveApp: + case VarItemListIndexMoveApp: { app->save_mainmenu_apps = true; app->require_reboot = true; - scene_manager_previous_scene(app->scene_manager); - scene_manager_next_scene(app->scene_manager, XtremeAppSceneInterfaceMainmenu); + size_t count = CharList_size(app->mainmenu_app_labels); + VariableItem* item = variable_item_list_get(app->var_item_list, VarItemListIndexApp); + if(count) { + app->mainmenu_app_index = CLAMP(app->mainmenu_app_index, count - 1, 0U); + char label[20]; + snprintf(label, 20, "App %u/%u", 1 + app->mainmenu_app_index, count); + variable_item_set_item_label(item, label); + variable_item_set_current_value_text( + item, *CharList_get(app->mainmenu_app_labels, app->mainmenu_app_index)); + } else { + app->mainmenu_app_index = 0; + variable_item_set_item_label(item, "App"); + variable_item_set_current_value_text(item, "None"); + } + variable_item_set_current_value_index(item, app->mainmenu_app_index); + variable_item_set_values_count(item, count); break; + } case VarItemListIndexAddApp: scene_manager_next_scene(app->scene_manager, XtremeAppSceneInterfaceMainmenuAdd); break; diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_misc_screen.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_misc_screen.c index e58236102..ba5cae6d0 100644 --- a/applications/main/xtreme_app/scenes/xtreme_app_scene_misc_screen.c +++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_misc_screen.c @@ -48,6 +48,7 @@ static const struct { {"Fuchsia", {255, 0, 255}}, {"Pink", {173, 31, 173}}, {"Brown", {165, 42, 42}}, {"White", {255, 192, 203}}, }; +static const size_t lcd_sz = COUNT_OF(lcd_colors); static void xtreme_app_scene_misc_screen_lcd_color_changed(VariableItem* item, uint8_t led) { XtremeApp* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -64,6 +65,14 @@ static void xtreme_app_scene_misc_screen_lcd_color_1_changed(VariableItem* item) static void xtreme_app_scene_misc_screen_lcd_color_2_changed(VariableItem* item) { xtreme_app_scene_misc_screen_lcd_color_changed(item, 2); } +static const struct { + uint8_t led; + VariableItemChangeCallback cb; +} lcd_cols[] = { + {0, xtreme_app_scene_misc_screen_lcd_color_0_changed}, + {1, xtreme_app_scene_misc_screen_lcd_color_1_changed}, + {2, xtreme_app_scene_misc_screen_lcd_color_2_changed}, +}; const char* const rainbow_lcd_names[RGBBacklightRainbowModeCount] = { "OFF", @@ -158,16 +167,6 @@ void xtreme_app_scene_misc_screen_on_enter(void* context) { item = variable_item_list_add(var_item_list, "RGB Backlight", 1, NULL, app); variable_item_set_current_value_text(item, xtreme_settings.rgb_backlight ? "ON" : "OFF"); - struct { - uint8_t led; - VariableItemChangeCallback cb; - } lcd_cols[] = { - {0, xtreme_app_scene_misc_screen_lcd_color_0_changed}, - {1, xtreme_app_scene_misc_screen_lcd_color_1_changed}, - {2, xtreme_app_scene_misc_screen_lcd_color_2_changed}, - }; - size_t lcd_sz = COUNT_OF(lcd_colors); - RgbColor color; for(size_t i = 0; i < COUNT_OF(lcd_cols); i++) { char name[12]; @@ -285,8 +284,31 @@ bool xtreme_app_scene_misc_screen_on_event(void* context, SceneManagerEvent even app->save_backlight = true; notification_message(app->notification, &sequence_display_backlight_on); rgb_backlight_reconfigure(xtreme_settings.rgb_backlight); - scene_manager_previous_scene(app->scene_manager); - scene_manager_next_scene(app->scene_manager, XtremeAppSceneMiscScreen); + variable_item_set_current_value_text( + variable_item_list_get(app->var_item_list, VarItemListIndexRgbBacklight), + xtreme_settings.rgb_backlight ? "ON" : "OFF"); + for(size_t i = 0; i < COUNT_OF(lcd_cols); i++) { + variable_item_set_locked( + variable_item_list_get(app->var_item_list, VarItemListIndexLcdColor0 + i), + !xtreme_settings.rgb_backlight, + "Needs RGB\nBacklight!"); + } + variable_item_set_locked( + variable_item_list_get(app->var_item_list, VarItemListIndexRainbowLcd), + !xtreme_settings.rgb_backlight, + "Needs RGB\nBacklight!"); + variable_item_set_locked( + variable_item_list_get(app->var_item_list, VarItemListIndexRainbowSpeed), + !xtreme_settings.rgb_backlight, + "Needs RGB\nBacklight!"); + variable_item_set_locked( + variable_item_list_get(app->var_item_list, VarItemListIndexRainbowInterval), + !xtreme_settings.rgb_backlight, + "Needs RGB\nBacklight!"); + variable_item_set_locked( + variable_item_list_get(app->var_item_list, VarItemListIndexRainbowSaturation), + !xtreme_settings.rgb_backlight, + "Needs RGB\nBacklight!"); } break; } diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols_freqs_hopper.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols_freqs_hopper.c index 13fdc0ac2..4dabdbeeb 100644 --- a/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols_freqs_hopper.c +++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols_freqs_hopper.c @@ -71,16 +71,32 @@ bool xtreme_app_scene_protocols_freqs_hopper_on_event(void* context, SceneManage *FrequencyList_get(app->subghz_hopper_freqs, app->subghz_hopper_index); FrequencyList_it_t it; FrequencyList_it(it, app->subghz_hopper_freqs); + size_t removed = 0; while(!FrequencyList_end_p(it)) { if(*FrequencyList_ref(it) == value) { FrequencyList_remove(app->subghz_hopper_freqs, it); + removed++; } else { FrequencyList_next(it); } } app->save_subghz_freqs = true; - scene_manager_previous_scene(app->scene_manager); - scene_manager_next_scene(app->scene_manager, XtremeAppSceneProtocolsFreqsHopper); + VariableItem* item = + variable_item_list_get(app->var_item_list, VarItemListIndexHopperFrequency); + variable_item_set_values_count(item, FrequencyList_size(app->subghz_hopper_freqs)); + if(FrequencyList_size(app->subghz_hopper_freqs)) { + app->subghz_hopper_index -= removed; + uint32_t value = + *FrequencyList_get(app->subghz_hopper_freqs, app->subghz_hopper_index); + char text[10] = {0}; + snprintf( + text, sizeof(text), "%lu.%02lu", value / 1000000, (value % 1000000) / 10000); + variable_item_set_current_value_text(item, text); + } else { + app->subghz_hopper_index = 0; + variable_item_set_current_value_text(item, "None"); + } + variable_item_set_current_value_index(item, app->subghz_hopper_index); break; case VarItemListIndexAddHopperFreq: scene_manager_set_scene_state( diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols_freqs_static.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols_freqs_static.c index 2f139b2b2..fdfcde35a 100644 --- a/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols_freqs_static.c +++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols_freqs_static.c @@ -71,16 +71,32 @@ bool xtreme_app_scene_protocols_freqs_static_on_event(void* context, SceneManage *FrequencyList_get(app->subghz_static_freqs, app->subghz_static_index); FrequencyList_it_t it; FrequencyList_it(it, app->subghz_static_freqs); + size_t removed = 0; while(!FrequencyList_end_p(it)) { if(*FrequencyList_ref(it) == value) { FrequencyList_remove(app->subghz_static_freqs, it); + removed++; } else { FrequencyList_next(it); } } app->save_subghz_freqs = true; - scene_manager_previous_scene(app->scene_manager); - scene_manager_next_scene(app->scene_manager, XtremeAppSceneProtocolsFreqsStatic); + VariableItem* item = + variable_item_list_get(app->var_item_list, VarItemListIndexStaticFrequency); + variable_item_set_values_count(item, FrequencyList_size(app->subghz_static_freqs)); + if(FrequencyList_size(app->subghz_static_freqs)) { + app->subghz_static_index -= removed; + uint32_t value = + *FrequencyList_get(app->subghz_static_freqs, app->subghz_static_index); + char text[10] = {0}; + snprintf( + text, sizeof(text), "%lu.%02lu", value / 1000000, (value % 1000000) / 10000); + variable_item_set_current_value_text(item, text); + } else { + app->subghz_static_index = 0; + variable_item_set_current_value_text(item, "None"); + } + variable_item_set_current_value_index(item, app->subghz_static_index); break; case VarItemListIndexAddStaticFreq: scene_manager_set_scene_state( diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index 042afb7d5..aaf40ef8a 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -17,9 +17,10 @@ #define TAG "AnimationManager" -#define HARDCODED_ANIMATION_NAME "thank_you_128x64" +#define HARDCODED_ANIMATION_NAME "L1_AnimationError_128x64" #define NO_SD_ANIMATION_NAME "L1_NoSd_128x49" #define BAD_BATTERY_ANIMATION_NAME "L1_BadBattery_128x47" +#define CREDITS_ANIMATION_NAME "Credits_128x64" #define NO_DB_ANIMATION_NAME "L0_NoDb_128x51" #define BAD_SD_ANIMATION_NAME "L0_SdBad_128x51" @@ -388,7 +389,7 @@ static StorageAnimation* uint32_t whole_weight = 0; // Filter valid animations - bool fallback = xtreme_settings.fallback_anim; + bool skip_credits = !xtreme_settings.credits_anim && xtreme_settings.asset_pack[0] == '\0'; bool unlock = xtreme_settings.unlock_anims; StorageAnimationList_it_t it; for(StorageAnimationList_it(it, animation_list); !StorageAnimationList_end_p(it);) { @@ -397,8 +398,11 @@ static StorageAnimation* animation_storage_get_meta(storage_animation); bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats, unlock); - if(strcmp(manifest_info->name, HARDCODED_ANIMATION_NAME) == 0 && !fallback) { - // Skip fallback animation + if(strcmp(manifest_info->name, HARDCODED_ANIMATION_NAME) == 0) { + // Dont pick error anim randomly + valid = false; + } else if(skip_credits && strcmp(manifest_info->name, CREDITS_ANIMATION_NAME) == 0) { + // Dont pick credits anim if disabled valid = false; } @@ -543,7 +547,8 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m animation_storage_get_meta(restore_animation); bool valid = animation_manager_is_valid_idle_animation( manifest_info, &stats, xtreme_settings.unlock_anims); - if(valid) { + // Restore only if anim is valid and not the error anim + if(valid && strcmp(manifest_info->name, HARDCODED_ANIMATION_NAME) != 0) { animation_manager_replace_current_animation( animation_manager, restore_animation); animation_manager->state = AnimationManagerStateIdle; diff --git a/applications/services/gui/modules/variable_item_list.c b/applications/services/gui/modules/variable_item_list.c index 736fe0975..25e4f39fe 100644 --- a/applications/services/gui/modules/variable_item_list.c +++ b/applications/services/gui/modules/variable_item_list.c @@ -543,6 +543,23 @@ VariableItem* variable_item_list_add( return item; } +VariableItem* variable_item_list_get(VariableItemList* variable_item_list, uint8_t position) { + VariableItem* item = NULL; + furi_assert(variable_item_list); + + with_view_model( + variable_item_list->view, + VariableItemListModel * model, + { + if(position < VariableItemArray_size(model->items)) { + item = VariableItemArray_get(model->items, position); + } + }, + true); + + return item; +} + void variable_item_list_set_enter_callback( VariableItemList* variable_item_list, VariableItemListEnterCallback callback, diff --git a/applications/services/gui/modules/variable_item_list.h b/applications/services/gui/modules/variable_item_list.h index 4079e5a5f..c5bb3628b 100644 --- a/applications/services/gui/modules/variable_item_list.h +++ b/applications/services/gui/modules/variable_item_list.h @@ -59,6 +59,15 @@ VariableItem* variable_item_list_add( VariableItemChangeCallback change_callback, void* context); +/** Get item in VariableItemList + * + * @param variable_item_list VariableItemList instance + * @param position index of the item to get + * + * @return VariableItem* item instance + */ +VariableItem* variable_item_list_get(VariableItemList* variable_item_list, uint8_t position); + /** Set enter callback * * @param variable_item_list VariableItemList instance diff --git a/applications/services/rpc/rpc_storage.c b/applications/services/rpc/rpc_storage.c index 825e6df82..5fd232642 100644 --- a/applications/services/rpc/rpc_storage.c +++ b/applications/services/rpc/rpc_storage.c @@ -651,7 +651,7 @@ static void rpc_system_storage_rename_process(const PB_Main* request, void* cont Storage* fs_api = furi_record_open(RECORD_STORAGE); if(path_contains_only_ascii(request->content.storage_rename_request.new_path)) { - FS_Error error = storage_common_rename( + FS_Error error = storage_common_rename_safe( fs_api, request->content.storage_rename_request.old_path, request->content.storage_rename_request.new_path); diff --git a/applications/services/storage/storage.h b/applications/services/storage/storage.h index 7449b7c60..bcca46e30 100644 --- a/applications/services/storage/storage.h +++ b/applications/services/storage/storage.h @@ -312,6 +312,7 @@ FS_Error storage_common_remove(Storage* storage, const char* path); * @brief Rename a file or a directory. * * The file or the directory must NOT be open. + * Will overwrite the destination file if it already exists. * * Renaming a regular file to itself does nothing and always succeeds. * Renaming a directory to itself or to a subdirectory of itself always fails. @@ -324,20 +325,20 @@ FS_Error storage_common_remove(Storage* storage, const char* path); FS_Error storage_common_rename(Storage* storage, const char* old_path, const char* new_path); /** - * @brief Move a file or a directory. + * @brief Rename a file or a directory. * * The file or the directory must NOT be open. - * Will overwrite the destination file if it already exists. + * Will error FSE_EXIST if the destination file already exists. * - * Moving a regular file to itself does nothing and always succeeds. - * Moving a directory to itself or to a subdirectory of itself always fails. + * Renaming a regular file to itself does nothing and always succeeds. + * Renaming a directory to itself or to a subdirectory of itself always fails. * * @param storage pointer to a storage API instance. * @param old_path pointer to a zero-terminated string containing the source path. * @param new_path pointer to a zero-terminated string containing the destination path. - * @return FSE_OK if the file or directory has been successfully moved, any other error code on failure. + * @return FSE_OK if the file or directory has been successfully renamed, any other error code on failure. */ -FS_Error storage_common_move(Storage* storage, const char* old_path, const char* new_path); +FS_Error storage_common_rename_safe(Storage* storage, const char* old_path, const char* new_path); /** * @brief Copy the file to a new location. diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c index ae35d6bbb..209e77c39 100644 --- a/applications/services/storage/storage_cli.c +++ b/applications/services/storage/storage_cli.c @@ -454,7 +454,7 @@ static void storage_cli_rename(Cli* cli, FuriString* old_path, FuriString* args) if(!args_read_probably_quoted_string_and_trim(args, new_path)) { storage_cli_print_usage(); } else { - FS_Error error = storage_common_rename( + FS_Error error = storage_common_rename_safe( api, furi_string_get_cstr(old_path), furi_string_get_cstr(new_path)); if(error != FSE_OK) { diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index 8cdf78617..0c6ff2295 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -479,12 +479,13 @@ FS_Error storage_common_rename(Storage* storage, const char* old_path, const cha break; } - if(storage_common_exists(storage, new_path)) { - error = FSE_EXIST; - break; - } - if(storage_dir_exists(storage, old_path)) { + // Cannot overwrite a file with a directory + if(storage_file_exists(storage, new_path)) { + error = FSE_INVALID_NAME; + break; + } + // Cannot rename a directory to itself or to a nested directory if(storage_common_equivalent_path(storage, old_path, new_path, true)) { error = FSE_INVALID_NAME; @@ -497,6 +498,10 @@ FS_Error storage_common_rename(Storage* storage, const char* old_path, const cha break; } + if(storage_file_exists(storage, new_path)) { + storage_common_remove(storage, new_path); + } + S_API_PROLOGUE; SAData data = { .rename = { @@ -525,7 +530,7 @@ FS_Error storage_common_rename(Storage* storage, const char* old_path, const cha return error; } -FS_Error storage_common_move(Storage* storage, const char* old_path, const char* new_path) { +FS_Error storage_common_rename_safe(Storage* storage, const char* old_path, const char* new_path) { FS_Error error; do { @@ -534,30 +539,24 @@ FS_Error storage_common_move(Storage* storage, const char* old_path, const char* break; } - if(storage_dir_exists(storage, old_path)) { - // Cannot overwrite a file with a directory - if(storage_file_exists(storage, new_path)) { - error = FSE_INVALID_NAME; - break; - } + if(storage_common_exists(storage, new_path)) { + error = FSE_EXIST; + break; + } - // Cannot move a directory to itself or to a nested directory + if(storage_dir_exists(storage, old_path)) { + // Cannot rename a directory to itself or to a nested directory if(storage_common_equivalent_path(storage, old_path, new_path, true)) { error = FSE_INVALID_NAME; break; } - // Moving a regular file to itself does nothing and always succeeds + // Renaming a regular file to itself does nothing and always succeeds } else if(storage_common_equivalent_path(storage, old_path, new_path, false)) { error = FSE_OK; break; } - if(storage_common_exists(storage, new_path)) { - error = storage_simply_remove_recursive(storage, new_path); - if(error != FSE_OK) break; - } - S_API_PROLOGUE; SAData data = { .rename = { @@ -756,7 +755,7 @@ static FS_Error if(error == FSE_OK) { if(file_info_is_dir(&fileinfo)) { if(!copy) { - error = storage_common_rename(storage, old_path, new_path); + error = storage_common_rename_safe(storage, old_path, new_path); } if(copy || error != FSE_OK) { error = storage_merge_recursive(storage, old_path, new_path, copy); @@ -814,7 +813,7 @@ static FS_Error stream_free(stream_from); stream_free(stream_to); } else { - error = storage_common_rename(storage, old_path, new_path_tmp); + error = storage_common_rename_safe(storage, old_path, new_path_tmp); } } } diff --git a/assets/dolphin/internal/thank_you_128x64/frame_0.png b/assets/dolphin/external/Credits_128x64/frame_0.png similarity index 100% rename from assets/dolphin/internal/thank_you_128x64/frame_0.png rename to assets/dolphin/external/Credits_128x64/frame_0.png diff --git a/assets/dolphin/internal/thank_you_128x64/frame_1.png b/assets/dolphin/external/Credits_128x64/frame_1.png similarity index 100% rename from assets/dolphin/internal/thank_you_128x64/frame_1.png rename to assets/dolphin/external/Credits_128x64/frame_1.png diff --git a/assets/dolphin/internal/thank_you_128x64/frame_2.png b/assets/dolphin/external/Credits_128x64/frame_2.png similarity index 100% rename from assets/dolphin/internal/thank_you_128x64/frame_2.png rename to assets/dolphin/external/Credits_128x64/frame_2.png diff --git a/assets/dolphin/internal/thank_you_128x64/frame_3.png b/assets/dolphin/external/Credits_128x64/frame_3.png similarity index 100% rename from assets/dolphin/internal/thank_you_128x64/frame_3.png rename to assets/dolphin/external/Credits_128x64/frame_3.png diff --git a/assets/dolphin/internal/thank_you_128x64/frame_4.png b/assets/dolphin/external/Credits_128x64/frame_4.png similarity index 100% rename from assets/dolphin/internal/thank_you_128x64/frame_4.png rename to assets/dolphin/external/Credits_128x64/frame_4.png diff --git a/assets/dolphin/internal/thank_you_128x64/frame_5.png b/assets/dolphin/external/Credits_128x64/frame_5.png similarity index 100% rename from assets/dolphin/internal/thank_you_128x64/frame_5.png rename to assets/dolphin/external/Credits_128x64/frame_5.png diff --git a/assets/dolphin/internal/thank_you_128x64/meta.txt b/assets/dolphin/external/Credits_128x64/meta.txt similarity index 100% rename from assets/dolphin/internal/thank_you_128x64/meta.txt rename to assets/dolphin/external/Credits_128x64/meta.txt diff --git a/assets/dolphin/external/manifest.txt b/assets/dolphin/external/manifest.txt index 4921c5523..fc4d112fe 100644 --- a/assets/dolphin/external/manifest.txt +++ b/assets/dolphin/external/manifest.txt @@ -175,3 +175,10 @@ Max butthurt: 14 Min level: 22 Max level: 30 Weight: 4 + +Name: Credits_128x64 +Min butthurt: 0 +Max butthurt: 14 +Min level: 6 +Max level: 30 +Weight: 1 diff --git a/assets/dolphin/internal/L1_AnimationError_128x64/frame_0.png b/assets/dolphin/internal/L1_AnimationError_128x64/frame_0.png new file mode 100644 index 000000000..5133056c2 Binary files /dev/null and b/assets/dolphin/internal/L1_AnimationError_128x64/frame_0.png differ diff --git a/assets/dolphin/internal/L1_AnimationError_128x64/meta.txt b/assets/dolphin/internal/L1_AnimationError_128x64/meta.txt new file mode 100644 index 000000000..bfac2e1fa --- /dev/null +++ b/assets/dolphin/internal/L1_AnimationError_128x64/meta.txt @@ -0,0 +1,14 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 1 +Active frames: 0 +Frames order: 0 +Active cycles: 0 +Frame rate: 1 +Duration: 30 +Active cooldown: 0 + +Bubble slots: 0 diff --git a/assets/dolphin/internal/manifest.txt b/assets/dolphin/internal/manifest.txt index 48dc597a8..e85c199eb 100644 --- a/assets/dolphin/internal/manifest.txt +++ b/assets/dolphin/internal/manifest.txt @@ -2,7 +2,7 @@ Filetype: Flipper Animation Manifest Version: 1 # Animation 1 -Name: thank_you_128x64 +Name: L1_AnimationError_128x64 Min butthurt: 0 Max butthurt: 14 Min level: 1 diff --git a/furi/flipper.c b/furi/flipper.c index 1ebaccdf1..0b33858fe 100644 --- a/furi/flipper.c +++ b/furi/flipper.c @@ -49,7 +49,7 @@ void flipper_migrate_files() { storage_common_remove(storage, INT_PATH(".passport.settings")); storage_common_remove(storage, INT_PATH(".region_data")); - // Migrate files + // Migrate files (use copy+remove to not overwrite dst but still delete src) FURI_LOG_I(TAG, "Migrate: Renames on external"); storage_common_copy(storage, ARCHIVE_FAV_OLD_PATH, ARCHIVE_FAV_PATH); storage_common_remove(storage, ARCHIVE_FAV_OLD_PATH); @@ -65,7 +65,7 @@ void flipper_migrate_files() { storage_common_remove(storage, POWER_SETTINGS_OLD_PATH); storage_common_copy(storage, BT_KEYS_STORAGE_OLD_PATH, BT_KEYS_STORAGE_PATH); storage_common_remove(storage, BT_KEYS_STORAGE_OLD_PATH); - storage_common_copy(storage, NOTIFICATION_SETTINGS_OLD_PATH, NOTIFICATION_SETTINGS_PATH); + // storage_common_copy(storage, NOTIFICATION_SETTINGS_OLD_PATH, NOTIFICATION_SETTINGS_PATH); // Not compatible anyway storage_common_remove(storage, NOTIFICATION_SETTINGS_OLD_PATH); // Ext -> Int FURI_LOG_I(TAG, "Migrate: External to Internal"); @@ -77,7 +77,7 @@ void flipper_migrate_files() { FileInfo file_info; if(storage_common_stat(storage, U2F_CNT_OLD_FILE, &file_info) == FSE_OK && file_info.size > 200) { // Is on Int and has content - storage_common_move(storage, U2F_CNT_OLD_FILE, U2F_CNT_FILE); // Int -> Ext + storage_common_rename(storage, U2F_CNT_OLD_FILE, U2F_CNT_FILE); // Int -> Ext } storage_common_copy(storage, U2F_KEY_OLD_FILE, U2F_KEY_FILE); // Ext -> Int diff --git a/lib/xtreme/settings.c b/lib/xtreme/settings.c index d178fae48..b4d5b652e 100644 --- a/lib/xtreme/settings.c +++ b/lib/xtreme/settings.c @@ -10,7 +10,7 @@ XtremeSettings xtreme_settings = { .anim_speed = 100, // 100% .cycle_anims = 0, // Meta.txt .unlock_anims = false, // OFF - .fallback_anim = true, // ON + .credits_anim = true, // ON .menu_style = MenuStyleWii, // Wii .lock_on_boot = false, // OFF .bad_pins_format = false, // OFF @@ -69,8 +69,8 @@ void XTREME_SETTINGS_LOAD() { x->unlock_anims = b; } flipper_format_rewind(file); - if(flipper_format_read_bool(file, "fallback_anim", &b, 1)) { - x->fallback_anim = b; + if(flipper_format_read_bool(file, "credits_anim", &b, 1)) { + x->credits_anim = b; } flipper_format_rewind(file); if(flipper_format_read_uint32(file, "menu_style", &u, 1)) { @@ -209,7 +209,7 @@ void XTREME_SETTINGS_SAVE() { flipper_format_write_uint32(file, "anim_speed", &x->anim_speed, 1); flipper_format_write_int32(file, "cycle_anims", &x->cycle_anims, 1); flipper_format_write_bool(file, "unlock_anims", &x->unlock_anims, 1); - flipper_format_write_bool(file, "fallback_anim", &x->fallback_anim, 1); + flipper_format_write_bool(file, "credits_anim", &x->credits_anim, 1); e = x->menu_style; flipper_format_write_uint32(file, "menu_style", &e, 1); flipper_format_write_bool(file, "bad_pins_format", &x->bad_pins_format, 1); diff --git a/lib/xtreme/xtreme.h b/lib/xtreme/xtreme.h index 47760797d..f8b0e8761 100644 --- a/lib/xtreme/xtreme.h +++ b/lib/xtreme/xtreme.h @@ -57,7 +57,7 @@ typedef struct { uint32_t anim_speed; int32_t cycle_anims; bool unlock_anims; - bool fallback_anim; + bool credits_anim; MenuStyle menu_style; bool lock_on_boot; bool bad_pins_format; diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index cc083b2ec..1c7a8f8b4 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -2814,9 +2814,9 @@ Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, ui Function,+,storage_common_merge,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_migrate,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_mkdir,FS_Error,"Storage*, const char*" -Function,+,storage_common_move,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_remove,FS_Error,"Storage*, const char*" Function,+,storage_common_rename,FS_Error,"Storage*, const char*, const char*" +Function,+,storage_common_rename_safe,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_resolve_path_and_ensure_app_directory,void,"Storage*, FuriString*" Function,+,storage_common_stat,FS_Error,"Storage*, const char*, FileInfo*" Function,+,storage_common_timestamp,FS_Error,"Storage*, const char*, uint32_t*" @@ -3239,6 +3239,7 @@ Function,+,variable_item_get_current_value_index,uint8_t,VariableItem* Function,+,variable_item_list_add,VariableItem*,"VariableItemList*, const char*, uint8_t, VariableItemChangeCallback, void*" Function,+,variable_item_list_alloc,VariableItemList*, Function,+,variable_item_list_free,void,VariableItemList* +Function,+,variable_item_list_get,VariableItem*,"VariableItemList*, uint8_t" Function,+,variable_item_list_get_selected_item_index,uint8_t,VariableItemList* Function,+,variable_item_list_get_view,View*,VariableItemList* Function,+,variable_item_list_reset,void,VariableItemList*