From 6264ee8c3b2c13a215fdcf643a8d1541dad1f990 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Sat, 29 Jan 2022 12:39:10 +0300 Subject: [PATCH] [FL-2212] File validators and archive fixes #972 Co-authored-by: Aleksandr Kutuzov --- applications/archive/archive_i.h | 1 + .../archive/helpers/archive_browser.c | 1 - .../archive/helpers/archive_favorites.c | 49 ++++++++++++++++++- applications/archive/helpers/archive_files.c | 8 +++ applications/archive/helpers/archive_files.h | 1 + .../archive/scenes/archive_scene_rename.c | 10 ++++ .../archive/views/archive_browser_view.h | 1 + .../desktop/scenes/desktop_scene_lock_menu.c | 8 ++- .../desktop/views/desktop_lock_menu.c | 20 +++++--- .../desktop/views/desktop_lock_menu.h | 2 +- applications/ibutton/ibutton_app.h | 8 +-- .../ibutton/scene/ibutton_scene_save_name.cpp | 9 ++++ .../irda/scene/irda_app_scene_edit_rename.cpp | 10 ++++ .../scene/lfrfid_app_scene_delete_confirm.cpp | 7 +-- .../scene/lfrfid_app_scene_read_success.cpp | 24 ++++----- .../scene/lfrfid_app_scene_save_name.cpp | 9 ++++ .../scene/lfrfid_app_scene_saved_info.cpp | 8 +-- .../lfrfid/view/elements/string_element.cpp | 15 +++++- .../lfrfid/view/elements/string_element.h | 2 + applications/nfc/nfc_device.c | 27 +++++----- applications/nfc/nfc_device.h | 4 ++ applications/nfc/scenes/nfc_scene_save_name.c | 10 ++++ .../view_modules/text_input_vm.cpp | 8 +++ .../view_modules/text_input_vm.h | 4 ++ 24 files changed, 194 insertions(+), 52 deletions(-) mode change 100755 => 100644 applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp diff --git a/applications/archive/archive_i.h b/applications/archive/archive_i.h index ba95ac4b..b450bb9c 100644 --- a/applications/archive/archive_i.h +++ b/applications/archive/archive_i.h @@ -25,4 +25,5 @@ struct ArchiveApp { ArchiveBrowserView* browser; TextInput* text_input; char text_store[MAX_NAME_LEN]; + char file_extension[MAX_EXT_LEN + 1]; }; diff --git a/applications/archive/helpers/archive_browser.c b/applications/archive/helpers/archive_browser.c index d52475cc..eb316c1e 100644 --- a/applications/archive/helpers/archive_browser.c +++ b/applications/archive/helpers/archive_browser.c @@ -272,7 +272,6 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) { with_view_model( browser->view, (ArchiveBrowserViewModel * model) { model->last_idx = model->idx; - model->last_offset = model->list_offset; model->idx = 0; model->depth = CLAMP(model->depth + 1, MAX_DEPTH, 0); return false; diff --git a/applications/archive/helpers/archive_favorites.c b/applications/archive/helpers/archive_favorites.c index 1e581502..b622e76f 100644 --- a/applications/archive/helpers/archive_favorites.c +++ b/applications/archive/helpers/archive_favorites.c @@ -31,6 +31,40 @@ uint16_t archive_favorites_count(void* context) { return lines; } +static bool archive_favourites_rescan() { + string_t buffer; + string_init(buffer); + FileWorker* file_worker = file_worker_alloc(true); + + bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); + if(result) { + while(1) { + if(!file_worker_read_until(file_worker, buffer, '\n')) { + break; + } + if(!string_size(buffer)) { + break; + } + + bool file_exists = false; + file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); + if(file_exists) { + archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer)); + } + } + } + + string_clear(buffer); + + file_worker_close(file_worker); + file_worker_remove(file_worker, ARCHIVE_FAV_PATH); + file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH); + + file_worker_free(file_worker); + + return result; +} + bool archive_favorites_read(void* context) { furi_assert(context); @@ -41,6 +75,8 @@ bool archive_favorites_read(void* context) { FileInfo file_info; string_init(buffer); + bool need_refresh = false; + bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); if(result) { @@ -52,13 +88,24 @@ bool archive_favorites_read(void* context) { break; } - archive_add_item(browser, &file_info, string_get_cstr(buffer)); + bool file_exists = false; + file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists); + + if(file_exists) + archive_add_item(browser, &file_info, string_get_cstr(buffer)); + else + need_refresh = true; string_reset(buffer); } } string_clear(buffer); file_worker_close(file_worker); file_worker_free(file_worker); + + if(need_refresh) { + archive_favourites_rescan(); + } + return result; } diff --git a/applications/archive/helpers/archive_files.c b/applications/archive/helpers/archive_files.c index 83b67a5b..a5bd2eb9 100644 --- a/applications/archive/helpers/archive_files.c +++ b/applications/archive/helpers/archive_files.c @@ -30,6 +30,14 @@ void archive_trim_file_path(char* name, bool ext) { } } +void archive_get_file_extension(char* name, char* ext) { + char* dot = strrchr(name, '.'); + if(dot == NULL) + *ext = '\0'; + else + strncpy(ext, dot, MAX_EXT_LEN); +} + void set_file_type(ArchiveFile_t* file, FileInfo* file_info) { furi_assert(file); furi_assert(file_info); diff --git a/applications/archive/helpers/archive_files.h b/applications/archive/helpers/archive_files.h index dd86a201..12fde2fb 100644 --- a/applications/archive/helpers/archive_files.h +++ b/applications/archive/helpers/archive_files.h @@ -50,6 +50,7 @@ ARRAY_DEF( bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name); void set_file_type(ArchiveFile_t* file, FileInfo* file_info); void archive_trim_file_path(char* name, bool ext); +void archive_get_file_extension(char* name, char* ext); bool archive_get_filenames(void* context, const char* path); bool archive_dir_empty(void* context, const char* path); bool archive_read_dir(void* context, const char* path); diff --git a/applications/archive/scenes/archive_scene_rename.c b/applications/archive/scenes/archive_scene_rename.c index 99ae8be4..8f32eb8a 100644 --- a/applications/archive/scenes/archive_scene_rename.c +++ b/applications/archive/scenes/archive_scene_rename.c @@ -18,6 +18,7 @@ void archive_scene_rename_on_enter(void* context) { ArchiveFile_t* current = archive_get_current_file(archive->browser); strlcpy(archive->text_store, string_get_cstr(current->name), MAX_NAME_LEN); + archive_get_file_extension(archive->text_store, archive->file_extension); archive_trim_file_path(archive->text_store, true); text_input_set_header_text(text_input, "Rename:"); @@ -30,6 +31,10 @@ void archive_scene_rename_on_enter(void* context) { MAX_TEXT_INPUT_LEN, false); + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(archive_get_path(archive->browser), archive->file_extension); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewTextInput); } @@ -74,6 +79,11 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) { void archive_scene_rename_on_exit(void* context) { ArchiveApp* archive = (ArchiveApp*)context; + // Clear view + void* validator_context = text_input_get_validator_callback_context(archive->text_input); + text_input_set_validator(archive->text_input, NULL, NULL); + validator_is_file_free(validator_context); + text_input_reset(archive->text_input); } diff --git a/applications/archive/views/archive_browser_view.h b/applications/archive/views/archive_browser_view.h index 91ce9ccc..634dec44 100644 --- a/applications/archive/views/archive_browser_view.h +++ b/applications/archive/views/archive_browser_view.h @@ -11,6 +11,7 @@ #define MAX_LEN_PX 110 #define MAX_NAME_LEN 255 +#define MAX_EXT_LEN 6 #define FRAME_HEIGHT 12 #define MENU_ITEMS 4 #define MAX_DEPTH 32 diff --git a/applications/desktop/scenes/desktop_scene_lock_menu.c b/applications/desktop/scenes/desktop_scene_lock_menu.c index 1c94b83e..7a3d51bb 100644 --- a/applications/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/desktop/scenes/desktop_scene_lock_menu.c @@ -18,6 +18,9 @@ void desktop_scene_lock_menu_on_enter(void* context) { desktop_lock_menu_set_callback(desktop->lock_menu, desktop_scene_lock_menu_callback, desktop); desktop_lock_menu_pin_set(desktop->lock_menu, desktop->settings.pincode.length > 0); + + uint8_t idx = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu); + desktop_lock_menu_set_idx(desktop->lock_menu, idx); view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewLockMenu); } @@ -30,6 +33,7 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { case DesktopLockMenuEventLock: scene_manager_set_scene_state( desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedNoPin); + scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); consumed = true; break; @@ -39,12 +43,14 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedWithPin); scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); } else { + scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1); scene_manager_next_scene(desktop->scene_manager, DesktopScenePinSetup); } consumed = true; break; case DesktopLockMenuEventExit: + scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); scene_manager_search_and_switch_to_previous_scene( desktop->scene_manager, DesktopSceneMain); consumed = true; @@ -57,6 +63,4 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { } void desktop_scene_lock_menu_on_exit(void* context) { - Desktop* desktop = (Desktop*)context; - desktop_lock_menu_reset_idx(desktop->lock_menu); } diff --git a/applications/desktop/views/desktop_lock_menu.c b/applications/desktop/views/desktop_lock_menu.c index ad8a0a3f..d65aa30d 100644 --- a/applications/desktop/views/desktop_lock_menu.c +++ b/applications/desktop/views/desktop_lock_menu.c @@ -4,6 +4,8 @@ #include "../desktop_i.h" #include "desktop_lock_menu.h" +#define LOCK_MENU_ITEMS_NB 3 + void desktop_lock_menu_set_callback( DesktopLockMenuView* lock_menu, DesktopLockMenuViewCallback callback, @@ -22,10 +24,11 @@ void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set) }); } -void desktop_lock_menu_reset_idx(DesktopLockMenuView* lock_menu) { +void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) { + furi_assert(idx < LOCK_MENU_ITEMS_NB); with_view_model( lock_menu->view, (DesktopLockMenuViewModel * model) { - model->idx = 0; + model->idx = idx; return true; }); } @@ -51,7 +54,7 @@ static void lock_menu_callback(void* context, uint8_t index) { } void desktop_lock_menu_render(Canvas* canvas, void* model) { - const char* Lockmenu_Items[3] = {"Lock", "Lock with PIN", "DUMB mode"}; + const char* Lockmenu_Items[LOCK_MENU_ITEMS_NB] = {"Lock", "Lock with PIN", "DUMB mode"}; DesktopLockMenuViewModel* m = model; canvas_clear(canvas); @@ -60,14 +63,15 @@ void desktop_lock_menu_render(Canvas* canvas, void* model) { canvas_draw_icon(canvas, 116, 0 + STATUS_BAR_Y_SHIFT, &I_DoorRight_70x55); canvas_set_font(canvas, FontSecondary); - for(uint8_t i = 0; i < 3; ++i) { + for(uint8_t i = 0; i < LOCK_MENU_ITEMS_NB; ++i) { const char* str = Lockmenu_Items[i]; if(i == 1 && !m->pin_set) str = "Set PIN"; if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not implemented"; - canvas_draw_str_aligned( - canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); + if(str != NULL) + canvas_draw_str_aligned( + canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); if(m->idx == i) elements_frame(canvas, 15, 1 + (i * 17) + STATUS_BAR_Y_SHIFT, 98, 15); } @@ -90,9 +94,9 @@ bool desktop_lock_menu_input(InputEvent* event, void* context) { lock_menu->view, (DesktopLockMenuViewModel * model) { model->hint_timeout = 0; // clear hint timeout if(event->key == InputKeyUp) { - model->idx = CLAMP(model->idx - 1, 2, 0); + model->idx = CLAMP(model->idx - 1, LOCK_MENU_ITEMS_NB - 1, 0); } else if(event->key == InputKeyDown) { - model->idx = CLAMP(model->idx + 1, 2, 0); + model->idx = CLAMP(model->idx + 1, LOCK_MENU_ITEMS_NB - 1, 0); } idx = model->idx; return true; diff --git a/applications/desktop/views/desktop_lock_menu.h b/applications/desktop/views/desktop_lock_menu.h index 80854520..e9928a38 100644 --- a/applications/desktop/views/desktop_lock_menu.h +++ b/applications/desktop/views/desktop_lock_menu.h @@ -28,6 +28,6 @@ void desktop_lock_menu_set_callback( View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu); void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set); -void desktop_lock_menu_reset_idx(DesktopLockMenuView* lock_menu); +void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx); DesktopLockMenuView* desktop_lock_menu_alloc(); void desktop_lock_menu_free(DesktopLockMenuView* lock_menu); diff --git a/applications/ibutton/ibutton_app.h b/applications/ibutton/ibutton_app.h index 402d4cdf..fc2a32e7 100644 --- a/applications/ibutton/ibutton_app.h +++ b/applications/ibutton/ibutton_app.h @@ -64,6 +64,10 @@ public: SceneAddValue, }; + static const char* app_folder; + static const char* app_extension; + static const char* app_filetype; + iButtonAppViewManager* get_view_manager(); void switch_to_next_scene(Scene index); void search_and_switch_to_previous_scene(std::initializer_list scenes_list); @@ -137,10 +141,6 @@ private: static const uint8_t text_store_size = 128; char text_store[text_store_size + 1]; - static const char* app_folder; - static const char* app_extension; - static const char* app_filetype; - bool load_key_data(string_t key_path); void make_app_folder(); }; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton_scene_save_name.cpp b/applications/ibutton/scene/ibutton_scene_save_name.cpp index 5b85d409..0d5c5900 100644 --- a/applications/ibutton/scene/ibutton_scene_save_name.cpp +++ b/applications/ibutton/scene/ibutton_scene_save_name.cpp @@ -25,6 +25,10 @@ void iButtonSceneSaveName::on_enter(iButtonApp* app) { text_input_set_result_callback( text_input, callback, app, app->get_text_store(), IBUTTON_KEY_NAME_SIZE, key_name_empty); + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(app->app_folder, app->app_extension); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewTextInput); } @@ -48,6 +52,11 @@ bool iButtonSceneSaveName::on_event(iButtonApp* app, iButtonEvent* event) { void iButtonSceneSaveName::on_exit(iButtonApp* app) { TextInput* text_input = app->get_view_manager()->get_text_input(); + + void* validator_context = text_input_get_validator_callback_context(text_input); + text_input_set_validator(text_input, NULL, NULL); + validator_is_file_free((ValidatorIsFile*)validator_context); + text_input_reset(text_input); } diff --git a/applications/irda/scene/irda_app_scene_edit_rename.cpp b/applications/irda/scene/irda_app_scene_edit_rename.cpp index f9253eaf..db6b8e4d 100644 --- a/applications/irda/scene/irda_app_scene_edit_rename.cpp +++ b/applications/irda/scene/irda_app_scene_edit_rename.cpp @@ -20,6 +20,10 @@ void IrdaAppSceneEditRename::on_enter(IrdaApp* app) { strncpy(app->get_text_store(0), remote_name.c_str(), app->get_text_store_size()); enter_name_length = IrdaAppRemoteManager::max_remote_name_length; text_input_set_header_text(text_input, "Name the remote"); + + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(app->irda_directory, app->irda_extension); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); } text_input_set_result_callback( @@ -59,4 +63,10 @@ bool IrdaAppSceneEditRename::on_event(IrdaApp* app, IrdaAppEvent* event) { } void IrdaAppSceneEditRename::on_exit(IrdaApp* app) { + TextInput* text_input = app->get_view_manager()->get_text_input(); + + void* validator_context = text_input_get_validator_callback_context(text_input); + text_input_set_validator(text_input, NULL, NULL); + + if(validator_context != NULL) validator_is_file_free((ValidatorIsFile*)validator_context); } diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp index c3d2621f..8f8fe9af 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp @@ -35,9 +35,9 @@ void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool need_restore) { string_printf(string_header, "Delete %s?", key.get_name()); line_1->set_text( - string_get_cstr(string_header), 64, 19, AlignCenter, AlignBottom, FontPrimary); + string_get_cstr(string_header), 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary); line_2->set_text( - string_get_cstr(string_data), 64, 29, AlignCenter, AlignBottom, FontSecondary); + string_get_cstr(string_data), 64, 29, 0, AlignCenter, AlignBottom, FontSecondary); switch(key.get_type()) { case LfrfidKeyType::KeyEM4100: @@ -52,12 +52,13 @@ void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool need_restore) { break; } line_3->set_text( - string_get_cstr(string_decrypted), 64, 39, AlignCenter, AlignBottom, FontSecondary); + string_get_cstr(string_decrypted), 64, 39, 0, AlignCenter, AlignBottom, FontSecondary); line_4->set_text( lfrfid_key_get_type_string(key.get_type()), 64, 49, + 0, AlignCenter, AlignBottom, FontSecondary); diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp index 70dc208c..46ff90ef 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp @@ -36,9 +36,9 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) { switch(app->worker.key.get_type()) { case LfrfidKeyType::KeyEM4100: - line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary); - line_2_text->set_text("Mod:", 65, 35, AlignRight, AlignBottom, FontSecondary); - line_3_text->set_text("ID:", 65, 47, AlignRight, AlignBottom, FontSecondary); + line_1_text->set_text("HEX:", 65, 23, 0, AlignRight, AlignBottom, FontSecondary); + line_2_text->set_text("Mod:", 65, 35, 0, AlignRight, AlignBottom, FontSecondary); + line_3_text->set_text("ID:", 65, 47, 0, AlignRight, AlignBottom, FontSecondary); for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) { string_cat_printf(string[0], "%02X", data[i]); @@ -48,17 +48,17 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) { string_printf(string[2], "%03u,%05u", data[2], (uint16_t)((data[3] << 8) | (data[4]))); line_1_value->set_text( - string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary); + string_get_cstr(string[0]), 68, 23, 0, AlignLeft, AlignBottom, FontSecondary); line_2_value->set_text( - string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary); + string_get_cstr(string[1]), 68, 35, 0, AlignLeft, AlignBottom, FontSecondary); line_3_value->set_text( - string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary); + string_get_cstr(string[2]), 68, 47, 0, AlignLeft, AlignBottom, FontSecondary); break; case LfrfidKeyType::KeyH10301: case LfrfidKeyType::KeyI40134: - line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary); - line_2_text->set_text("FC:", 65, 35, AlignRight, AlignBottom, FontSecondary); - line_3_text->set_text("Card:", 65, 47, AlignRight, AlignBottom, FontSecondary); + line_1_text->set_text("HEX:", 65, 23, 0, AlignRight, AlignBottom, FontSecondary); + line_2_text->set_text("FC:", 65, 35, 0, AlignRight, AlignBottom, FontSecondary); + line_3_text->set_text("Card:", 65, 47, 0, AlignRight, AlignBottom, FontSecondary); for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) { string_cat_printf(string[0], "%02X", data[i]); @@ -68,11 +68,11 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) { string_printf(string[2], "%u", (uint16_t)((data[1] << 8) | (data[2]))); line_1_value->set_text( - string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary); + string_get_cstr(string[0]), 68, 23, 0, AlignLeft, AlignBottom, FontSecondary); line_2_value->set_text( - string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary); + string_get_cstr(string[1]), 68, 35, 0, AlignLeft, AlignBottom, FontSecondary); line_3_value->set_text( - string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary); + string_get_cstr(string[2]), 68, 47, 0, AlignLeft, AlignBottom, FontSecondary); break; } diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp old mode 100755 new mode 100644 index 76165941..e5fee4fe --- a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp @@ -21,6 +21,10 @@ void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool need_restore) { app->worker.key.get_name_length(), key_name_empty); + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(app->app_folder, app->app_extension); + text_input->set_validator(validator_is_file_callback, validator_is_file); + app->view_controller.switch_to(); } @@ -46,6 +50,11 @@ bool LfRfidAppSceneSaveName::on_event(LfRfidApp* app, LfRfidApp::Event* event) { } void LfRfidAppSceneSaveName::on_exit(LfRfidApp* app) { + void* validator_context = + app->view_controller.get()->get_validator_callback_context(); + app->view_controller.get()->set_validator(NULL, NULL); + validator_is_file_free((ValidatorIsFile*)validator_context); + app->view_controller.get()->clean(); } diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp index 45463d46..b054e141 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp @@ -28,8 +28,9 @@ void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool need_restore) { string_cat_printf(string_data, "%02X", data[i]); } - line_1->set_text(key.get_name(), 64, 17, AlignCenter, AlignBottom, FontSecondary); - line_2->set_text(string_get_cstr(string_data), 64, 29, AlignCenter, AlignBottom, FontPrimary); + line_1->set_text(key.get_name(), 64, 17, 128 - 2, AlignCenter, AlignBottom, FontSecondary); + line_2->set_text( + string_get_cstr(string_data), 64, 29, 0, AlignCenter, AlignBottom, FontPrimary); switch(key.get_type()) { case LfrfidKeyType::KeyEM4100: @@ -44,12 +45,13 @@ void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool need_restore) { break; } line_3->set_text( - string_get_cstr(string_decrypted), 64, 39, AlignCenter, AlignBottom, FontSecondary); + string_get_cstr(string_decrypted), 64, 39, 0, AlignCenter, AlignBottom, FontSecondary); line_4->set_text( lfrfid_key_get_type_string(key.get_type()), 64, 49, + 0, AlignCenter, AlignBottom, FontSecondary); diff --git a/applications/lfrfid/view/elements/string_element.cpp b/applications/lfrfid/view/elements/string_element.cpp index 92bb7abd..028bd7fd 100644 --- a/applications/lfrfid/view/elements/string_element.cpp +++ b/applications/lfrfid/view/elements/string_element.cpp @@ -9,8 +9,17 @@ StringElement::~StringElement() { void StringElement::draw(Canvas* canvas) { if(text) { + string_t line; + string_init(line); + string_set_str(line, text); + canvas_set_font(canvas, font); - elements_multiline_text_aligned(canvas, x, y, horizontal, vertical, text); + if(fit_width != 0) { + elements_string_fit_width(canvas, line, fit_width); + } + elements_multiline_text_aligned(canvas, x, y, horizontal, vertical, string_get_cstr(line)); + + string_clear(line); } } @@ -22,6 +31,7 @@ void StringElement::set_text( const char* _text, uint8_t _x, uint8_t _y, + uint8_t _fit_w, Align _horizontal, Align _vertical, Font _font) { @@ -29,8 +39,9 @@ void StringElement::set_text( text = _text; x = _x; y = _y; + fit_width = _fit_w; horizontal = _horizontal; vertical = _vertical; font = _font; unlock_model(true); -} +} \ No newline at end of file diff --git a/applications/lfrfid/view/elements/string_element.h b/applications/lfrfid/view/elements/string_element.h index 4bc5364d..173fdd60 100644 --- a/applications/lfrfid/view/elements/string_element.h +++ b/applications/lfrfid/view/elements/string_element.h @@ -12,6 +12,7 @@ public: const char* text = NULL, uint8_t x = 0, uint8_t y = 0, + uint8_t fit_width = 0, Align horizontal = AlignLeft, Align vertical = AlignTop, Font font = FontPrimary); @@ -20,6 +21,7 @@ private: const char* text = NULL; uint8_t x = 0; uint8_t y = 0; + uint8_t fit_width = 0; Align horizontal = AlignLeft; Align vertical = AlignTop; Font font = FontPrimary; diff --git a/applications/nfc/nfc_device.c b/applications/nfc/nfc_device.c index cfd0db2d..d6996b3f 100755 --- a/applications/nfc/nfc_device.c +++ b/applications/nfc/nfc_device.c @@ -4,9 +4,6 @@ #include #include -static const char* nfc_app_folder = "/any/nfc"; -static const char* nfc_app_extension = ".nfc"; -static const char* nfc_app_shadow_extension = ".shd"; static const char* nfc_file_header = "Flipper NFC device"; static const uint32_t nfc_file_version = 2; @@ -243,7 +240,7 @@ static bool nfc_device_save_file( do { // Create nfc directory if necessary - if(!storage_simply_mkdir(dev->storage, nfc_app_folder)) break; + if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break; // First remove nfc device file if it was saved string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); // Open file @@ -281,12 +278,12 @@ static bool nfc_device_save_file( } bool nfc_device_save(NfcDevice* dev, const char* dev_name) { - return nfc_device_save_file(dev, dev_name, nfc_app_folder, nfc_app_extension); + return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_EXTENSION); } bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) { dev->shadow_file_exist = true; - return nfc_device_save_file(dev, dev_name, nfc_app_folder, nfc_app_shadow_extension); + return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION); } static bool nfc_device_load_data(NfcDevice* dev, string_t path) { @@ -300,9 +297,9 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path) { do { // Check existance of shadow file - size_t ext_start = string_search_str(path, nfc_app_extension); + size_t ext_start = string_search_str(path, NFC_APP_EXTENSION); string_set_n(temp_str, path, 0, ext_start); - string_cat_printf(temp_str, "%s", nfc_app_shadow_extension); + string_cat_printf(temp_str, "%s", NFC_APP_SHADOW_EXTENSION); dev->shadow_file_exist = storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK; // Open shadow file if it exists. If not - open original @@ -374,15 +371,15 @@ bool nfc_file_select(NfcDevice* dev) { // Input events and views are managed by file_select bool res = dialog_file_select_show( dev->dialogs, - nfc_app_folder, - nfc_app_extension, + NFC_APP_FOLDER, + NFC_APP_EXTENSION, dev->file_name, sizeof(dev->file_name), dev->dev_name); if(res) { string_t dev_str; // Get key file path - string_init_printf(dev_str, "%s/%s%s", nfc_app_folder, dev->file_name, nfc_app_extension); + string_init_printf(dev_str, "%s/%s%s", NFC_APP_FOLDER, dev->file_name, NFC_APP_EXTENSION); res = nfc_device_load_data(dev, dev_str); if(res) { nfc_device_set_name(dev, dev->file_name); @@ -409,12 +406,12 @@ bool nfc_device_delete(NfcDevice* dev) { do { // Delete original file - string_init_printf(file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension); + string_init_printf(file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; // Delete shadow file if it exists if(dev->shadow_file_exist) { string_printf( - file_path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension); + file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; } deleted = true; @@ -437,10 +434,10 @@ bool nfc_device_restore(NfcDevice* dev) { do { string_init_printf( - path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension); + path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); if(!storage_simply_remove(dev->storage, string_get_cstr(path))) break; dev->shadow_file_exist = false; - string_printf(path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension); + string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); if(!nfc_device_load_data(dev, path)) break; restored = true; } while(0); diff --git a/applications/nfc/nfc_device.h b/applications/nfc/nfc_device.h index 888f0c2f..cf0c389c 100644 --- a/applications/nfc/nfc_device.h +++ b/applications/nfc/nfc_device.h @@ -10,6 +10,10 @@ #define NFC_DEV_NAME_MAX_LEN 22 #define NFC_FILE_NAME_MAX_LEN 120 +#define NFC_APP_FOLDER "/any/nfc" +#define NFC_APP_EXTENSION ".nfc" +#define NFC_APP_SHADOW_EXTENSION ".shd" + typedef enum { NfcDeviceNfca, NfcDeviceNfcb, diff --git a/applications/nfc/scenes/nfc_scene_save_name.c b/applications/nfc/scenes/nfc_scene_save_name.c index 83a60e38..c66484ff 100755 --- a/applications/nfc/scenes/nfc_scene_save_name.c +++ b/applications/nfc/scenes/nfc_scene_save_name.c @@ -1,5 +1,6 @@ #include "../nfc_i.h" #include +#include #define SCENE_SAVE_NAME_CUSTOM_EVENT (0UL) @@ -29,6 +30,11 @@ void nfc_scene_save_name_on_enter(void* context) { nfc->text_store, NFC_DEV_NAME_MAX_LEN, dev_name_empty); + + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); } @@ -60,5 +66,9 @@ void nfc_scene_save_name_on_exit(void* context) { Nfc* nfc = (Nfc*)context; // Clear view + void* validator_context = text_input_get_validator_callback_context(nfc->text_input); + text_input_set_validator(nfc->text_input, NULL, NULL); + validator_is_file_free(validator_context); + text_input_reset(nfc->text_input); } diff --git a/lib/app-scened-template/view_modules/text_input_vm.cpp b/lib/app-scened-template/view_modules/text_input_vm.cpp index 06f243de..05e5ed1d 100644 --- a/lib/app-scened-template/view_modules/text_input_vm.cpp +++ b/lib/app-scened-template/view_modules/text_input_vm.cpp @@ -29,3 +29,11 @@ void TextInputVM::set_result_callback( void TextInputVM::set_header_text(const char* text) { text_input_set_header_text(text_input, text); } + +void TextInputVM::set_validator(TextInputValidatorCallback callback, void* callback_context) { + text_input_set_validator(text_input, callback, callback_context); +} + +void* TextInputVM::get_validator_callback_context() { + return text_input_get_validator_callback_context(text_input); +} diff --git a/lib/app-scened-template/view_modules/text_input_vm.h b/lib/app-scened-template/view_modules/text_input_vm.h index 3aedc9be..8fafe861 100644 --- a/lib/app-scened-template/view_modules/text_input_vm.h +++ b/lib/app-scened-template/view_modules/text_input_vm.h @@ -32,6 +32,10 @@ public: */ void set_header_text(const char* text); + void set_validator(TextInputValidatorCallback callback, void* callback_context); + + void* get_validator_callback_context(); + private: TextInput* text_input; }; \ No newline at end of file