From 72ef61bc49efcae94bcdb26dd01760d09a96a4b2 Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Sun, 4 Aug 2024 20:50:53 -0400 Subject: [PATCH] save works fine --- key_copier.c | 380 +++++++++++++++++++++++++------------------------- key_formats.h | 4 +- 2 files changed, 192 insertions(+), 192 deletions(-) diff --git a/key_copier.c b/key_copier.c index 16403f3..e6f429b 100644 --- a/key_copier.c +++ b/key_copier.c @@ -14,8 +14,10 @@ #include "key_formats.h" #include "key_copier.h" #include +#include #include #include +#include #define TAG "KeyCopier" @@ -26,8 +28,10 @@ // Our application menu has 3 items. You can add more items if you want. typedef enum { + KeyCopierSubmenuIndexMeasure, KeyCopierSubmenuIndexConfigure, - KeyCopierSubmenuIndexGame, + KeyCopierSubmenuIndexSave, + KeyCopierSubmenuIndexLoad, KeyCopierSubmenuIndexAbout, } KeyCopierSubmenuIndex; @@ -35,8 +39,11 @@ typedef enum { typedef enum { KeyCopierViewSubmenu, // The menu when the app starts KeyCopierViewTextInput, // Input for configuring text settings - KeyCopierViewConfigure, // The configuration screen - KeyCopierViewGame, // The main screen + KeyCopierViewConfigure_i, // The configuration screen + KeyCopierViewConfigure_e, // The configuration screen + KeyCopierViewSave, + KeyCopierViewLoad, + KeyCopierViewMeasure, // The main screen KeyCopierViewAbout, // The about screen with directions, link to social channel, etc. } KeyCopierView; @@ -51,13 +58,17 @@ typedef struct { Submenu* submenu; // The application menu TextInput* text_input; // The text input screen VariableItemList* variable_item_list_config; // The configuration screen - View* view_game; // The main screen + View* view_measure; // The main screen + View* view_config_e; // The configuration screen + View* view_save; + View* view_load; // The load view Widget* widget_about; // The about screen - VariableItem* key_name_item; // The name setting item (so we can update the text) char* temp_buffer; // Temporary buffer for text input uint32_t temp_buffer_size; // Size of temporary buffer + DialogsApp* dialogs; + FuriString* file_path; FuriTimer* timer; // Timer for redrawing the screen } KeyCopierApp; @@ -65,25 +76,24 @@ typedef struct { uint32_t format_index; // The index for total number of pins FuriString* key_name_str; // The name setting uint8_t pin_slc; // The pin that is being adjusted - uint8_t total_pin; // The total number of pins we are adjusting uint8_t* depth; // The cutting depth + bool data_loaded; KeyFormat format; -} KeyCopierGameModel; - -void initialize_format(KeyCopierGameModel* model) { - model->format_index = 0; - memcpy(&model->format, &all_formats[model->format_index], sizeof(KeyFormat)); -} +} KeyCopierMeasureModel; -void initialize_model(KeyCopierGameModel* model) { +void initialize_model(KeyCopierMeasureModel* model) { if(model->depth != NULL) { free(model->depth); } - initialize_format(model); + model->format_index = 0; + memcpy(&model->format, &all_formats[model->format_index], sizeof(KeyFormat)); model->depth = (uint8_t*)malloc((model->format.pin_num + 1) * sizeof(uint8_t)); for(uint8_t i = 0; i <= model->format.pin_num; i++) { model->depth[i] = model->format.min_depth_ind; } + model->pin_slc = 1; + model->data_loaded = 0; + model->key_name_str = furi_string_alloc(); } /** @@ -110,18 +120,6 @@ static uint32_t key_copier_navigation_submenu_callback(void* _context) { return KeyCopierViewSubmenu; } -/** - * @brief Callback for returning to configure screen. - * @details This function is called when user press back button. We return VIEW_NONE to - * indicate that we want to navigate to the configure screen. - * @param _context The context - unused - * @return next view id -*/ -static uint32_t key_copier_navigation_configure_callback(void* _context) { - UNUSED(_context); - return KeyCopierViewConfigure; -} - /** * @brief Handle submenu item selection. * @details This function is called when user selects an item from the submenu. @@ -131,11 +129,17 @@ static uint32_t key_copier_navigation_configure_callback(void* _context) { static void key_copier_submenu_callback(void* context, uint32_t index) { KeyCopierApp* app = (KeyCopierApp*)context; switch(index) { + case KeyCopierSubmenuIndexMeasure: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewMeasure); + break; case KeyCopierSubmenuIndexConfigure: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewConfigure); + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewConfigure_e); + break; + case KeyCopierSubmenuIndexSave: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSave); break; - case KeyCopierSubmenuIndexGame: - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewGame); + case KeyCopierSubmenuIndexLoad: + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewLoad); break; case KeyCopierSubmenuIndexAbout: view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewAbout); @@ -145,19 +149,29 @@ static void key_copier_submenu_callback(void* context, uint32_t index) { } } -/** - * Our 1st sample setting is a team color. We have 3 options: red, green, and blue. -*/ -static const char* total_pin_config_label = "Key Format"; -static char* format_names[] = {"Kwikset", "Schlage"}; -static void key_copier_total_pin_change(VariableItem* item) { +char* format_names[COUNT_OF(all_formats)]; +void initialize_format_names(char** format_names) { + // Populate the format_names array + for(size_t i = 0; i < COUNT_OF(all_formats); i++) { + format_names[i] = all_formats[i].format_name; + } +} + +static const char* format_config_label = "Key Format"; +static void key_copier_format_change(VariableItem* item) { KeyCopierApp* app = variable_item_get_context(item); - uint8_t format_index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, format_names[format_index]); - KeyCopierGameModel* model = view_get_model(app->view_game); - model->format_index = format_index; - model->format = all_formats[format_index]; - model->total_pin = model->format.pin_num; + KeyCopierMeasureModel* model = view_get_model(app->view_measure); + if(model->data_loaded) { + variable_item_set_current_value_index(item, model->format_index); + } else { + uint8_t format_index = variable_item_get_current_value_index(item); + model->format_index = format_index; + model->format = all_formats[format_index]; + } + model->data_loaded = false; + variable_item_set_current_value_text(item, model->format.format_name); + + model->format = all_formats[model->format_index]; if(model->depth != NULL) { free(model->depth); } @@ -167,72 +181,53 @@ static void key_copier_total_pin_change(VariableItem* item) { } } -void ensure_dir_exists(Storage* storage) { - // If apps_data directory doesn't exist, create it. - if(!storage_dir_exists(storage, KEY_COPIER_APPS_DATA_FOLDER)) { - FURI_LOG_I(TAG, "Creating directory: %s", KEY_COPIER_APPS_DATA_FOLDER); - storage_simply_mkdir(storage, KEY_COPIER_APPS_DATA_FOLDER); - } else { - FURI_LOG_I(TAG, "Directory exists: %s", KEY_COPIER_APPS_DATA_FOLDER); - } - - // If wiegand directory doesn't exist, create it. - if(!storage_dir_exists(storage, KEY_COPIER_SAVE_FOLDER)) { - FURI_LOG_I(TAG, "Creating directory: %s", KEY_COPIER_SAVE_FOLDER); - storage_simply_mkdir(storage, KEY_COPIER_SAVE_FOLDER); - } else { - FURI_LOG_I(TAG, "Directory exists: %s", KEY_COPIER_SAVE_FOLDER); - } -} - /** * Our 2nd sample setting is a text field. When the user clicks OK on the configuration * setting we use a text input screen to allow the user to enter a name. This function is * called when the user clicks OK on the text input screen. */ -static const char* key_name_config_label = "Save Key"; static const char* key_name_entry_text = "Enter name"; -static const char* key_name_default_value = ""; -static void key_copier_key_name_text_updated(void* context) { +static void key_copier_file_saver(void* context) { KeyCopierApp* app = (KeyCopierApp*)context; - KeyCopierGameModel* model = view_get_model(app->view_game); + KeyCopierMeasureModel* model = view_get_model(app->view_measure); bool redraw = true; with_view_model( - app->view_game, - KeyCopierGameModel * model, - { - furi_string_set(model->key_name_str, app->temp_buffer); - variable_item_set_current_value_text( - app->key_name_item, furi_string_get_cstr(model->key_name_str)); - }, + app->view_measure, + KeyCopierMeasureModel * model, + { furi_string_set(model->key_name_str, app->temp_buffer); }, redraw); - FuriString* buffer = furi_string_alloc(); FuriString* file_path = furi_string_alloc(); furi_string_printf( file_path, "%s/%s%s", - KEY_COPIER_SAVE_FOLDER, + STORAGE_APP_DATA_PATH_PREFIX, furi_string_get_cstr(model->key_name_str), KEY_COPIER_SAVE_EXTENSION); Storage* storage = furi_record_open(RECORD_STORAGE); - ensure_dir_exists(storage); - File* data_file = storage_file_alloc(storage); - if(storage_file_open( - data_file, furi_string_get_cstr(file_path), FSAM_WRITE, FSOM_OPEN_ALWAYS)) { - furi_string_printf(buffer, "Filetype: Flipper Key Copier File\n"); - storage_file_write(data_file, furi_string_get_cstr(buffer), furi_string_size(buffer)); - furi_string_printf(buffer, "Version: 1.0\n"); - storage_file_write(data_file, furi_string_get_cstr(buffer), furi_string_size(buffer)); - furi_string_printf(buffer, "Key Format: %s\n", model->format.format_name); - storage_file_write(data_file, furi_string_get_cstr(buffer), furi_string_size(buffer)); - furi_string_printf(buffer, "Link: %s\n", model->format.format_link); - storage_file_write(data_file, furi_string_get_cstr(buffer), furi_string_size(buffer)); - furi_string_printf(buffer, "Number of Pins: %d\n", model->format.pin_num); - storage_file_write(data_file, furi_string_get_cstr(buffer), furi_string_size(buffer)); - furi_string_printf(buffer, "Maximum Adjacent Cut Specification: %d\n", model->format.macs); - storage_file_write(data_file, furi_string_get_cstr(buffer), furi_string_size(buffer)); - furi_string_printf(buffer, "\nBitting Pattern:\n"); + storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX); + FURI_LOG_D(TAG, "mkdir finished"); + FlipperFormat* flipper_format = flipper_format_file_alloc(storage); + do { + const uint32_t version = 1; + const uint32_t pin_num_buffer = (uint32_t)model->format.pin_num; + const uint32_t macs_buffer = (uint32_t)model->format.macs; + if(!flipper_format_file_open_always(flipper_format, furi_string_get_cstr(file_path))) + break; + if(!flipper_format_write_header_cstr(flipper_format, "Flipper Key Copier File", version)) + break; + if(!flipper_format_write_string_cstr( + flipper_format, "Key Format", model->format.format_name)) + break; + if(!flipper_format_write_string_cstr( + flipper_format, "Key Format Short", model->format.format_short_name)) + break; + if(!flipper_format_write_uint32(flipper_format, "Number of Pins", &pin_num_buffer, 1)) + break; + if(!flipper_format_write_uint32( + flipper_format, "Maximum Adjacent Cut Specification (MACS)", &macs_buffer, 1)) + break; + FuriString* buffer = furi_string_alloc(); for(int i = 0; i < model->format.pin_num; i++) { if(i < model->format.pin_num - 1) { furi_string_cat_printf(buffer, "%d-", model->depth[i]); @@ -240,12 +235,15 @@ static void key_copier_key_name_text_updated(void* context) { furi_string_cat_printf(buffer, "%d", model->depth[i]); } } - furi_string_push_back(buffer, '\n'); - storage_file_write(data_file, furi_string_get_cstr(buffer), furi_string_size(buffer)); + if(!flipper_format_write_string( + flipper_format, "Bitting Pattern", buffer)) + break; + furi_string_free(buffer); + // signal that the file was written successfully + } while(0); + flipper_format_free(flipper_format); - storage_file_close(data_file); - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewConfigure); - } + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewSubmenu); } /** * @brief Callback when item in configuration screen is clicked. @@ -254,45 +252,40 @@ static void key_copier_key_name_text_updated(void* context) { * @param context The context - KeyCopierApp object. * @param index - The index of the item that was clicked. */ -static void key_copier_setting_item_clicked(void* context, uint32_t index) { +static void key_copier_view_save_callback(void* context) { KeyCopierApp* app = (KeyCopierApp*)context; - index++; // The index starts at zero, but we want to start at 1. - - // Our configuration UI has the 2nd item as a text field. - if(index == 2) { - // Header to display on the text input screen. - text_input_set_header_text(app->text_input, key_name_entry_text); - - // Copy the current name into the temporary buffer. - bool redraw = false; - with_view_model( - app->view_game, - KeyCopierGameModel * model, - { - strncpy( - app->temp_buffer, - furi_string_get_cstr(model->key_name_str), - app->temp_buffer_size); - }, - redraw); - - // Configure the text input. When user enters text and clicks OK, key_copier_setting_text_updated be called. - bool clear_previous_text = false; - text_input_set_result_callback( - app->text_input, - key_copier_key_name_text_updated, - app, - app->temp_buffer, - app->temp_buffer_size, - clear_previous_text); - - // Pressing the BACK button will reload the configure screen. - view_set_previous_callback( - text_input_get_view(app->text_input), key_copier_navigation_configure_callback); - - // Show text input dialog. - view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewTextInput); - } + // Header to display on the text input screen. + text_input_set_header_text(app->text_input, key_name_entry_text); + + // Copy the current name into the temporary buffer. + bool redraw = false; + with_view_model( + app->view_measure, + KeyCopierMeasureModel * model, + { + strncpy( + app->temp_buffer, + furi_string_get_cstr(model->key_name_str), + app->temp_buffer_size); + }, + redraw); + + // Configure the text input. When user enters text and clicks OK, key_copier_setting_text_updated be called. + bool clear_previous_text = false; + text_input_set_result_callback( + app->text_input, + key_copier_file_saver, + app, + app->temp_buffer, + app->temp_buffer_size, + clear_previous_text); + + // Pressing the BACK button will reload the configure screen. + view_set_previous_callback( + text_input_get_view(app->text_input), key_copier_navigation_submenu_callback); + + // Show text input dialog. + view_dispatcher_switch_to_view(app->view_dispatcher, KeyCopierViewTextInput); } static inline int min(int a, int b) { @@ -311,8 +304,8 @@ static double inches_per_px = (double)INCHES_PER_PX; * @param canvas The canvas to draw on. * @param model The model - MyModel object. */ -static void key_copier_view_game_draw_callback(Canvas* canvas, void* model) { - KeyCopierGameModel* my_model = (KeyCopierGameModel*)model; +static void key_copier_view_measure_draw_callback(Canvas* canvas, void* model) { + KeyCopierMeasureModel* my_model = (KeyCopierMeasureModel*)model; KeyFormat my_format = my_model->format; int pin_half_width_px = (int)round((my_format.pin_width_inch / inches_per_px) / 2); @@ -323,7 +316,7 @@ static void key_copier_view_game_draw_callback(Canvas* canvas, void* model) { int post_extra_x_px = 0; int pre_extra_x_px = 0; - for(int current_pin = 1; current_pin <= my_model->total_pin; current_pin += 1) { + for(int current_pin = 1; current_pin <= my_model->format.pin_num; current_pin += 1) { double current_center_px = my_format.first_pin_inch + (current_pin - 1) * my_format.pin_increment_inch; int pin_center_px = (int)round(current_center_px / inches_per_px); @@ -351,7 +344,7 @@ static void key_copier_view_game_draw_callback(Canvas* canvas, void* model) { last_depth = 0; pre_extra_x_px = max(current_depth_px + pin_half_width_px, 0); } - if(current_pin == my_model->total_pin) { + if(current_pin == my_model->format.pin_num) { next_depth = 0; } if((last_depth + current_depth) > my_format.clearance && @@ -417,8 +410,6 @@ static void key_copier_view_game_draw_callback(Canvas* canvas, void* model) { int level_contour_px = (int)round((my_format.last_pin_inch + my_format.pin_increment_inch) / inches_per_px - 4); canvas_draw_line(canvas, 0, 62, level_contour_px, 62); - int step_px = (int)round(my_format.pin_increment_inch / inches_per_px); - canvas_draw_line(canvas, level_contour_px, 62, level_contour_px + step_px, 62 - step_px); int slc_pin_px = (int)round( (my_format.first_pin_inch + (my_model->pin_slc - 1) * my_format.pin_increment_inch) / @@ -426,12 +417,12 @@ static void key_copier_view_game_draw_callback(Canvas* canvas, void* model) { canvas_draw_str(canvas, slc_pin_px - 2, 23, "*"); FuriString* xstr = furi_string_alloc(); - int buffer_size = my_model->total_pin + 1; + int buffer_size = my_model->format.pin_num + 1; char depth_str[buffer_size]; depth_str[0] = '\0'; // Initialize the string // Manual string concatenation char* pos = depth_str; - for(int i = 0; i < my_model->total_pin; i++) { + for(int i = 0; i < my_model->format.pin_num; i++) { int written = snprintf(pos, buffer_size - (pos - depth_str), "%u", my_model->depth[i]); if(written < 0 || written >= buffer_size - (pos - depth_str)) { // Handle error @@ -455,7 +446,7 @@ static void key_copier_view_game_draw_callback(Canvas* canvas, void* model) { * @details This function is called when the timer is elapsed. We use this to queue a redraw event. * @param context The context - KeyCopierApp object. */ -static void key_copier_view_game_timer_callback(void* context) { +static void key_copier_view_measure_timer_callback(void* context) { KeyCopierApp* app = (KeyCopierApp*)context; view_dispatcher_send_custom_event(app->view_dispatcher, KeyCopierEventIdRedrawScreen); } @@ -466,12 +457,12 @@ static void key_copier_view_game_timer_callback(void* context) { * redraw the screen periodically (so the random number is refreshed). * @param context The context - KeyCopierApp object. */ -static void key_copier_view_game_enter_callback(void* context) { +static void key_copier_view_measure_enter_callback(void* context) { uint32_t period = furi_ms_to_ticks(500); KeyCopierApp* app = (KeyCopierApp*)context; furi_assert(app->timer == NULL); app->timer = - furi_timer_alloc(key_copier_view_game_timer_callback, FuriTimerTypePeriodic, context); + furi_timer_alloc(key_copier_view_measure_timer_callback, FuriTimerTypePeriodic, context); furi_timer_start(app->timer, period); } @@ -480,7 +471,7 @@ static void key_copier_view_game_enter_callback(void* context) { * @details This function is called when the user exits the game screen. We stop the timer. * @param context The context - KeyCopierApp object. */ -static void key_copier_view_game_exit_callback(void* context) { +static void key_copier_view_measure_exit_callback(void* context) { KeyCopierApp* app = (KeyCopierApp*)context; furi_timer_stop(app->timer); furi_timer_free(app->timer); @@ -493,7 +484,7 @@ static void key_copier_view_game_exit_callback(void* context) { * @param event The event id - KeyCopierEventId value. * @param context The context - KeyCopierApp object. */ -static bool key_copier_view_game_custom_event_callback(uint32_t event, void* context) { +static bool key_copier_view_measure_custom_event_callback(uint32_t event, void* context) { KeyCopierApp* app = (KeyCopierApp*)context; switch(event) { case KeyCopierEventIdRedrawScreen: @@ -501,7 +492,7 @@ static bool key_copier_view_game_custom_event_callback(uint32_t event, void* con { bool redraw = true; with_view_model( - app->view_game, KeyCopierGameModel * _model, { UNUSED(_model); }, redraw); + app->view_measure, KeyCopierMeasureModel * _model, { UNUSED(_model); }, redraw); return true; } case KeyCopierEventIdOkPressed: @@ -520,7 +511,7 @@ static bool key_copier_view_game_custom_event_callback(uint32_t event, void* con * @param context The context - KeyCopierApp object. * @return true if the event was handled, false otherwise. */ -static bool key_copier_view_game_input_callback(InputEvent* event, void* context) { +static bool key_copier_view_measure_input_callback(InputEvent* event, void* context) { KeyCopierApp* app = (KeyCopierApp*)context; if(event->type == InputTypeShort) { switch(event->key) { @@ -528,8 +519,8 @@ static bool key_copier_view_game_input_callback(InputEvent* event, void* context // Left button clicked, reduce x coordinate. bool redraw = true; with_view_model( - app->view_game, - KeyCopierGameModel * model, + app->view_measure, + KeyCopierMeasureModel * model, { if(model->pin_slc > 1) { model->pin_slc--; @@ -542,8 +533,8 @@ static bool key_copier_view_game_input_callback(InputEvent* event, void* context // Left button clicked, reduce x coordinate. bool redraw = true; with_view_model( - app->view_game, - KeyCopierGameModel * model, + app->view_measure, + KeyCopierMeasureModel * model, { if(model->pin_slc < model->format.pin_num) { model->pin_slc++; @@ -556,8 +547,8 @@ static bool key_copier_view_game_input_callback(InputEvent* event, void* context // Left button clicked, reduce x coordinate. bool redraw = true; with_view_model( - app->view_game, - KeyCopierGameModel * model, + app->view_measure, + KeyCopierMeasureModel * model, { if(model->depth[model->pin_slc - 1] > model->format.min_depth_ind) { if(model->pin_slc == 1) { //first pin only limited by the next one @@ -590,8 +581,8 @@ static bool key_copier_view_game_input_callback(InputEvent* event, void* context // Right button clicked, increase x coordinate. bool redraw = true; with_view_model( - app->view_game, - KeyCopierGameModel * model, + app->view_measure, + KeyCopierMeasureModel * model, { if(model->depth[model->pin_slc - 1] < model->format.max_depth_ind) { if(model->pin_slc == 1) { //first pin only limited by the next one @@ -652,9 +643,13 @@ static KeyCopierApp* key_copier_app_alloc() { app->submenu = submenu_alloc(); submenu_add_item( - app->submenu, "Measure", KeyCopierSubmenuIndexGame, key_copier_submenu_callback, app); + app->submenu, "Measure", KeyCopierSubmenuIndexMeasure, key_copier_submenu_callback, app); submenu_add_item( app->submenu, "Config", KeyCopierSubmenuIndexConfigure, key_copier_submenu_callback, app); + submenu_add_item( + app->submenu, "Save", KeyCopierSubmenuIndexSave, key_copier_submenu_callback, app); + submenu_add_item( + app->submenu, "Load", KeyCopierSubmenuIndexLoad, key_copier_submenu_callback, app); submenu_add_item( app->submenu, "About", KeyCopierSubmenuIndexAbout, key_copier_submenu_callback, app); view_set_previous_callback( @@ -668,51 +663,52 @@ static KeyCopierApp* key_copier_app_alloc() { app->view_dispatcher, KeyCopierViewTextInput, text_input_get_view(app->text_input)); app->temp_buffer_size = 32; app->temp_buffer = (char*)malloc(app->temp_buffer_size); + app->temp_buffer = ""; + + app->view_measure = view_alloc(); + view_set_draw_callback(app->view_measure, key_copier_view_measure_draw_callback); + view_set_input_callback(app->view_measure, key_copier_view_measure_input_callback); + view_set_previous_callback(app->view_measure, key_copier_navigation_submenu_callback); + view_set_enter_callback(app->view_measure, key_copier_view_measure_enter_callback); + view_set_exit_callback(app->view_measure, key_copier_view_measure_exit_callback); + view_set_context(app->view_measure, app); + view_set_custom_callback(app->view_measure, key_copier_view_measure_custom_event_callback); + view_allocate_model(app->view_measure, ViewModelTypeLockFree, sizeof(KeyCopierMeasureModel)); + KeyCopierMeasureModel* model = view_get_model(app->view_measure); + + initialize_model(model); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewMeasure, app->view_measure); app->variable_item_list_config = variable_item_list_alloc(); variable_item_list_reset(app->variable_item_list_config); VariableItem* item = variable_item_list_add( app->variable_item_list_config, - total_pin_config_label, + format_config_label, COUNT_OF(format_names), - key_copier_total_pin_change, + key_copier_format_change, app); - FuriString* key_name_str = furi_string_alloc(); - furi_string_set_str(key_name_str, key_name_default_value); - app->key_name_item = variable_item_list_add( - app->variable_item_list_config, key_name_config_label, 1, NULL, NULL); - variable_item_set_current_value_text(app->key_name_item, furi_string_get_cstr(key_name_str)); - variable_item_list_set_enter_callback( - app->variable_item_list_config, key_copier_setting_item_clicked, app); - view_set_previous_callback( variable_item_list_get_view(app->variable_item_list_config), key_copier_navigation_submenu_callback); view_dispatcher_add_view( app->view_dispatcher, - KeyCopierViewConfigure, + KeyCopierViewConfigure_e, variable_item_list_get_view(app->variable_item_list_config)); - - app->view_game = view_alloc(); - view_set_draw_callback(app->view_game, key_copier_view_game_draw_callback); - view_set_input_callback(app->view_game, key_copier_view_game_input_callback); - view_set_previous_callback(app->view_game, key_copier_navigation_submenu_callback); - view_set_enter_callback(app->view_game, key_copier_view_game_enter_callback); - view_set_exit_callback(app->view_game, key_copier_view_game_exit_callback); - view_set_context(app->view_game, app); - view_set_custom_callback(app->view_game, key_copier_view_game_custom_event_callback); - view_allocate_model(app->view_game, ViewModelTypeLockFree, sizeof(KeyCopierGameModel)); - KeyCopierGameModel* model = view_get_model(app->view_game); - - initialize_model(model); - model->key_name_str = key_name_str; - model->pin_slc = 1; - model->total_pin = model->format.pin_num; variable_item_set_current_value_index(item, model->format_index); - variable_item_set_current_value_text(item, format_names[model->format_index]); + variable_item_set_current_value_text(item, model->format.format_name); + + app->view_save = view_alloc(); + view_set_context(app->view_save, app); + view_set_enter_callback(app->view_save, key_copier_view_save_callback); + view_set_previous_callback(app->view_save, key_copier_navigation_submenu_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewSave, app->view_save); - view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewGame, app->view_game); + app->view_load = view_alloc(); + view_set_context(app->view_load, app); + view_set_enter_callback(app->view_load, key_copier_view_save_callback); + view_set_previous_callback(app->view_load, key_copier_navigation_submenu_callback); + view_dispatcher_add_view(app->view_dispatcher, KeyCopierViewLoad, app->view_load); app->widget_about = widget_alloc(); widget_add_text_scroll_element( @@ -721,7 +717,7 @@ static KeyCopierApp* key_copier_app_alloc() { 0, 128, 64, - "Key Maker App 0.3\n\nTo measure your key:\n\n1. Place it on top of the screen.\n\n2. Use the horizontal lines to align your key.\n\n3. Adjust each pin's bitting depth until they match.\n\n4. Save the bitting pattern and key format by pressing the OK button or in the Config menu.\n\nGithub: github.com/zinongli/KeyCopier \n\nSpecial thanks to Derek Jamison's Skeleton App Template."); + "Key Maker App 0.3\n\nTo measure your key:\n\n1. Place it on top of the screen.\n\n2. Use the horizontal lines to align your key.\n\n3. Adjust each pin's bitting depth until they match. It's easier if you close one eye.\n\n4. Save the bitting pattern and key format by pressing the OK button or in the Config menu.\n\nGithub: github.com/zinongli/KeyCopier \n\nSpecial thanks to Derek Jamison's Skeleton App Template."); view_set_previous_callback( widget_get_view(app->widget_about), key_copier_navigation_submenu_callback); view_dispatcher_add_view( @@ -752,18 +748,20 @@ static void key_copier_app_free(KeyCopierApp* app) { free(app->temp_buffer); view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewAbout); widget_free(app->widget_about); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewGame); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewMeasure); with_view_model( - app->view_game, - KeyCopierGameModel * model, + app->view_measure, + KeyCopierMeasureModel * model, { if(model->depth != NULL) { free(model->depth); } }, false); - view_free(app->view_game); - view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure); + view_free(app->view_measure); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewConfigure_e); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSave); + view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewLoad); variable_item_list_free(app->variable_item_list_config); view_dispatcher_remove_view(app->view_dispatcher, KeyCopierViewSubmenu); submenu_free(app->submenu); diff --git a/key_formats.h b/key_formats.h index 066d428..6a2d3f2 100644 --- a/key_formats.h +++ b/key_formats.h @@ -1,6 +1,8 @@ #ifndef KEY_FORMATS_H #define KEY_FORMATS_H +#define FORMAT_NUM 2 + typedef struct { char* format_name; char* format_short_name; @@ -23,6 +25,6 @@ typedef struct { int clearance; } KeyFormat; -extern const KeyFormat all_formats[]; +extern const KeyFormat all_formats[FORMAT_NUM]; #endif // KEY_FORMATS_H