TollyH 2 лет назад
Родитель
Сommit
e7be67e38d

BIN
assets/DolphinSaved_92x58.png


+ 45 - 0
mfc_editor_app.c

@@ -145,6 +145,7 @@ MfcEditorPromptResponse mfc_editor_load_file(MfcEditorApp* instance, FuriString*
             const MfClassicData* mf_classic_data =
                 nfc_device_get_data(nfc_device, NfcProtocolMfClassic);
             mf_classic_copy(instance->mf_classic_data, mf_classic_data);
+            instance->is_unsaved_changes = false;
         } else {
             result = MfcEditorPromptResponseNotMfClassic;
         }
@@ -155,6 +156,25 @@ MfcEditorPromptResponse mfc_editor_load_file(MfcEditorApp* instance, FuriString*
     return result;
 }
 
+bool mfc_editor_save_file(MfcEditorApp* instance) {
+    furi_assert(instance);
+    furi_assert(instance->file_path);
+    furi_assert(instance->mf_classic_data);
+
+    NfcDevice* nfc_device = nfc_device_alloc();
+
+    nfc_device_set_data(nfc_device, NfcProtocolMfClassic, instance->mf_classic_data);
+
+    bool result = nfc_device_save(nfc_device, furi_string_get_cstr(instance->file_path));
+    if(!result) {
+        dialog_message_show_storage_error(instance->dialogs, "Cannot save\nkey file");
+    }
+
+    nfc_device_free(nfc_device);
+
+    return result;
+}
+
 static DialogMessageButton mfc_editor_prompt_should_load_shadow(MfcEditorApp* instance) {
     DialogMessage* message = dialog_message_alloc();
     dialog_message_set_header(message, "File has modifications", 63, 3, AlignCenter, AlignTop);
@@ -252,6 +272,31 @@ bool mfc_editor_warn_risky_operation(MfcEditorApp* instance) {
     return message_button == DialogMessageButtonCenter;
 }
 
+MfcEditorSaveResponse mfc_editor_warn_unsaved_changes(MfcEditorApp* instance) {
+    DialogMessage* message = dialog_message_alloc();
+    dialog_message_set_header(message, "Unsaved changes", 63, 3, AlignCenter, AlignTop);
+    dialog_message_set_text(
+        message,
+        "Would you like to save?\nDiscarding your\nchanges is permanent.",
+        63,
+        31,
+        AlignCenter,
+        AlignCenter);
+    dialog_message_set_buttons(message, "Discrd", "Save", "Cancel");
+
+    DialogMessageButton message_button = dialog_message_show(instance->dialogs, message);
+
+    dialog_message_free(message);
+
+    if(message_button == DialogMessageButtonCenter) {
+        return MfcEditorSaveResponseSave;
+    } else if(message_button == DialogMessageButtonLeft) {
+        return MfcEditorSaveResponseDiscard;
+    } else {
+        return MfcEditorSaveResponseCancel;
+    }
+}
+
 int32_t mfc_editor_app(void* p) {
     UNUSED(p);
 

+ 13 - 1
mfc_editor_app_i.h

@@ -59,6 +59,8 @@ struct MfcEditorApp {
 
     FuriString* file_path;
 
+    bool is_unsaved_changes;
+
     uint8_t current_sector;
     uint8_t current_block;
 
@@ -89,6 +91,12 @@ typedef enum {
     MfcEditorPromptResponseExitedShadow,
 } MfcEditorPromptResponse;
 
+typedef enum {
+    MfcEditorSaveResponseSave,
+    MfcEditorSaveResponseDiscard,
+    MfcEditorSaveResponseCancel,
+} MfcEditorSaveResponse;
+
 typedef enum {
     MfcEditorBlockViewNormal,
 
@@ -110,10 +118,14 @@ MfcEditorPromptResponse mfc_editor_prompt_load_file(MfcEditorApp* instance);
 
 MfcEditorPromptResponse mfc_editor_load_file(MfcEditorApp* instance, FuriString* file_path);
 
-// Warning dialog
+bool mfc_editor_save_file(MfcEditorApp* instance);
+
+// Warning dialogs
 
 bool mfc_editor_warn_risky_operation(MfcEditorApp* instance);
 
+MfcEditorSaveResponse mfc_editor_warn_unsaved_changes(MfcEditorApp* instance);
+
 // Helper methods
 
 uint8_t mfc_editor_calculate_uid_bcc(uint8_t* uid, uint8_t uid_len);

+ 1 - 0
scenes/mfc_editor_scene_config.h

@@ -6,3 +6,4 @@ ADD_SCENE(mfc_editor, block_select, BlockSelect)
 ADD_SCENE(mfc_editor, data_view, DataView)
 ADD_SCENE(mfc_editor, data_edit, DataEdit)
 ADD_SCENE(mfc_editor, data_edit_access_bits, DataEditAccessBits)
+ADD_SCENE(mfc_editor, save_success, SaveSuccess)

+ 3 - 2
scenes/mfc_editor_scene_data_edit.c

@@ -186,9 +186,10 @@ bool mfc_editor_scene_data_edit_on_event(void* context, SceneManagerEvent event)
                 mf_classic_get_sector_trailer_by_sector(mf_classic_data, instance->current_sector)
                     ->access_bits.data[3] = instance->edit_buffer[0];
             }
+            instance->is_unsaved_changes = true;
+            scene_manager_previous_scene(instance->scene_manager);
+            consumed = true;
         }
-        scene_manager_previous_scene(instance->scene_manager);
-        consumed = true;
     }
 
     return consumed;

+ 1 - 0
scenes/mfc_editor_scene_data_edit_access_bits.c

@@ -87,6 +87,7 @@ bool mfc_editor_scene_data_edit_access_bits_on_event(void* context, SceneManager
         } else if(event.event == DialogExResultCenter) {
             mfc_editor_set_block_access_bits(
                 instance->mf_classic_data, instance->current_block, &instance->access_bits_edit);
+            instance->is_unsaved_changes = true;
             scene_manager_previous_scene(instance->scene_manager);
             consumed = true;
         }

+ 2 - 0
scenes/mfc_editor_scene_data_view.c

@@ -269,6 +269,7 @@ bool mfc_editor_scene_data_view_on_event(void* context, SceneManagerEvent event)
                         instance->mf_classic_data->block[0].data,
                         instance->mf_classic_data->iso14443_3a_data->uid,
                         instance->mf_classic_data->iso14443_3a_data->uid_len);
+                    instance->is_unsaved_changes = true;
                     mfc_editor_scene_data_view_update_display(instance);
                 }
                 consumed = true;
@@ -291,6 +292,7 @@ bool mfc_editor_scene_data_view_on_event(void* context, SceneManagerEvent event)
                     instance->mf_classic_data->block[0].data[4] = mfc_editor_calculate_uid_bcc(
                         instance->mf_classic_data->iso14443_3a_data->uid,
                         instance->mf_classic_data->iso14443_3a_data->uid_len);
+                    instance->is_unsaved_changes = true;
                     mfc_editor_scene_data_view_update_display(instance);
                 }
                 consumed = true;

+ 40 - 0
scenes/mfc_editor_scene_save_success.c

@@ -0,0 +1,40 @@
+#include "../mfc_editor_app_i.h"
+
+void mfc_editor_scene_save_success_popup_callback(void* context) {
+    MfcEditorApp* instance = context;
+    view_dispatcher_send_custom_event(instance->view_dispatcher, MfcEditorCustomEventViewExit);
+}
+
+void mfc_editor_scene_save_success_on_enter(void* context) {
+    MfcEditorApp* instance = context;
+
+    Popup* popup = instance->popup;
+    popup_set_icon(popup, 36, 5, &I_DolphinSaved_92x58);
+    popup_set_header(popup, "Saved", 15, 19, AlignLeft, AlignBottom);
+    popup_set_timeout(popup, 1500);
+    popup_set_context(popup, instance);
+    popup_set_callback(popup, mfc_editor_scene_save_success_popup_callback);
+    popup_enable_timeout(popup);
+
+    view_dispatcher_switch_to_view(instance->view_dispatcher, MfcEditorAppViewPopup);
+}
+
+bool mfc_editor_scene_save_success_on_event(void* context, SceneManagerEvent event) {
+    MfcEditorApp* instance = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == MfcEditorCustomEventViewExit) {
+            consumed = scene_manager_search_and_switch_to_previous_scene(
+                instance->scene_manager, MfcEditorSceneFileSelect);
+        }
+    }
+
+    return consumed;
+}
+
+void mfc_editor_scene_save_success_on_exit(void* context) {
+    MfcEditorApp* instance = context;
+
+    popup_reset(instance->popup);
+}

+ 14 - 0
scenes/mfc_editor_scene_sector_select.c

@@ -41,6 +41,20 @@ bool mfc_editor_scene_sector_select_on_event(void* context, SceneManagerEvent ev
         scene_manager_set_scene_state(instance->scene_manager, MfcEditorSceneBlockSelect, 0);
         scene_manager_next_scene(instance->scene_manager, MfcEditorSceneBlockSelect);
         consumed = true;
+    } else if(event.type == SceneManagerEventTypeBack) {
+        if(instance->is_unsaved_changes) {
+            MfcEditorSaveResponse response = mfc_editor_warn_unsaved_changes(instance);
+            if(response == MfcEditorSaveResponseSave) {
+                if(mfc_editor_save_file(instance)) {
+                    scene_manager_next_scene(instance->scene_manager, MfcEditorSceneSaveSuccess);
+                }
+                // Stop the scene manager from going back to previous scene
+                consumed = true;
+            } else if(response == MfcEditorSaveResponseCancel) {
+                // Stop the scene manager from going back to previous scene
+                consumed = true;
+            }
+        }
     }
 
     return consumed;