[FL-2212] File validators and archive fixes #972
Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									84410c83b5
								
							
						
					
					
						commit
						6264ee8c3b
					
				| @ -25,4 +25,5 @@ struct ArchiveApp { | ||||
|     ArchiveBrowserView* browser; | ||||
|     TextInput* text_input; | ||||
|     char text_store[MAX_NAME_LEN]; | ||||
|     char file_extension[MAX_EXT_LEN + 1]; | ||||
| }; | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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; | ||||
|             } | ||||
| 
 | ||||
|             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; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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,12 +63,13 @@ 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"; | ||||
| 
 | ||||
|         if(str != NULL) | ||||
|             canvas_draw_str_aligned( | ||||
|                 canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); | ||||
| 
 | ||||
| @ -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; | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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<Scene> 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(); | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										9
									
								
								applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										9
									
								
								applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -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<TextInputVM>(); | ||||
| } | ||||
| 
 | ||||
| @ -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<TextInputVM>()->get_validator_callback_context(); | ||||
|     app->view_controller.get<TextInputVM>()->set_validator(NULL, NULL); | ||||
|     validator_is_file_free((ValidatorIsFile*)validator_context); | ||||
| 
 | ||||
|     app->view_controller.get<TextInputVM>()->clean(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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,6 +39,7 @@ void StringElement::set_text( | ||||
|     text = _text; | ||||
|     x = _x; | ||||
|     y = _y; | ||||
|     fit_width = _fit_w; | ||||
|     horizontal = _horizontal; | ||||
|     vertical = _vertical; | ||||
|     font = _font; | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -4,9 +4,6 @@ | ||||
| #include <lib/toolbox/path.h> | ||||
| #include <lib/flipper_file/flipper_file.h> | ||||
| 
 | ||||
| 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); | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| #include "../nfc_i.h" | ||||
| #include <lib/toolbox/random_name.h> | ||||
| #include <gui/modules/validators.h> | ||||
| 
 | ||||
| #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); | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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; | ||||
| }; | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Nikolay Minaylov
						Nikolay Minaylov