From 0fda004e0f59f1051f9ad4e8f57e38af08dd2ecd Mon Sep 17 00:00:00 2001 From: Mykhailo Shevchuk Date: Thu, 23 Jul 2026 19:27:34 +0300 Subject: [PATCH 1/2] Barcode Gen: create barcodes folder on startup, descriptive save errors Fixes #234 - Call init_folder() in barcode_main() instead of free_app(), so /ext/apps_data/barcodes exists before the first save attempt instead of being created only on app exit. Also ensure the folder exists in save_barcode() as a safety net. - Show a message for empty Name/Data/Type instead of silently returning. - Detect the "file already exists" case in New mode (open_new fails on existing files) and report it instead of the generic error. - Add next_view to the message view so save errors return to the create view (keeping the entered data) instead of the main menu. - Support multiline messages in the message view. Co-Authored-By: Claude Opus 4.8 (1M context) --- base_pack/barcode_gen/barcode_app.c | 7 ++- base_pack/barcode_gen/views/create_view.c | 72 +++++++++++++--------- base_pack/barcode_gen/views/message_view.c | 24 +++++--- base_pack/barcode_gen/views/message_view.h | 2 + 4 files changed, 65 insertions(+), 40 deletions(-) diff --git a/base_pack/barcode_gen/barcode_app.c b/base_pack/barcode_gen/barcode_app.c index 16c27046..01c2e88b 100644 --- a/base_pack/barcode_gen/barcode_app.c +++ b/base_pack/barcode_gen/barcode_app.c @@ -183,7 +183,10 @@ void edit_barcode_item(BarcodeApp* app) { with_view_model( app->message_view->view, MessageViewModel * model, - { model->message = get_error_code_message(reason); }, + { + model->message = get_error_code_message(reason); + model->next_view = MainMenuView; + }, true); view_dispatcher_switch_to_view( @@ -275,7 +278,6 @@ uint32_t exit_callback(void* context) { void free_app(BarcodeApp* app) { FURI_LOG_I(TAG, "Freeing Data"); - init_folder(); free_types(); view_dispatcher_remove_view(app->view_dispatcher, TextInputView); @@ -320,6 +322,7 @@ int32_t barcode_main(void* p) { UNUSED(p); BarcodeApp* app = malloc(sizeof(BarcodeApp)); init_types(); + init_folder(); app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); // Register view port in GUI diff --git a/base_pack/barcode_gen/views/create_view.c b/base_pack/barcode_gen/views/create_view.c index d359a3d7..535716f2 100644 --- a/base_pack/barcode_gen/views/create_view.c +++ b/base_pack/barcode_gen/views/create_view.c @@ -323,6 +323,25 @@ void create_view_free_model(CreateView* create_view_object) { true); } +/** + * Shows a message in the message view + * @param message the message to display + * @param next_view the view to switch to when the message is dismissed +*/ +static void show_message(CreateView* create_view_object, const char* message, uint32_t next_view) { + with_view_model( + create_view_object->barcode_app->message_view->view, + MessageViewModel * model, + { + model->message = message; + model->next_view = next_view; + }, + true); + + view_dispatcher_switch_to_view( + create_view_object->barcode_app->view_dispatcher, MessageErrorView); +} + void remove_barcode(CreateView* create_view_object) { Storage* storage = furi_record_open(RECORD_STORAGE); @@ -353,20 +372,8 @@ void remove_barcode(CreateView* create_view_object) { true); furi_record_close(RECORD_STORAGE); - with_view_model( - create_view_object->barcode_app->message_view->view, - MessageViewModel * model, - { - if(success) { - model->message = "File Deleted"; - } else { - model->message = "Could not delete file"; - } - }, - true); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, MessageErrorView); + show_message( + create_view_object, success ? "File Deleted" : "Could not delete file", MainMenuView); } void save_barcode(CreateView* create_view_object) { @@ -390,18 +397,22 @@ void save_barcode(CreateView* create_view_object) { if(file_name == NULL || furi_string_empty(file_name)) { FURI_LOG_E(TAG, "File Name cannot be empty"); + show_message(create_view_object, "File name\ncannot be empty", CreateBarcodeView); return; } if(barcode_data == NULL || furi_string_empty(barcode_data)) { FURI_LOG_E(TAG, "Barcode Data cannot be empty"); + show_message(create_view_object, "Barcode data\ncannot be empty", CreateBarcodeView); return; } if(barcode_type == NULL) { FURI_LOG_E(TAG, "Type not defined"); + show_message(create_view_object, "Barcode type\nis not selected", CreateBarcodeView); return; } bool success = false; + const char* error_message = "A saving error\nhas occurred"; FuriString* full_file_path = furi_string_alloc_set(DEFAULT_USER_BARCODES); furi_string_push_back(full_file_path, '/'); @@ -410,6 +421,9 @@ void save_barcode(CreateView* create_view_object) { Storage* storage = furi_record_open(RECORD_STORAGE); + //ensure the barcodes folder exists before saving + storage_simply_mkdir(storage, DEFAULT_USER_BARCODES); + if(mode == EditMode) { if(!furi_string_empty(file_path)) { if(!furi_string_equal(file_path, full_file_path)) { @@ -432,8 +446,14 @@ void save_barcode(CreateView* create_view_object) { bool file_opened_status = false; if(mode == NewMode) { - file_opened_status = - flipper_format_file_open_new(ff, furi_string_get_cstr(full_file_path)); + //open_new fails on existing files, check first to give a clear error message + if(storage_file_exists(storage, furi_string_get_cstr(full_file_path))) { + FURI_LOG_E(TAG, "File \"%s\" already exists", furi_string_get_cstr(full_file_path)); + error_message = "A file with this\nname already exists"; + } else { + file_opened_status = + flipper_format_file_open_new(ff, furi_string_get_cstr(full_file_path)); + } } else if(mode == EditMode) { file_opened_status = flipper_format_file_open_always(ff, furi_string_get_cstr(full_file_path)); @@ -466,20 +486,12 @@ void save_barcode(CreateView* create_view_object) { flipper_format_free(ff); furi_record_close(RECORD_STORAGE); - with_view_model( - create_view_object->barcode_app->message_view->view, - MessageViewModel * model, - { - if(success) { - model->message = "File Saved!"; - } else { - model->message = "A saving error has occurred"; - } - }, - true); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, MessageErrorView); + if(success) { + show_message(create_view_object, "File Saved!", MainMenuView); + } else { + //go back to the create view so the entered data is not lost + show_message(create_view_object, error_message, CreateBarcodeView); + } } void create_view_free(CreateView* create_view_object) { diff --git a/base_pack/barcode_gen/views/message_view.c b/base_pack/barcode_gen/views/message_view.c index d68d0c0c..dc3b9525 100644 --- a/base_pack/barcode_gen/views/message_view.c +++ b/base_pack/barcode_gen/views/message_view.c @@ -8,7 +8,7 @@ static void app_draw_callback(Canvas* canvas, void* ctx) { canvas_clear(canvas); if(message_view_model->message != NULL) { - canvas_draw_str_aligned( + elements_multiline_text_aligned( canvas, 62, 30, AlignCenter, AlignCenter, message_view_model->message); } @@ -23,15 +23,23 @@ static bool app_input_callback(InputEvent* input_event, void* ctx) { MessageView* message_view_object = ctx; + bool dismissed = false; if(input_event->key == InputKeyBack) { - view_dispatcher_switch_to_view( - message_view_object->barcode_app->view_dispatcher, MainMenuView); + dismissed = true; + } + if(input_event->type == InputTypeShort && input_event->key == InputKeyOk) { + dismissed = true; } - if(input_event->type == InputTypeShort) { - if(input_event->key == InputKeyOk) { - view_dispatcher_switch_to_view( - message_view_object->barcode_app->view_dispatcher, MainMenuView); - } + + if(dismissed) { + uint32_t next_view = MainMenuView; + with_view_model( + message_view_object->view, + MessageViewModel * model, + { next_view = model->next_view; }, + false); + view_dispatcher_switch_to_view( + message_view_object->barcode_app->view_dispatcher, next_view); } return true; diff --git a/base_pack/barcode_gen/views/message_view.h b/base_pack/barcode_gen/views/message_view.h index 33acc3d0..c3a99475 100644 --- a/base_pack/barcode_gen/views/message_view.h +++ b/base_pack/barcode_gen/views/message_view.h @@ -11,6 +11,8 @@ typedef struct { typedef struct { const char* message; + //the view to switch to when the message is dismissed + uint32_t next_view; } MessageViewModel; MessageView* message_view_allocate(BarcodeApp* barcode_app); From e34fb87a0422fe23f5cb076cb5f4063e14ba5c15 Mon Sep 17 00:00:00 2001 From: Mykhailo Shevchuk Date: Thu, 23 Jul 2026 19:47:27 +0300 Subject: [PATCH 2/2] Barcode Gen: harden save flow after review, add changelog, bump to 1.5 Review follow-ups on top of the #234 fixes: - Fail the save with a specific message when an edit-mode rename would overwrite another barcode or the rename itself fails; sync the model path after a successful rename so a later failure leaves no stale path. - Check all flipper_format write results; a partially written file is no longer reported as "File Saved!". - Report a mkdir failure as "Cannot access the SD card" and log real init_folder failures as errors instead of "already exists". - Unify the New/Edit duplicate-name checks into one mode-independent clobber guard; collapse the three status flags into one error_message sentinel; only allocate the FlipperFormat when the save can proceed. - Move the show-message helper into the message view (message_view_show) and reuse it from edit_barcode_item; reuse init_folder in save_barcode. - Give next_view a safe default, dismiss only on short presses, and keep delete/save failures in the edit view so entered data survives. - Add CHANGELOG.md backfilled from repo and upstream release history; bump fap_version to 1.5. Co-Authored-By: Claude Opus 4.8 (1M context) --- base_pack/barcode_gen/CHANGELOG.md | 30 ++++ base_pack/barcode_gen/application.fam | 2 +- base_pack/barcode_gen/barcode_app.c | 29 ++-- base_pack/barcode_gen/barcode_app.h | 2 + base_pack/barcode_gen/views/create_view.c | 161 ++++++++++----------- base_pack/barcode_gen/views/message_view.c | 34 ++++- base_pack/barcode_gen/views/message_view.h | 10 +- 7 files changed, 156 insertions(+), 112 deletions(-) create mode 100644 base_pack/barcode_gen/CHANGELOG.md diff --git a/base_pack/barcode_gen/CHANGELOG.md b/base_pack/barcode_gen/CHANGELOG.md new file mode 100644 index 00000000..fcc65a4f --- /dev/null +++ b/base_pack/barcode_gen/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +## 1.5 + +- Fix the first save after a fresh install always failing with "A saving error has occurred": the barcodes folder was only created when the app exited; it is now created on startup and rechecked before every save +- Show the actual save error instead of a generic message: empty name or data, a file with this name already exists, SD card not accessible, rename failure +- Fix renaming a barcode to the name of another saved barcode silently overwriting it - it is now rejected with a clear message +- Fix "File Saved!" being reported when the file could not be fully written (e.g. SD card removed mid-save) +- Save and delete failures now return to the edit form with the entered data intact instead of dropping to the main menu + +## 1.4 + +- Add a custom keyboard (by thevan4): symbols can be entered for barcode data, while characters not allowed in file names stay hidden when naming a file +- Update for a newer firmware API (no functional changes) + +## 1.3 + +- Keep the display backlight on while a barcode is shown +- Version bump for catalog compatibility + +## 1.2 + +- Add an "Error Codes Info" screen to the main menu explaining every error the app can show +- Add an About screen +- Fix CODE-128 barcodes containing `#` producing an "Invalid Characters" error +- Fix the CODE-128 check digit encoding lookup for check digit values below 100 + +## 1.1 + +- Initial release in this pack: create, edit and display UPC-A, EAN-8, EAN-13, CODE-39, Codabar, CODE-128 (Set B) and CODE-128C barcodes; saved barcodes are stored in `/apps_data/barcodes` diff --git a/base_pack/barcode_gen/application.fam b/base_pack/barcode_gen/application.fam index 5608ba5a..8b00b152 100644 --- a/base_pack/barcode_gen/application.fam +++ b/base_pack/barcode_gen/application.fam @@ -11,6 +11,6 @@ App( fap_file_assets="barcode_encoding_files", fap_author="@Kingal1337", fap_weburl="https://github.com/Kingal1337/flipper-barcode-generator", - fap_version="1.4", + fap_version="1.5", fap_description="App allows you to display various barcodes on flipper screen", ) diff --git a/base_pack/barcode_gen/barcode_app.c b/base_pack/barcode_gen/barcode_app.c index 01c2e88b..7f8b5c00 100644 --- a/base_pack/barcode_gen/barcode_app.c +++ b/base_pack/barcode_gen/barcode_app.c @@ -95,17 +95,19 @@ bool get_file_name_from_path(FuriString* file_path, FuriString* file_name, bool } /** - * Creates the barcode folder + * Creates the barcode folder if it does not exist + * @returns true if the folder exists or was created */ -void init_folder() { +bool init_folder() { Storage* storage = furi_record_open(RECORD_STORAGE); - FURI_LOG_I(TAG, "Creating barcodes folder"); - if(storage_simply_mkdir(storage, DEFAULT_USER_BARCODES)) { - FURI_LOG_I(TAG, "Barcodes folder successfully created!"); - } else { - FURI_LOG_I(TAG, "Barcodes folder already exists."); + //simply_mkdir also returns true when the folder already exists, + //false is a real failure, e.g. a missing SD card + bool folder_ready = storage_simply_mkdir(storage, DEFAULT_USER_BARCODES); + if(!folder_ready) { + FURI_LOG_E(TAG, "Could not create the barcodes folder"); } furi_record_close(RECORD_STORAGE); + return folder_ready; } void select_barcode_item(BarcodeApp* app) { @@ -180,18 +182,7 @@ void edit_barcode_item(BarcodeApp* app) { reason = read_raw_data(file_path, raw_type, raw_data); if(reason != OKCode) { FURI_LOG_E(TAG, "Could not read data correctly"); - with_view_model( - app->message_view->view, - MessageViewModel * model, - { - model->message = get_error_code_message(reason); - model->next_view = MainMenuView; - }, - true); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, MessageErrorView); - + message_view_show(app->message_view, get_error_code_message(reason), MainMenuView); } else { BarcodeTypeObj* type_obj = get_type(raw_type); if(type_obj->type == UNKNOWN) { diff --git a/base_pack/barcode_gen/barcode_app.h b/base_pack/barcode_gen/barcode_app.h index d5e7d6b2..a18e2a46 100644 --- a/base_pack/barcode_gen/barcode_app.h +++ b/base_pack/barcode_gen/barcode_app.h @@ -85,6 +85,8 @@ enum Views { void submenu_callback(void* context, uint32_t index); +bool init_folder(); + uint32_t main_menu_callback(void* context); uint32_t exit_callback(void* context); diff --git a/base_pack/barcode_gen/views/create_view.c b/base_pack/barcode_gen/views/create_view.c index 535716f2..c4e130ba 100644 --- a/base_pack/barcode_gen/views/create_view.c +++ b/base_pack/barcode_gen/views/create_view.c @@ -323,25 +323,6 @@ void create_view_free_model(CreateView* create_view_object) { true); } -/** - * Shows a message in the message view - * @param message the message to display - * @param next_view the view to switch to when the message is dismissed -*/ -static void show_message(CreateView* create_view_object, const char* message, uint32_t next_view) { - with_view_model( - create_view_object->barcode_app->message_view->view, - MessageViewModel * model, - { - model->message = message; - model->next_view = next_view; - }, - true); - - view_dispatcher_switch_to_view( - create_view_object->barcode_app->view_dispatcher, MessageErrorView); -} - void remove_barcode(CreateView* create_view_object) { Storage* storage = furi_record_open(RECORD_STORAGE); @@ -372,8 +353,13 @@ void remove_barcode(CreateView* create_view_object) { true); furi_record_close(RECORD_STORAGE); - show_message( - create_view_object, success ? "File Deleted" : "Could not delete file", MainMenuView); + MessageView* message_view = create_view_object->barcode_app->message_view; + if(success) { + message_view_show(message_view, "File Deleted", MainMenuView); + } else { + //stay in the edit view so the user can retry + message_view_show(message_view, "Could not delete file", CreateBarcodeView); + } } void save_barcode(CreateView* create_view_object) { @@ -395,24 +381,26 @@ void save_barcode(CreateView* create_view_object) { }, true); + MessageView* message_view = create_view_object->barcode_app->message_view; + if(file_name == NULL || furi_string_empty(file_name)) { FURI_LOG_E(TAG, "File Name cannot be empty"); - show_message(create_view_object, "File name\ncannot be empty", CreateBarcodeView); + message_view_show(message_view, "File name\ncannot be empty", CreateBarcodeView); return; } if(barcode_data == NULL || furi_string_empty(barcode_data)) { FURI_LOG_E(TAG, "Barcode Data cannot be empty"); - show_message(create_view_object, "Barcode data\ncannot be empty", CreateBarcodeView); + message_view_show(message_view, "Barcode data\ncannot be empty", CreateBarcodeView); return; } if(barcode_type == NULL) { FURI_LOG_E(TAG, "Type not defined"); - show_message(create_view_object, "Barcode type\nis not selected", CreateBarcodeView); + message_view_show(message_view, "Barcode type\nis not selected", CreateBarcodeView); return; } - bool success = false; - const char* error_message = "A saving error\nhas occurred"; + //NULL while the save is still going fine + const char* error_message = NULL; FuriString* full_file_path = furi_string_alloc_set(DEFAULT_USER_BARCODES); furi_string_push_back(full_file_path, '/'); @@ -421,76 +409,83 @@ void save_barcode(CreateView* create_view_object) { Storage* storage = furi_record_open(RECORD_STORAGE); - //ensure the barcodes folder exists before saving - storage_simply_mkdir(storage, DEFAULT_USER_BARCODES); - - if(mode == EditMode) { - if(!furi_string_empty(file_path)) { - if(!furi_string_equal(file_path, full_file_path)) { - FS_Error error = storage_common_rename( - storage, - furi_string_get_cstr(file_path), - furi_string_get_cstr(full_file_path)); - if(error != FSE_OK) { - FURI_LOG_E(TAG, "Rename error: %s", storage_error_get_desc(error)); - } else { - FURI_LOG_I(TAG, "Rename Success"); - } - } - } + //ensure the barcodes folder exists before saving, + //it could have been removed while the app was running + if(!init_folder()) { + error_message = "Cannot access\nthe SD card"; } - FlipperFormat* ff = flipper_format_file_alloc(storage); - - FURI_LOG_I(TAG, "Saving Barcode to: %s", furi_string_get_cstr(full_file_path)); + //overwriting the barcode's own file in edit mode is fine, but saving + //over any other existing file would destroy it, fail with a clear message instead + bool same_file = file_path != NULL && furi_string_equal(file_path, full_file_path); + if(error_message == NULL && !same_file && + storage_file_exists(storage, furi_string_get_cstr(full_file_path))) { + FURI_LOG_E(TAG, "File \"%s\" already exists", furi_string_get_cstr(full_file_path)); + error_message = "A file with this\nname already exists"; + } - bool file_opened_status = false; - if(mode == NewMode) { - //open_new fails on existing files, check first to give a clear error message - if(storage_file_exists(storage, furi_string_get_cstr(full_file_path))) { - FURI_LOG_E(TAG, "File \"%s\" already exists", furi_string_get_cstr(full_file_path)); - error_message = "A file with this\nname already exists"; + //in edit mode a changed name moves the old file before saving + if(error_message == NULL && mode == EditMode && !same_file && !furi_string_empty(file_path)) { + FS_Error error = storage_common_rename( + storage, furi_string_get_cstr(file_path), furi_string_get_cstr(full_file_path)); + if(error != FSE_OK) { + FURI_LOG_E(TAG, "Rename error: %s", storage_error_get_desc(error)); + error_message = "Could not rename\nthe barcode file"; } else { - file_opened_status = - flipper_format_file_open_new(ff, furi_string_get_cstr(full_file_path)); + FURI_LOG_I(TAG, "Rename Success"); + //keep the model path in sync so a failed save below + //does not leave it pointing at the old, now removed file + furi_string_set(file_path, full_file_path); } - } else if(mode == EditMode) { - file_opened_status = - flipper_format_file_open_always(ff, furi_string_get_cstr(full_file_path)); } - if(file_opened_status) { - // Filetype: Barcode - // Version: 1 - - // # Types - UPC-A, EAN-8, EAN-13, CODE-39 - // Type: CODE-39 - // Data: AB - flipper_format_write_string_cstr(ff, "Filetype", "Barcode"); - - flipper_format_write_string_cstr(ff, "Version", FILE_VERSION); - - flipper_format_write_comment_cstr( - ff, "Types - UPC-A, EAN-8, EAN-13, CODE-39, CODE-128, Codabar"); - - flipper_format_write_string_cstr(ff, "Type", barcode_type->name); - - flipper_format_write_string_cstr(ff, "Data", furi_string_get_cstr(barcode_data)); - - success = true; - } else { - FURI_LOG_E(TAG, "Save error"); - success = false; + FlipperFormat* ff = NULL; + if(error_message == NULL) { + FURI_LOG_I(TAG, "Saving Barcode to: %s", furi_string_get_cstr(full_file_path)); + ff = flipper_format_file_alloc(storage); + + //open_new fails on existing files as a backstop to the check above + bool file_saved = + mode == NewMode ? + flipper_format_file_open_new(ff, furi_string_get_cstr(full_file_path)) : + flipper_format_file_open_always(ff, furi_string_get_cstr(full_file_path)); + if(file_saved) { + // Filetype: Barcode + // Version: 1 + + // # Types - UPC-A, EAN-8, EAN-13, CODE-39, CODE-128, Codabar + // Type: CODE-39 + // Data: AB + file_saved = + flipper_format_write_string_cstr(ff, "Filetype", "Barcode") && + flipper_format_write_string_cstr(ff, "Version", FILE_VERSION) && + flipper_format_write_comment_cstr( + ff, "Types - UPC-A, EAN-8, EAN-13, CODE-39, CODE-128, Codabar") && + flipper_format_write_string_cstr(ff, "Type", barcode_type->name) && + flipper_format_write_string_cstr(ff, "Data", furi_string_get_cstr(barcode_data)); + if(!file_saved) { + //the file may be partially written, e.g. if the SD card was removed mid-save + FURI_LOG_E(TAG, "Could not write the barcode file"); + } + } else { + FURI_LOG_E(TAG, "Could not open file %s", furi_string_get_cstr(full_file_path)); + } + if(!file_saved) { + error_message = "A saving error\nhas occurred"; + } } + furi_string_free(full_file_path); - flipper_format_free(ff); + if(ff != NULL) { + flipper_format_free(ff); + } furi_record_close(RECORD_STORAGE); - if(success) { - show_message(create_view_object, "File Saved!", MainMenuView); + if(error_message == NULL) { + message_view_show(message_view, "File Saved!", MainMenuView); } else { //go back to the create view so the entered data is not lost - show_message(create_view_object, error_message, CreateBarcodeView); + message_view_show(message_view, error_message, CreateBarcodeView); } } diff --git a/base_pack/barcode_gen/views/message_view.c b/base_pack/barcode_gen/views/message_view.c index dc3b9525..903b4bd5 100644 --- a/base_pack/barcode_gen/views/message_view.c +++ b/base_pack/barcode_gen/views/message_view.c @@ -23,16 +23,11 @@ static bool app_input_callback(InputEvent* input_event, void* ctx) { MessageView* message_view_object = ctx; - bool dismissed = false; - if(input_event->key == InputKeyBack) { - dismissed = true; - } - if(input_event->type == InputTypeShort && input_event->key == InputKeyOk) { - dismissed = true; - } + bool dismissed = input_event->type == InputTypeShort && + (input_event->key == InputKeyBack || input_event->key == InputKeyOk); if(dismissed) { - uint32_t next_view = MainMenuView; + uint32_t next_view; with_view_model( message_view_object->view, MessageViewModel * model, @@ -58,9 +53,32 @@ MessageView* message_view_allocate(BarcodeApp* barcode_app) { view_set_draw_callback(message_view_object->view, app_draw_callback); view_set_input_callback(message_view_object->view, app_input_callback); + //safe default in case a caller sets a message without a next_view + with_view_model( + message_view_object->view, + MessageViewModel * model, + { model->next_view = MainMenuView; }, + false); + return message_view_object; } +void message_view_show(MessageView* message_view_object, const char* message, uint32_t next_view) { + furi_assert(message_view_object); + + with_view_model( + message_view_object->view, + MessageViewModel * model, + { + model->message = message; + model->next_view = next_view; + }, + true); + + view_dispatcher_switch_to_view( + message_view_object->barcode_app->view_dispatcher, MessageErrorView); +} + void message_view_free(MessageView* message_view_object) { furi_assert(message_view_object); diff --git a/base_pack/barcode_gen/views/message_view.h b/base_pack/barcode_gen/views/message_view.h index c3a99475..c2742eb4 100644 --- a/base_pack/barcode_gen/views/message_view.h +++ b/base_pack/barcode_gen/views/message_view.h @@ -10,6 +10,8 @@ typedef struct { } MessageView; typedef struct { + //the message to display, the string is not copied + //so it must outlive the message view (e.g. a string literal) const char* message; //the view to switch to when the message is dismissed uint32_t next_view; @@ -17,7 +19,13 @@ typedef struct { MessageView* message_view_allocate(BarcodeApp* barcode_app); -void message_view_free_model(MessageView* message_view_object); +/** + * Shows a message in the message view and switches to it + * @param message the message to display, the string is not copied + * so it must outlive the message view (e.g. a string literal) + * @param next_view the view to switch to when the message is dismissed +*/ +void message_view_show(MessageView* message_view_object, const char* message, uint32_t next_view); void message_view_free(MessageView* message_view_object);