|
|
@@ -0,0 +1,242 @@
|
|
|
+#include "mag_i.h"
|
|
|
+
|
|
|
+static bool mag_debug_custom_event_callback(void* context, uint32_t event) {
|
|
|
+ furi_assert(context);
|
|
|
+ Mag* mag = context;
|
|
|
+ return scene_manager_handle_custom_event(mag->scene_manager, event);
|
|
|
+}
|
|
|
+
|
|
|
+static bool mag_debug_back_event_callback(void* context) {
|
|
|
+ furi_assert(context);
|
|
|
+ Mag* mag = context;
|
|
|
+ return scene_manager_handle_back_event(mag->scene_manager);
|
|
|
+}
|
|
|
+
|
|
|
+static Mag* mag_alloc() {
|
|
|
+ Mag* mag = malloc(sizeof(Mag));
|
|
|
+
|
|
|
+ mag->storage = furi_record_open(RECORD_STORAGE);
|
|
|
+ mag->dialogs = furi_record_open(RECORD_DIALOGS);
|
|
|
+
|
|
|
+ mag->file_name = furi_string_alloc();
|
|
|
+ mag->file_path = furi_string_alloc_set(MAG_APP_FOLDER);
|
|
|
+
|
|
|
+ mag->view_dispatcher = view_dispatcher_alloc();
|
|
|
+ mag->scene_manager = scene_manager_alloc(&mag_scene_handlers, mag);
|
|
|
+ view_dispatcher_enable_queue(mag->view_dispatcher);
|
|
|
+ view_dispatcher_set_event_callback_context(mag->view_dispatcher, mag);
|
|
|
+ view_dispatcher_set_custom_event_callback(
|
|
|
+ mag->view_dispatcher, mag_debug_custom_event_callback);
|
|
|
+ view_dispatcher_set_navigation_event_callback(
|
|
|
+ mag->view_dispatcher, mag_debug_back_event_callback);
|
|
|
+
|
|
|
+ // Open GUI record
|
|
|
+ mag->gui = furi_record_open(RECORD_GUI);
|
|
|
+
|
|
|
+ // Open Notification record
|
|
|
+ mag->notifications = furi_record_open(RECORD_NOTIFICATION);
|
|
|
+
|
|
|
+ // Submenu
|
|
|
+ mag->submenu = submenu_alloc();
|
|
|
+ view_dispatcher_add_view(mag->view_dispatcher, MagViewSubmenu, submenu_get_view(mag->submenu));
|
|
|
+
|
|
|
+ // Dialog
|
|
|
+ mag->dialog_ex = dialog_ex_alloc();
|
|
|
+ view_dispatcher_add_view(
|
|
|
+ mag->view_dispatcher, MagViewDialogEx, dialog_ex_get_view(mag->dialog_ex));
|
|
|
+
|
|
|
+ // Popup
|
|
|
+ mag->popup = popup_alloc();
|
|
|
+ view_dispatcher_add_view(mag->view_dispatcher, MagViewPopup, popup_get_view(mag->popup));
|
|
|
+
|
|
|
+ // Widget
|
|
|
+ mag->widget = widget_alloc();
|
|
|
+ view_dispatcher_add_view(mag->view_dispatcher, MagViewWidget, widget_get_view(mag->widget));
|
|
|
+
|
|
|
+ // Text Input
|
|
|
+ mag->text_input = text_input_alloc();
|
|
|
+ view_dispatcher_add_view(
|
|
|
+ mag->view_dispatcher, MagViewTextInput, text_input_get_view(mag->text_input));
|
|
|
+
|
|
|
+ // Byte Input
|
|
|
+ mag->byte_input = byte_input_alloc();
|
|
|
+ view_dispatcher_add_view(
|
|
|
+ mag->view_dispatcher, MagViewByteInput, byte_input_get_view(mag->byte_input));
|
|
|
+
|
|
|
+ return mag;
|
|
|
+}
|
|
|
+
|
|
|
+static void mag_free(Mag* mag) {
|
|
|
+ furi_assert(mag);
|
|
|
+
|
|
|
+ furi_string_free(mag->file_name);
|
|
|
+ furi_string_free(mag->file_path);
|
|
|
+
|
|
|
+ // Submenu
|
|
|
+ view_dispatcher_remove_view(mag->view_dispatcher, MagViewSubmenu);
|
|
|
+ submenu_free(mag->submenu);
|
|
|
+
|
|
|
+ // DialogEx
|
|
|
+ view_dispatcher_remove_view(mag->view_dispatcher, MagViewDialogEx);
|
|
|
+ dialog_ex_free(mag->dialog_ex);
|
|
|
+
|
|
|
+ // Popup
|
|
|
+ view_dispatcher_remove_view(mag->view_dispatcher, MagViewPopup);
|
|
|
+ popup_free(mag->popup);
|
|
|
+
|
|
|
+ // Widget
|
|
|
+ view_dispatcher_remove_view(mag->view_dispatcher, MagViewWidget);
|
|
|
+ widget_free(mag->widget);
|
|
|
+
|
|
|
+ // TextInput
|
|
|
+ view_dispatcher_remove_view(mag->view_dispatcher, MagViewTextInput);
|
|
|
+ text_input_free(mag->text_input);
|
|
|
+
|
|
|
+ // ByteInput
|
|
|
+ view_dispatcher_remove_view(mag->view_dispatcher, MagViewByteInput);
|
|
|
+ byte_input_free(mag->byte_input);
|
|
|
+
|
|
|
+ // View Dispatcher
|
|
|
+ view_dispatcher_free(mag->view_dispatcher);
|
|
|
+
|
|
|
+ // Scene Manager
|
|
|
+ scene_manager_free(mag->scene_manager);
|
|
|
+
|
|
|
+ // GUI
|
|
|
+ furi_record_close(RECORD_GUI);
|
|
|
+ mag->gui = NULL;
|
|
|
+
|
|
|
+ // Notifications
|
|
|
+ furi_record_close(RECORD_NOTIFICATION);
|
|
|
+ mag->notifications = NULL;
|
|
|
+
|
|
|
+ furi_record_close(RECORD_STORAGE);
|
|
|
+ furi_record_close(RECORD_DIALOGS);
|
|
|
+
|
|
|
+ free(mag);
|
|
|
+}
|
|
|
+
|
|
|
+// entry point for app
|
|
|
+int32_t mag_app(void* p) {
|
|
|
+ Mag* mag = mag_alloc();
|
|
|
+ char* args = p;
|
|
|
+ UNUSED(args);
|
|
|
+
|
|
|
+ mag_make_app_folder(mag);
|
|
|
+
|
|
|
+ view_dispatcher_attach_to_gui(mag->view_dispatcher, mag->gui, ViewDispatcherTypeFullscreen);
|
|
|
+ scene_manager_next_scene(mag->scene_manager, MagSceneStart);
|
|
|
+
|
|
|
+ view_dispatcher_run(mag->view_dispatcher);
|
|
|
+
|
|
|
+ mag_free(mag);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+bool mag_save_key(Mag* mag) {
|
|
|
+ furi_assert(mag);
|
|
|
+
|
|
|
+ bool result = false;
|
|
|
+
|
|
|
+ mag_make_app_folder(mag);
|
|
|
+
|
|
|
+ if(furi_string_end_with(mag->file_path, MAG_APP_EXTENSION)) {
|
|
|
+ size_t filename_start = furi_string_search_rchar(mag->file_path, '/');
|
|
|
+ furi_string_left(mag->file_path, filename_start);
|
|
|
+ }
|
|
|
+
|
|
|
+ furi_string_cat_printf(
|
|
|
+ mag->file_path, "/%s%s", furi_string_get_cstr(mag->file_name), MAG_APP_EXTENSION);
|
|
|
+
|
|
|
+ result = mag_save_key_data(mag, mag->file_path);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+bool mag_load_key_from_file_select(Mag* mag) {
|
|
|
+ furi_assert(mag);
|
|
|
+
|
|
|
+ DialogsFileBrowserOptions browser_options;
|
|
|
+ // TODO: Fix icon reference / definition! Temporarily importing asset_icons.h in mag_i.h to let it compile. Remove when fixed!
|
|
|
+ dialog_file_browser_set_basic_options(&browser_options, MAG_APP_EXTENSION, &I_125_10px);
|
|
|
+ browser_options.base_path = MAG_APP_FOLDER;
|
|
|
+
|
|
|
+ // Input events and views are managed by file_browser
|
|
|
+ bool result =
|
|
|
+ dialog_file_browser_show(mag->dialogs, mag->file_path, mag->file_path, &browser_options);
|
|
|
+
|
|
|
+ if(result) {
|
|
|
+ result = mag_load_key_data(mag, mag->file_path, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+bool mag_delete_key(Mag* mag) {
|
|
|
+ furi_assert(mag);
|
|
|
+
|
|
|
+ return storage_simply_remove(mag->storage, furi_string_get_cstr(mag->file_path));
|
|
|
+}
|
|
|
+
|
|
|
+bool mag_load_key_data(Mag* mag, FuriString* path, bool show_dialog) {
|
|
|
+ bool result = false;
|
|
|
+ UNUSED(mag);
|
|
|
+ UNUSED(path);
|
|
|
+ UNUSED(show_dialog);
|
|
|
+
|
|
|
+ // TODO: Needs reworking from LFRFID version, as that goes through some custom protocol by key type.
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+bool mag_save_key_data(Mag* mag, FuriString* path) {
|
|
|
+ bool result = false;
|
|
|
+ UNUSED(path);
|
|
|
+ //bool result = lfrfid_dict_file_save(app->dict, app->protocol_id, furi_string_get_cstr(path));
|
|
|
+ // TODO: needs reworking from LFRFID version
|
|
|
+ if(!result) {
|
|
|
+ dialog_message_show_storage_error(mag->dialogs, "Cannot save\nkey file");
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+void mag_make_app_folder(Mag* mag) {
|
|
|
+ furi_assert(mag);
|
|
|
+
|
|
|
+ if(!storage_simply_mkdir(mag->storage, MAG_APP_FOLDER)) {
|
|
|
+ dialog_message_show_storage_error(mag->dialogs, "Cannot create\napp folder");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void mag_text_store_set(Mag* mag, const char* text, ...) {
|
|
|
+ furi_assert(mag);
|
|
|
+ va_list args;
|
|
|
+ va_start(args, text);
|
|
|
+
|
|
|
+ vsnprintf(mag->text_store, MAG_TEXT_STORE_SIZE, text, args);
|
|
|
+
|
|
|
+ va_end(args);
|
|
|
+}
|
|
|
+
|
|
|
+void mag_text_store_clear(Mag* mag) {
|
|
|
+ furi_assert(mag);
|
|
|
+ memset(mag->text_store, 0, sizeof(mag->text_store));
|
|
|
+}
|
|
|
+
|
|
|
+void mag_popup_timeout_callback(void* context) {
|
|
|
+ Mag* mag = context;
|
|
|
+ view_dispatcher_send_custom_event(mag->view_dispatcher, MagEventPopupClosed);
|
|
|
+}
|
|
|
+
|
|
|
+void mag_widget_callback(GuiButtonType result, InputType type, void* context) {
|
|
|
+ Mag* mag = context;
|
|
|
+ if(type == InputTypeShort) {
|
|
|
+ view_dispatcher_send_custom_event(mag->view_dispatcher, result);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void mag_text_input_callback(void* context) {
|
|
|
+ Mag* mag = context;
|
|
|
+ view_dispatcher_send_custom_event(mag->view_dispatcher, MagEventNext);
|
|
|
+}
|