Просмотр исходного кода

[FL-1448], [FL-1529] Introducing Scene Manager, NFC App refactoring and bug fixes (#575)

* gui: refactore ViewNavigator -> SceneManager
* view_dispatcher: remove scene controller, add custom and navigation cb
* scene_manager: rework scene controller, move AppScene from lib
* nfc: rework nfc scenes with new scene controller API
* view_dispatcher: crash on free if not all views were freed
* nfc: introduce scene declaration
* scene_manager: allocate and configure application scenes
* nfc: rework nfc with new Scene Manager API
* scene_manager: remove dublicated scene handlers allocation
* nfc: rework nfc app with new scene manager API
* view_dispatcher: add tick event
* scene_manager: add tick event type and handler
* nfc: rework notifications with tick event
* scene_manager: remove scene id from scene structure
* scene_manager: rename array -> stack, add documentation
* api-hal-nfc: remove listen activation processing
* nfc_scene_start: shorter submenu call
* nfc: fix nfc file name
* nfc: fix Retry in mifare ul success read
* nfc_cli: fix read timeout in nfc_detect CLI command

Co-authored-by: あく <alleteam@gmail.com>
gornekich 4 лет назад
Родитель
Сommit
3571b58d0a
65 измененных файлов с 753 добавлено и 1218 удалено
  1. 139 0
      applications/gui/scene_manager.c
  2. 116 0
      applications/gui/scene_manager.h
  3. 17 0
      applications/gui/scene_manager_i.h
  4. 48 60
      applications/gui/view_dispatcher.c
  5. 35 14
      applications/gui/view_dispatcher.h
  6. 8 5
      applications/gui/view_dispatcher_i.h
  7. 0 109
      applications/gui/view_navigator.c
  8. 0 28
      applications/gui/view_navigator.h
  9. 0 16
      applications/gui/view_navigator_i.h
  10. 36 54
      applications/nfc/nfc.c
  11. 2 2
      applications/nfc/nfc_cli.c
  12. 2 2
      applications/nfc/nfc_device.c
  13. 7 80
      applications/nfc/nfc_i.h
  14. 30 0
      applications/nfc/scenes/nfc_scene.c
  15. 29 0
      applications/nfc/scenes/nfc_scene.h
  16. 26 44
      applications/nfc/scenes/nfc_scene_card_menu.c
  17. 0 7
      applications/nfc/scenes/nfc_scene_card_menu.h
  18. 23 0
      applications/nfc/scenes/nfc_scene_config.h
  19. 1 18
      applications/nfc/scenes/nfc_scene_debug_detect.c
  20. 0 7
      applications/nfc/scenes/nfc_scene_debug_detect.h
  21. 1 18
      applications/nfc/scenes/nfc_scene_debug_emulate.c
  22. 0 7
      applications/nfc/scenes/nfc_scene_debug_emulate.h
  23. 25 41
      applications/nfc/scenes/nfc_scene_debug_menu.c
  24. 0 7
      applications/nfc/scenes/nfc_scene_debug_menu.h
  25. 1 18
      applications/nfc/scenes/nfc_scene_debug_read_emv.c
  26. 0 7
      applications/nfc/scenes/nfc_scene_debug_read_emv.h
  27. 1 18
      applications/nfc/scenes/nfc_scene_debug_read_mifare_ul.c
  28. 0 7
      applications/nfc/scenes/nfc_scene_debug_read_mifare_ul.h
  29. 10 22
      applications/nfc/scenes/nfc_scene_emulate_uid.c
  30. 0 7
      applications/nfc/scenes/nfc_scene_emulate_uid.h
  31. 3 24
      applications/nfc/scenes/nfc_scene_file_select.c
  32. 0 7
      applications/nfc/scenes/nfc_scene_file_select.h
  33. 17 32
      applications/nfc/scenes/nfc_scene_mifare_ul_menu.c
  34. 0 7
      applications/nfc/scenes/nfc_scene_mifare_ul_menu.h
  35. 5 24
      applications/nfc/scenes/nfc_scene_not_implemented.c
  36. 0 7
      applications/nfc/scenes/nfc_scene_not_implemented.h
  37. 9 27
      applications/nfc/scenes/nfc_scene_read_card.c
  38. 0 7
      applications/nfc/scenes/nfc_scene_read_card.h
  39. 10 31
      applications/nfc/scenes/nfc_scene_read_card_success.c
  40. 0 7
      applications/nfc/scenes/nfc_scene_read_card_success.h
  41. 9 23
      applications/nfc/scenes/nfc_scene_read_mifare_ul.c
  42. 0 7
      applications/nfc/scenes/nfc_scene_read_mifare_ul.h
  43. 33 46
      applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c
  44. 0 7
      applications/nfc/scenes/nfc_scene_read_mifare_ul_success.h
  45. 11 33
      applications/nfc/scenes/nfc_scene_save_name.c
  46. 0 7
      applications/nfc/scenes/nfc_scene_save_name.h
  47. 5 23
      applications/nfc/scenes/nfc_scene_save_success.c
  48. 0 7
      applications/nfc/scenes/nfc_scene_save_success.h
  49. 23 40
      applications/nfc/scenes/nfc_scene_saved_menu.c
  50. 0 7
      applications/nfc/scenes/nfc_scene_saved_menu.h
  51. 15 31
      applications/nfc/scenes/nfc_scene_scripts_menu.c
  52. 0 7
      applications/nfc/scenes/nfc_scene_scripts_menu.h
  53. 6 26
      applications/nfc/scenes/nfc_scene_set_atqa.c
  54. 0 7
      applications/nfc/scenes/nfc_scene_set_atqa.h
  55. 6 26
      applications/nfc/scenes/nfc_scene_set_sak.c
  56. 0 7
      applications/nfc/scenes/nfc_scene_set_sak.h
  57. 11 32
      applications/nfc/scenes/nfc_scene_set_type.c
  58. 0 7
      applications/nfc/scenes/nfc_scene_set_type.h
  59. 6 26
      applications/nfc/scenes/nfc_scene_set_uid.c
  60. 0 7
      applications/nfc/scenes/nfc_scene_set_uid.h
  61. 27 44
      applications/nfc/scenes/nfc_scene_start.c
  62. 0 7
      applications/nfc/scenes/nfc_scene_start.h
  63. 0 4
      firmware/targets/f5/api-hal/api-hal-nfc.c
  64. 0 4
      firmware/targets/f6/api-hal/api-hal-nfc.c
  65. 0 12
      lib/app_scene_template/app_scene.h

+ 139 - 0
applications/gui/scene_manager.c

@@ -0,0 +1,139 @@
+#include "scene_manager_i.h"
+#include <furi.h>
+
+SceneManager* scene_manager_alloc(const SceneManagerHandlers* app_scene_handlers, void* context) {
+    furi_assert(context);
+
+    SceneManager* scene_manager = furi_alloc(sizeof(SceneManager));
+    // Set SceneManager context and scene handlers
+    scene_manager->context = context;
+    scene_manager->scene_handlers = app_scene_handlers;
+    // Allocate all scenes
+    scene_manager->scene = furi_alloc(sizeof(AppScene) * app_scene_handlers->scene_num);
+    // Initialize ScaneManager array for navigation
+    SceneManagerIdStack_init(scene_manager->scene_id_stack);
+
+    return scene_manager;
+}
+
+void scene_manager_free(SceneManager* scene_manager) {
+    furi_assert(scene_manager);
+
+    // Clear ScaneManager array
+    SceneManagerIdStack_clear(scene_manager->scene_id_stack);
+    // Clear allocated scenes
+    free(scene_manager->scene);
+    // Free SceneManager structure
+    free(scene_manager);
+}
+
+void scene_manager_set_scene_state(SceneManager* scene_manager, uint32_t scene_id, uint32_t state) {
+    furi_assert(scene_manager);
+    furi_assert(scene_id < scene_manager->scene_handlers->scene_num);
+
+    scene_manager->scene[scene_id].state = state;
+}
+
+uint32_t scene_manager_get_scene_state(SceneManager* scene_manager, uint32_t scene_id) {
+    furi_assert(scene_manager);
+    furi_assert(scene_id < scene_manager->scene_handlers->scene_num);
+
+    return scene_manager->scene[scene_id].state;
+}
+
+bool scene_manager_handle_custom_event(SceneManager* scene_manager, uint32_t custom_event) {
+    furi_assert(scene_manager);
+
+    SceneManagerEvent event = {
+        .type = SceneManagerEventTypeCustom,
+        .event = custom_event,
+    };
+    uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
+    return scene_manager->scene_handlers->on_event_handlers[scene_id](
+        scene_manager->context, event);
+}
+
+bool scene_manager_handle_navigation_event(SceneManager* scene_manager) {
+    furi_assert(scene_manager);
+
+    SceneManagerEvent event = {
+        .type = SceneManagerEventTypeNavigation,
+    };
+    uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
+    bool consumed =
+        scene_manager->scene_handlers->on_event_handlers[scene_id](scene_manager->context, event);
+    if(!consumed) {
+        consumed = scene_manager_previous_scene(scene_manager);
+    }
+    return consumed;
+}
+
+void scene_manager_handle_tick_event(SceneManager* scene_manager) {
+    furi_assert(scene_manager);
+
+    SceneManagerEvent event = {
+        .type = SceneManagerEventTypeTick,
+    };
+    uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
+    scene_manager->scene_handlers->on_event_handlers[scene_id](scene_manager->context, event);
+}
+
+void scene_manager_next_scene(SceneManager* scene_manager, uint32_t next_scene_id) {
+    furi_assert(scene_manager);
+    furi_assert(next_scene_id < scene_manager->scene_handlers->scene_num);
+
+    // Check if it is not the first scene
+    if(SceneManagerIdStack_size(scene_manager->scene_id_stack)) {
+        uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
+        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
+    }
+    // Add next scene and run on_enter
+    SceneManagerIdStack_push_back(scene_manager->scene_id_stack, next_scene_id);
+    scene_manager->scene_handlers->on_enter_handlers[next_scene_id](scene_manager->context);
+}
+
+bool scene_manager_previous_scene(SceneManager* scene_manager) {
+    furi_assert(scene_manager);
+
+    uint32_t cur_scene_id = 0;
+    SceneManagerIdStack_pop_back(&cur_scene_id, scene_manager->scene_id_stack);
+
+    // Handle exit from start scene separately
+    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) == 0) {
+        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
+        return false;
+    }
+    uint32_t prev_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
+    scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
+    scene_manager->scene_handlers->on_enter_handlers[prev_scene_id](scene_manager->context);
+    return true;
+}
+
+bool scene_manager_search_previous_scene(SceneManager* scene_manager, uint32_t scene_id) {
+    furi_assert(scene_manager);
+
+    uint32_t prev_scene_id = 0;
+    uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
+    SceneManagerIdStack_it_t scene_it;
+    SceneManagerIdStack_it_last(scene_it, scene_manager->scene_id_stack);
+    // Search scene with given id in navigation stack
+    bool scene_found = false;
+    while(!scene_found) {
+        SceneManagerIdStack_previous(scene_it);
+        if(SceneManagerIdStack_end_p(scene_it)) {
+            return false;
+        }
+        prev_scene_id = *SceneManagerIdStack_ref(scene_it);
+        if(prev_scene_id == scene_id) {
+            scene_found = true;
+        }
+    }
+    // Remove all scene id from navigation stack
+    SceneManagerIdStack_next(scene_it);
+    SceneManagerIdStack_pop_until(scene_manager->scene_id_stack, scene_it);
+
+    scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
+    scene_manager->scene_handlers->on_enter_handlers[prev_scene_id](scene_manager->context);
+
+    return true;
+}

+ 116 - 0
applications/gui/scene_manager.h

@@ -0,0 +1,116 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/** Scene Manager events type
+ */
+typedef enum {
+    SceneManagerEventTypeCustom,
+    SceneManagerEventTypeNavigation,
+    SceneManagerEventTypeTick,
+} SceneManagerEventType;
+
+/** Scene Manager event
+ */
+typedef struct {
+    SceneManagerEventType type;
+    uint32_t event;
+} SceneManagerEvent;
+
+/** Prototype for Scene on_enter handler */
+typedef void (*AppSceneOnEnterCallback)(void* context);
+
+/** Prototype for Scene on_event handler */
+typedef bool (*AppSceneOnEventCallback)(void* context, SceneManagerEvent event);
+
+/** Prototype for Scene on_exit handler */
+typedef void (*AppSceneOnExitCallback)(void* context);
+
+/** Scene Manager configuration structure
+ * Contains array of Scene handlers
+ */
+typedef struct {
+    const AppSceneOnEnterCallback* on_enter_handlers;
+    const AppSceneOnEventCallback* on_event_handlers;
+    const AppSceneOnExitCallback* on_exit_handlers;
+    const uint32_t scene_num;
+} SceneManagerHandlers;
+
+typedef struct SceneManager SceneManager;
+
+/** Set Scene state
+ * @param scene_manager SceneManager instance
+ * @param scene_id Scene ID
+ * @param state Scene new state
+ */
+void scene_manager_set_scene_state(SceneManager* scene_manager, uint32_t scene_id, uint32_t state);
+
+/** Get Scene state
+ * @param scene_manager SceneManager instance
+ * @param scene_id Scene ID
+ * @return Scene state
+ */
+uint32_t scene_manager_get_scene_state(SceneManager* scene_manager, uint32_t scene_id);
+
+/** Scene Manager allocation and configuration
+ * Scene Manager allocates all scenes internally
+ * @param app_scene_handlers SceneManagerHandlers instance
+ * @param context context to be set on Scene handlers calls
+ * @return SceneManager instance
+ */
+SceneManager* scene_manager_alloc(const SceneManagerHandlers* app_scene_handlers, void* context);
+
+/** Free Scene Manager with allocated Scenes
+ * @param scene_manager SceneManager instance
+ */
+void scene_manager_free(SceneManager* scene_manager);
+
+/** Custom event handler
+ * Calls Scene event handler with Custom event parameter
+ * @param scene_manager SceneManager instance
+ * @param custom_event Custom event code
+ * @return true if event was consumed, false otherwise
+ */
+bool scene_manager_handle_custom_event(SceneManager* scene_manager, uint32_t custom_event);
+
+/** Navigation event handler
+ * Calls Scene event handler with Navigation event parameter
+ * @param scene_manager SceneManager instance
+ * @return true if event was consumed, false otherwise
+ */
+bool scene_manager_handle_navigation_event(SceneManager* scene_manager);
+
+/** Tick event handler
+ * Calls Scene event handler with Tick event parameter
+ * @param scene_manager SceneManager instance
+ * @return true if event was consumed, false otherwise
+ */
+void scene_manager_handle_tick_event(SceneManager* scene_manager);
+
+/** Add and run next Scene
+ * @param scene_manager SceneManager instance
+ * @param next_scene_id next Scene ID
+ */
+void scene_manager_next_scene(SceneManager* scene_manager, uint32_t next_scene_id);
+
+/** Run previous Scene
+ * @param scene_manager SceneManager instance
+ * @return true if previous scene was found, false otherwise
+ */
+bool scene_manager_previous_scene(SceneManager* scene_manager);
+
+/** Search previous Scene by ID
+ * @param scene_manager SceneManager instance
+ * @param scene_id Scene ID
+ * @return true if previous scene was found, false otherwise
+ */
+bool scene_manager_search_previous_scene(SceneManager* scene_manager, uint32_t scene_id);
+
+#ifdef __cplusplus
+}
+#endif

+ 17 - 0
applications/gui/scene_manager_i.h

@@ -0,0 +1,17 @@
+#pragma once
+
+#include "scene_manager.h"
+#include <m-array.h>
+
+ARRAY_DEF(SceneManagerIdStack, uint32_t, M_DEFAULT_OPLIST);
+
+typedef struct {
+    uint32_t state;
+} AppScene;
+
+struct SceneManager {
+    SceneManagerIdStack_t scene_id_stack;
+    const SceneManagerHandlers* scene_handlers;
+    AppScene* scene;
+    void* context;
+};

+ 48 - 60
applications/gui/view_dispatcher.c

@@ -20,15 +20,9 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher) {
     if(view_dispatcher->gui) {
     if(view_dispatcher->gui) {
         gui_remove_view_port(view_dispatcher->gui, view_dispatcher->view_port);
         gui_remove_view_port(view_dispatcher->gui, view_dispatcher->view_port);
     }
     }
-    // Free views
-    ViewDict_it_t it;
-    ViewDict_it(it, view_dispatcher->views);
-    while(!ViewDict_end_p(it)) {
-        ViewDict_itref_t* ref = ViewDict_ref(it);
-        // Crash if view wasn't freed
-        furi_check(ref->value);
-        ViewDict_next(it);
-    }
+    // Crash if not all views were freed
+    furi_assert(ViewDict_size(view_dispatcher->views) == 0);
+
     ViewDict_clear(view_dispatcher->views);
     ViewDict_clear(view_dispatcher->views);
     // Free ViewPort
     // Free ViewPort
     view_port_free(view_dispatcher->view_port);
     view_port_free(view_dispatcher->view_port);
@@ -36,10 +30,6 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher) {
     if(view_dispatcher->queue) {
     if(view_dispatcher->queue) {
         osMessageQueueDelete(view_dispatcher->queue);
         osMessageQueueDelete(view_dispatcher->queue);
     }
     }
-    // Free View Navigator
-    if(view_dispatcher->view_navigator) {
-        view_navigator_free(view_dispatcher->view_navigator);
-    }
     // Free dispatcher
     // Free dispatcher
     free(view_dispatcher);
     free(view_dispatcher);
 }
 }
@@ -50,40 +40,55 @@ void view_dispatcher_enable_queue(ViewDispatcher* view_dispatcher) {
     view_dispatcher->queue = osMessageQueueNew(8, sizeof(ViewDispatcherMessage), NULL);
     view_dispatcher->queue = osMessageQueueNew(8, sizeof(ViewDispatcherMessage), NULL);
 }
 }
 
 
-void view_dispatcher_enable_navigation(ViewDispatcher* view_dispatcher, void* context) {
+void view_dispatcher_set_event_callback_context(ViewDispatcher* view_dispatcher, void* context) {
+    furi_assert(view_dispatcher);
+    view_dispatcher->event_context = context;
+}
+
+void view_dispatcher_set_navigation_event_callback(
+    ViewDispatcher* view_dispatcher,
+    ViewDispatcherNavigationEventCallback callback) {
+    furi_assert(view_dispatcher);
+    furi_assert(callback);
+    view_dispatcher->navigation_event_callback = callback;
+}
+
+void view_dispatcher_set_custom_event_callback(
+    ViewDispatcher* view_dispatcher,
+    ViewDispatcherCustomEventCallback callback) {
     furi_assert(view_dispatcher);
     furi_assert(view_dispatcher);
-    view_dispatcher->view_navigator = view_navigator_alloc(context);
+    furi_assert(callback);
+    view_dispatcher->custom_event_callback = callback;
 }
 }
 
 
-void view_dispatcher_add_scene(ViewDispatcher* view_dispatcher, AppScene* scene) {
+void view_dispatcher_set_tick_event_callback(
+    ViewDispatcher* view_dispatcher,
+    ViewDispatcherTickEventCallback callback,
+    uint32_t tick_period) {
     furi_assert(view_dispatcher);
     furi_assert(view_dispatcher);
-    furi_assert(view_dispatcher->view_navigator);
-    furi_assert(scene);
-    view_navigator_add_next_scene(view_dispatcher->view_navigator, scene);
+    furi_assert(callback);
+    view_dispatcher->tick_event_callback = callback;
+    view_dispatcher->tick_period = tick_period;
 }
 }
 
 
 void view_dispatcher_run(ViewDispatcher* view_dispatcher) {
 void view_dispatcher_run(ViewDispatcher* view_dispatcher) {
     furi_assert(view_dispatcher);
     furi_assert(view_dispatcher);
     furi_assert(view_dispatcher->queue);
     furi_assert(view_dispatcher->queue);
 
 
-    if(view_dispatcher->view_navigator) {
-        view_navigator_start(view_dispatcher->view_navigator);
-    }
-
+    uint32_t tick_period = view_dispatcher->tick_period == 0 ? osWaitForever :
+                                                               view_dispatcher->tick_period;
     ViewDispatcherMessage message;
     ViewDispatcherMessage message;
-    while(osMessageQueueGet(view_dispatcher->queue, &message, NULL, osWaitForever) == osOK) {
+    while(1) {
+        if(osMessageQueueGet(view_dispatcher->queue, &message, NULL, tick_period) != osOK) {
+            view_dispatcher_handle_tick_event(view_dispatcher);
+            continue;
+        }
         if(message.type == ViewDispatcherMessageTypeStop) {
         if(message.type == ViewDispatcherMessageTypeStop) {
             break;
             break;
         } else if(message.type == ViewDispatcherMessageTypeInput) {
         } else if(message.type == ViewDispatcherMessageTypeInput) {
             view_dispatcher_handle_input(view_dispatcher, &message.input);
             view_dispatcher_handle_input(view_dispatcher, &message.input);
         } else if(message.type == ViewDispatcherMessageTypeCustomEvent) {
         } else if(message.type == ViewDispatcherMessageTypeCustomEvent) {
             view_dispatcher_handle_custom_event(view_dispatcher, message.custom_event);
             view_dispatcher_handle_custom_event(view_dispatcher, message.custom_event);
-        } else if(message.type == ViewDispatcherMessageTypeNavigationEvent) {
-            view_navigator_handle_navigation_event(
-                view_dispatcher->view_navigator, message.navigator_event);
-        } else if(message.type == ViewDispatcherMessageTypeBackSearchScene) {
-            view_navigator_handle_back_search_scene_event(
-                view_dispatcher->view_navigator, message.navigator_event);
         }
         }
     }
     }
 }
 }
@@ -206,9 +211,9 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
         uint32_t view_id = VIEW_IGNORE;
         uint32_t view_id = VIEW_IGNORE;
         if(event->key == InputKeyBack) {
         if(event->key == InputKeyBack) {
             view_id = view_previous(view_dispatcher->current_view);
             view_id = view_previous(view_dispatcher->current_view);
-            if((view_id == VIEW_IGNORE) && (view_dispatcher->view_navigator)) {
-                is_consumed = view_navigator_handle_navigation_event(
-                    view_dispatcher->view_navigator, ViewNavigatorEventBack);
+            if((view_id == VIEW_IGNORE) && (view_dispatcher->navigation_event_callback)) {
+                is_consumed =
+                    view_dispatcher->navigation_event_callback(view_dispatcher->event_context);
                 if(!is_consumed) {
                 if(!is_consumed) {
                     view_dispatcher_stop(view_dispatcher);
                     view_dispatcher_stop(view_dispatcher);
                     return;
                     return;
@@ -223,14 +228,21 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
     }
     }
 }
 }
 
 
+void view_dispatcher_handle_tick_event(ViewDispatcher* view_dispatcher) {
+    if(view_dispatcher->tick_event_callback) {
+        view_dispatcher->tick_event_callback(view_dispatcher->event_context);
+    }
+}
+
 void view_dispatcher_handle_custom_event(ViewDispatcher* view_dispatcher, uint32_t event) {
 void view_dispatcher_handle_custom_event(ViewDispatcher* view_dispatcher, uint32_t event) {
     bool is_consumed = false;
     bool is_consumed = false;
     if(view_dispatcher->current_view) {
     if(view_dispatcher->current_view) {
         is_consumed = view_custom(view_dispatcher->current_view, event);
         is_consumed = view_custom(view_dispatcher->current_view, event);
     }
     }
-    // If custom event is not consumed in View, handle it in Scene
-    if(!is_consumed) {
-        is_consumed = view_navigator_handle_custom_event(view_dispatcher->view_navigator, event);
+    // If custom event is not consumed in View, call callback
+    if(!is_consumed && view_dispatcher->custom_event_callback) {
+        is_consumed =
+            view_dispatcher->custom_event_callback(view_dispatcher->event_context, event);
     }
     }
 }
 }
 
 
@@ -245,30 +257,6 @@ void view_dispatcher_send_custom_event(ViewDispatcher* view_dispatcher, uint32_t
     furi_check(osMessageQueuePut(view_dispatcher->queue, &message, 0, osWaitForever) == osOK);
     furi_check(osMessageQueuePut(view_dispatcher->queue, &message, 0, osWaitForever) == osOK);
 }
 }
 
 
-void view_dispatcher_send_navigation_event(ViewDispatcher* view_dispatcher, uint32_t event) {
-    furi_assert(view_dispatcher);
-    furi_assert(view_dispatcher->queue);
-    furi_assert(view_dispatcher->view_navigator);
-
-    ViewDispatcherMessage message;
-    message.type = ViewDispatcherMessageTypeNavigationEvent;
-    message.custom_event = event;
-
-    furi_check(osMessageQueuePut(view_dispatcher->queue, &message, 0, osWaitForever) == osOK);
-}
-
-void view_dispatcher_send_back_search_scene_event(ViewDispatcher* view_dispatcher, uint32_t event) {
-    furi_assert(view_dispatcher);
-    furi_assert(view_dispatcher->queue);
-    furi_assert(view_dispatcher->view_navigator);
-
-    ViewDispatcherMessage message;
-    message.type = ViewDispatcherMessageTypeBackSearchScene;
-    message.custom_event = event;
-
-    furi_check(osMessageQueuePut(view_dispatcher->queue, &message, 0, osWaitForever) == osOK);
-}
-
 void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* view) {
 void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* view) {
     furi_assert(view_dispatcher);
     furi_assert(view_dispatcher);
     // Dispatch view exit event
     // Dispatch view exit event

+ 35 - 14
applications/gui/view_dispatcher.h

@@ -2,7 +2,7 @@
 
 
 #include "view.h"
 #include "view.h"
 #include "gui.h"
 #include "gui.h"
-#include "view_navigator.h"
+#include "scene_manager.h"
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
@@ -18,6 +18,18 @@ typedef enum {
 
 
 typedef struct ViewDispatcher ViewDispatcher;
 typedef struct ViewDispatcher ViewDispatcher;
 
 
+/** Prototype for custom event callback
+ */
+typedef bool (*ViewDispatcherCustomEventCallback)(void* context, uint32_t event);
+
+/** Prototype for navigation event callback
+ */
+typedef bool (*ViewDispatcherNavigationEventCallback)(void* context);
+
+/** Prototype for tick event callback
+ */
+typedef void (*ViewDispatcherTickEventCallback)(void* context);
+
 /** Allocate ViewDispatcher instance
 /** Allocate ViewDispatcher instance
  * @return pointer to ViewDispatcher instance
  * @return pointer to ViewDispatcher instance
  */
  */
@@ -39,30 +51,39 @@ void view_dispatcher_enable_queue(ViewDispatcher* view_dispatcher);
  */
  */
 void view_dispatcher_send_custom_event(ViewDispatcher* view_dispatcher, uint32_t event);
 void view_dispatcher_send_custom_event(ViewDispatcher* view_dispatcher, uint32_t event);
 
 
-/** Enable View Navigator to handle custom events and scene navigation
+/** Set custom event handler
+ * Called on Custom Event, if it is not consumed by view
  * @param view_dispatcher ViewDispatcher instance
  * @param view_dispatcher ViewDispatcher instance
- * @param context  context for all scenes
+ * @param callback ViewDispatcherCustomEventCallback instance
  */
  */
-void view_dispatcher_enable_navigation(ViewDispatcher* view_dispatcher, void* context);
+void view_dispatcher_set_custom_event_callback(
+    ViewDispatcher* view_dispatcher,
+    ViewDispatcherCustomEventCallback callback);
 
 
-/** Add Scene to view navigator
- * Use only after navigation enabled
+/** Set navigation event handler
+ * Called on Input Short Back Event, if it is not consumed by view
  * @param view_dispatcher ViewDispatcher instance
  * @param view_dispatcher ViewDispatcher instance
- * @param scene AppScene instance
+ * @param callback ViewDispatcherNavigationEventCallback instance
  */
  */
-void view_dispatcher_add_scene(ViewDispatcher* view_dispatcher, AppScene* scene);
+void view_dispatcher_set_navigation_event_callback(
+    ViewDispatcher* view_dispatcher,
+    ViewDispatcherNavigationEventCallback callback);
 
 
-/** Send navigation event
+/** Set tick event handler
  * @param view_dispatcher ViewDispatcher instance
  * @param view_dispatcher ViewDispatcher instance
- * @param event event
+ * @param callback ViewDispatcherTickEventCallback
+ * @param tick_period callback call period
  */
  */
-void view_dispatcher_send_navigation_event(ViewDispatcher* view_dispatcher, uint32_t event);
+void view_dispatcher_set_tick_event_callback(
+    ViewDispatcher* view_dispatcher,
+    ViewDispatcherTickEventCallback callback,
+    uint32_t tick_period);
 
 
-/** Send search scene event
+/** Set event callback context
  * @param view_dispatcher ViewDispatcher instance
  * @param view_dispatcher ViewDispatcher instance
- * @param event event
+ * @param context pointer to context
  */
  */
-void view_dispatcher_send_back_search_scene_event(ViewDispatcher* view_dispatcher, uint32_t event);
+void view_dispatcher_set_event_callback_context(ViewDispatcher* view_dispatcher, void* context);
 
 
 /** Run ViewDispatcher
 /** Run ViewDispatcher
  * Use only after queue enabled
  * Use only after queue enabled

+ 8 - 5
applications/gui/view_dispatcher_i.h

@@ -15,14 +15,16 @@ struct ViewDispatcher {
     ViewPort* view_port;
     ViewPort* view_port;
     ViewDict_t views;
     ViewDict_t views;
     View* current_view;
     View* current_view;
-    ViewNavigator* view_navigator;
+    ViewDispatcherCustomEventCallback custom_event_callback;
+    ViewDispatcherNavigationEventCallback navigation_event_callback;
+    ViewDispatcherTickEventCallback tick_event_callback;
+    uint32_t tick_period;
+    void* event_context;
 };
 };
 
 
 typedef enum {
 typedef enum {
     ViewDispatcherMessageTypeInput,
     ViewDispatcherMessageTypeInput,
     ViewDispatcherMessageTypeCustomEvent,
     ViewDispatcherMessageTypeCustomEvent,
-    ViewDispatcherMessageTypeNavigationEvent,
-    ViewDispatcherMessageTypeBackSearchScene,
     ViewDispatcherMessageTypeStop,
     ViewDispatcherMessageTypeStop,
 } ViewDispatcherMessageType;
 } ViewDispatcherMessageType;
 
 
@@ -31,8 +33,6 @@ typedef struct {
     union {
     union {
         InputEvent input;
         InputEvent input;
         uint32_t custom_event;
         uint32_t custom_event;
-        ViewNavigatorEvent navigator_event;
-        uint32_t scene_id;
     };
     };
 } ViewDispatcherMessage;
 } ViewDispatcherMessage;
 
 
@@ -45,6 +45,9 @@ void view_dispatcher_input_callback(InputEvent* event, void* context);
 /* Input handler */
 /* Input handler */
 void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* event);
 void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* event);
 
 
+/* Tick handler */
+void view_dispatcher_handle_tick_event(ViewDispatcher* view_dispatcher);
+
 /* Custom event handler */
 /* Custom event handler */
 void view_dispatcher_handle_custom_event(ViewDispatcher* view_dispatcher, uint32_t event);
 void view_dispatcher_handle_custom_event(ViewDispatcher* view_dispatcher, uint32_t event);
 
 

+ 0 - 109
applications/gui/view_navigator.c

@@ -1,109 +0,0 @@
-#include "view_navigator_i.h"
-
-ViewNavigator* view_navigator_alloc(void* context) {
-    furi_assert(context);
-
-    ViewNavigator* view_navigator = furi_alloc(sizeof(ViewNavigator));
-    view_navigator->context = context;
-    ViewNavSceneArray_init(view_navigator->scene_array);
-
-    return view_navigator;
-}
-
-void view_navigator_free(ViewNavigator* view_navigator) {
-    furi_assert(view_navigator);
-    ViewNavSceneArray_clear(view_navigator->scene_array);
-
-    free(view_navigator);
-}
-
-bool view_navigator_handle_custom_event(ViewNavigator* view_navigator, uint32_t event) {
-    AppScene* scene = *ViewNavSceneArray_back(view_navigator->scene_array);
-    return scene->on_event(view_navigator->context, event);
-}
-
-bool view_navigator_handle_navigation_event(ViewNavigator* view_navigator, uint32_t event) {
-    if(event == ViewNavigatorEventNext) {
-        return view_navigator_next_scene(view_navigator);
-    } else if(event == ViewNavigatorEventBack) {
-        AppScene* scene = *ViewNavSceneArray_back(view_navigator->scene_array);
-        if(scene->on_event(view_navigator->context, ViewNavigatorEventBack)) {
-            return true;
-        } else {
-            return view_navigator_previous_scene(view_navigator);
-        }
-    }
-    return false;
-}
-
-bool view_navigator_handle_back_search_scene_event(ViewNavigator* view_navigator, uint32_t event) {
-    return view_navigator_search_previous_scene(view_navigator, event);
-}
-
-void view_navigator_add_next_scene(ViewNavigator* view_navigator, AppScene* scene) {
-    furi_assert(view_navigator);
-    furi_assert(scene);
-
-    ViewNavSceneArray_push_back(view_navigator->scene_array, scene);
-}
-
-void view_navigator_start(ViewNavigator* view_navigator) {
-    furi_assert(view_navigator);
-    AppScene* scene = *ViewNavSceneArray_front(view_navigator->scene_array);
-    furi_assert(scene);
-    scene->on_enter(view_navigator->context);
-}
-
-bool view_navigator_next_scene(ViewNavigator* view_navigator) {
-    ViewNavSceneArray_it_t scene_it;
-    ViewNavSceneArray_it_last(scene_it, view_navigator->scene_array);
-    ViewNavSceneArray_previous(scene_it);
-    AppScene* current_scene = *ViewNavSceneArray_ref(scene_it);
-    AppScene* next_scene = *ViewNavSceneArray_back(view_navigator->scene_array);
-    if(current_scene && next_scene) {
-        current_scene->on_exit(view_navigator->context);
-        next_scene->on_enter(view_navigator->context);
-        return true;
-    }
-    return false;
-}
-
-bool view_navigator_previous_scene(ViewNavigator* view_navigator) {
-    AppScene* current_scene = NULL;
-    ViewNavSceneArray_pop_back(&current_scene, view_navigator->scene_array);
-    if(ViewNavSceneArray_size(view_navigator->scene_array) == 0) {
-        // Handle exit from start scene separately
-        current_scene->on_exit(view_navigator->context);
-        return false;
-    }
-    AppScene* previous_scene = *ViewNavSceneArray_back(view_navigator->scene_array);
-    if(current_scene && previous_scene) {
-        current_scene->on_exit(view_navigator->context);
-        previous_scene->on_enter(view_navigator->context);
-        return true;
-    }
-    return false;
-}
-
-bool view_navigator_search_previous_scene(ViewNavigator* view_navigator, uint32_t scene_id) {
-    AppScene* previous_scene = NULL;
-    AppScene* current_scene = *ViewNavSceneArray_back(view_navigator->scene_array);
-    ViewNavSceneArray_it_t scene_it;
-    ViewNavSceneArray_it_last(scene_it, view_navigator->scene_array);
-    bool scene_found = false;
-    while(!scene_found) {
-        ViewNavSceneArray_previous(scene_it);
-        previous_scene = *ViewNavSceneArray_ref(scene_it);
-        if(previous_scene == NULL) {
-            return false;
-        }
-        if(previous_scene->id == scene_id) {
-            scene_found = true;
-        }
-    }
-    ViewNavSceneArray_next(scene_it);
-    ViewNavSceneArray_pop_until(view_navigator->scene_array, scene_it);
-    current_scene->on_exit(view_navigator->context);
-    previous_scene->on_enter(view_navigator->context);
-    return true;
-}

+ 0 - 28
applications/gui/view_navigator.h

@@ -1,28 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum {
-    ViewNavigatorEventNext = 0x00000000UL,
-    ViewNavigatorEventBack = 0xFFFFFFFFUL,
-} ViewNavigatorEvent;
-
-typedef struct ViewNavigator ViewNavigator;
-
-ViewNavigator* view_navigator_alloc(void* context);
-void view_navigator_free(ViewNavigator* view_navigator);
-
-bool view_navigator_handle_custom_event(ViewNavigator* view_navigator, uint32_t event);
-bool view_navigator_handle_navigation_event(ViewNavigator* view_navigator, uint32_t event);
-bool view_navigator_handle_back_search_scene_event(ViewNavigator* view_navigator, uint32_t event);
-
-void view_navigator_add_next_scene(ViewNavigator* view_navigator, AppScene* scene);
-void view_navigator_start(ViewNavigator* view_navigator);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 16
applications/gui/view_navigator_i.h

@@ -1,16 +0,0 @@
-#pragma once
-
-#include "view_navigator.h"
-#include <furi.h>
-#include <m-array.h>
-
-ARRAY_DEF(ViewNavSceneArray, AppScene*, M_PTR_OPLIST);
-
-struct ViewNavigator {
-    ViewNavSceneArray_t scene_array;
-    void* context;
-};
-
-bool view_navigator_next_scene(ViewNavigator* view_navigator);
-bool view_navigator_previous_scene(ViewNavigator* view_navigator);
-bool view_navigator_search_previous_scene(ViewNavigator* view_navigator, uint32_t scene_id);

+ 36 - 54
applications/nfc/nfc.c

@@ -1,14 +1,38 @@
 #include "nfc_i.h"
 #include "nfc_i.h"
 #include "api-hal-nfc.h"
 #include "api-hal-nfc.h"
-#include "app_scene.h"
+
+bool nfc_custom_event_callback(void* context, uint32_t event) {
+    furi_assert(context);
+    Nfc* nfc = (Nfc*)context;
+    return scene_manager_handle_custom_event(nfc->scene_manager, event);
+}
+
+bool nfc_navigation_event_callback(void* context) {
+    furi_assert(context);
+    Nfc* nfc = (Nfc*)context;
+    return scene_manager_handle_navigation_event(nfc->scene_manager);
+}
+
+void nfc_tick_event_callback(void* context) {
+    furi_assert(context);
+    Nfc* nfc = (Nfc*)context;
+    scene_manager_handle_tick_event(nfc->scene_manager);
+}
 
 
 Nfc* nfc_alloc() {
 Nfc* nfc_alloc() {
     Nfc* nfc = furi_alloc(sizeof(Nfc));
     Nfc* nfc = furi_alloc(sizeof(Nfc));
 
 
     nfc->nfc_common.worker = nfc_worker_alloc();
     nfc->nfc_common.worker = nfc_worker_alloc();
     nfc->nfc_common.view_dispatcher = view_dispatcher_alloc();
     nfc->nfc_common.view_dispatcher = view_dispatcher_alloc();
+    nfc->scene_manager = scene_manager_alloc(&nfc_scene_handlers, nfc);
     view_dispatcher_enable_queue(nfc->nfc_common.view_dispatcher);
     view_dispatcher_enable_queue(nfc->nfc_common.view_dispatcher);
-    view_dispatcher_enable_navigation(nfc->nfc_common.view_dispatcher, nfc);
+    view_dispatcher_set_event_callback_context(nfc->nfc_common.view_dispatcher, nfc);
+    view_dispatcher_set_custom_event_callback(
+        nfc->nfc_common.view_dispatcher, nfc_custom_event_callback);
+    view_dispatcher_set_navigation_event_callback(
+        nfc->nfc_common.view_dispatcher, nfc_navigation_event_callback);
+    view_dispatcher_set_tick_event_callback(
+        nfc->nfc_common.view_dispatcher, nfc_tick_event_callback, 300);
 
 
     // Open GUI record
     // Open GUI record
     nfc->gui = furi_record_open("gui");
     nfc->gui = furi_record_open("gui");
@@ -71,32 +95,8 @@ Nfc* nfc_alloc() {
         NfcViewMifareUl,
         NfcViewMifareUl,
         nfc_mifare_ul_get_view(nfc->nfc_mifare_ul));
         nfc_mifare_ul_get_view(nfc->nfc_mifare_ul));
 
 
-    // Scene allocation
-    nfc->scene_start = nfc_scene_start_alloc();
-    nfc->scene_read_card = nfc_scene_read_card_alloc();
-    nfc->scene_read_card_success = nfc_scene_read_card_success_alloc();
-    nfc->scene_card_menu = nfc_scene_card_menu_alloc();
-    nfc->scene_not_implemented = nfc_scene_not_implemented_alloc();
-    nfc->scene_debug_menu = nfc_scene_debug_menu_alloc();
-    nfc->scene_debug_detect = nfc_scene_debug_detect_alloc();
-    nfc->scene_debug_emulate = nfc_scene_debug_emulate_alloc();
-    nfc->scene_debug_read_emv = nfc_scene_debug_read_emv_alloc();
-    nfc->scene_debug_read_mifare_ul = nfc_scene_debug_read_mifare_ul_alloc();
-    nfc->scene_emulate_uid = nfc_scene_emulate_uid_alloc();
-    nfc->scene_save_name = nfc_scene_save_name_alloc();
-    nfc->scene_save_success = nfc_scene_save_success_alloc();
-    nfc->scene_file_select = nfc_scene_file_select_alloc();
-    nfc->scene_saved_menu = nfc_scene_saved_menu_alloc();
-    nfc->scene_set_type = nfc_scene_set_type_alloc();
-    nfc->scene_set_sak = nfc_scene_set_sak_alloc();
-    nfc->scene_set_atqa = nfc_scene_set_atqa_alloc();
-    nfc->scene_set_uid = nfc_scene_set_uid_alloc();
-    nfc->scene_scripts_menu = nfc_scene_scripts_menu_alloc();
-    nfc->scene_read_mifare_ul = nfc_scene_read_mifare_ul_alloc();
-    nfc->scene_read_mifare_ul_success = nfc_scene_read_mifare_ul_success_alloc();
-    nfc->scene_mifare_ul_menu = nfc_scene_mifare_ul_menu_alloc();
-
-    view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_start);
+    // Run first scene
+    scene_manager_next_scene(nfc->scene_manager, NfcSceneStart);
 
 
     return nfc;
     return nfc;
 }
 }
@@ -149,34 +149,12 @@ void nfc_free(Nfc* nfc) {
     nfc_worker_stop(nfc->nfc_common.worker);
     nfc_worker_stop(nfc->nfc_common.worker);
     nfc_worker_free(nfc->nfc_common.worker);
     nfc_worker_free(nfc->nfc_common.worker);
 
 
-    // Scenes
-    nfc_scene_start_free(nfc->scene_start);
-    nfc_scene_read_card_free(nfc->scene_read_card);
-    nfc_scene_read_card_success_free(nfc->scene_read_card_success);
-    nfc_scene_card_menu_free(nfc->scene_card_menu);
-    nfc_scene_not_implemented_free(nfc->scene_not_implemented);
-    nfc_scene_debug_menu_free(nfc->scene_debug_menu);
-    nfc_scene_debug_detect_free(nfc->scene_debug_detect);
-    nfc_scene_debug_emulate_free(nfc->scene_debug_emulate);
-    nfc_scene_debug_read_emv_free(nfc->scene_debug_read_emv);
-    nfc_scene_debug_read_mifare_ul_free(nfc->scene_debug_read_mifare_ul);
-    nfc_scene_emulate_uid_free(nfc->scene_emulate_uid);
-    nfc_scene_save_name_free(nfc->scene_save_name);
-    nfc_scene_save_success_free(nfc->scene_save_success);
-    nfc_scene_file_select_free(nfc->scene_file_select);
-    nfc_scene_saved_menu_free(nfc->scene_saved_menu);
-    nfc_scene_set_type_free(nfc->scene_set_type);
-    nfc_scene_set_sak_free(nfc->scene_set_sak);
-    nfc_scene_set_atqa_free(nfc->scene_set_atqa);
-    nfc_scene_set_uid_free(nfc->scene_set_uid);
-    nfc_scene_scripts_menu_free(nfc->scene_scripts_menu);
-    nfc_scene_read_mifare_ul_free(nfc->scene_read_mifare_ul);
-    nfc_scene_read_mifare_ul_success_free(nfc->scene_read_mifare_ul_success);
-    nfc_scene_mifare_ul_menu_free(nfc->scene_mifare_ul_menu);
-
     // View Dispatcher
     // View Dispatcher
     view_dispatcher_free(nfc->nfc_common.view_dispatcher);
     view_dispatcher_free(nfc->nfc_common.view_dispatcher);
 
 
+    // Scene Manager
+    scene_manager_free(nfc->scene_manager);
+
     // GUI
     // GUI
     furi_record_close("gui");
     furi_record_close("gui");
     nfc->gui = NULL;
     nfc->gui = NULL;
@@ -198,7 +176,7 @@ int32_t nfc_task(void* p) {
     return 0;
     return 0;
 }
 }
 
 
-void nfc_set_text_store(Nfc* nfc, const char* text, ...) {
+void nfc_text_store_set(Nfc* nfc, const char* text, ...) {
     va_list args;
     va_list args;
     va_start(args, text);
     va_start(args, text);
 
 
@@ -206,3 +184,7 @@ void nfc_set_text_store(Nfc* nfc, const char* text, ...) {
 
 
     va_end(args);
     va_end(args);
 }
 }
+
+void nfc_text_store_clear(Nfc* nfc) {
+    memset(nfc->text_store, 0, sizeof(nfc->text_store));
+}

+ 2 - 2
applications/nfc/nfc_cli.c

@@ -24,7 +24,7 @@ void nfc_cli_detect(Cli* cli, string_t args, void* context) {
     printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n");
     printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n");
     while(!cmd_exit) {
     while(!cmd_exit) {
         cmd_exit |= cli_cmd_interrupt_received(cli);
         cmd_exit |= cli_cmd_interrupt_received(cli);
-        cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, true);
+        cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 200, true);
         if(dev_cnt > 0) {
         if(dev_cnt > 0) {
             printf("Found %d devices\r\n", dev_cnt);
             printf("Found %d devices\r\n", dev_cnt);
             for(uint8_t i = 0; i < dev_cnt; i++) {
             for(uint8_t i = 0; i < dev_cnt; i++) {
@@ -57,7 +57,7 @@ void nfc_cli_emulate(Cli* cli, string_t args, void* context) {
     printf("Press Ctrl+C to abort\r\n");
     printf("Press Ctrl+C to abort\r\n");
 
 
     NfcDeviceData params = {
     NfcDeviceData params = {
-        .uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1},
+        .uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1, 0x34},
         .uid_len = 7,
         .uid_len = 7,
         .atqa = {0x44, 0x00},
         .atqa = {0x44, 0x00},
         .sak = 0x00,
         .sak = 0x00,

+ 2 - 2
applications/nfc/nfc_device.c

@@ -25,7 +25,7 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
     };
     };
 
 
     // First remove nfc device file if it was saved
     // First remove nfc device file if it was saved
-    string_init_printf(dev_file_name, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_extension);
+    string_init_printf(dev_file_name, "%s/%s%s", nfc_app_folder, dev_name, nfc_app_extension);
     if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) {
     if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) {
         string_clear(dev_file_name);
         string_clear(dev_file_name);
         return false;
         return false;
@@ -73,7 +73,7 @@ static bool nfc_device_load_data(FileWorker* file_worker, string_t path, NfcDevi
         return false;
         return false;
     }
     }
 
 
-    // // Load other data
+    // Load other data
     if(!file_worker_read_hex(file_worker, &buff[1], buff[0] + 3)) {
     if(!file_worker_read_hex(file_worker, &buff[1], buff[0] + 3)) {
         return false;
         return false;
     }
     }

+ 7 - 80
applications/nfc/nfc_i.h

@@ -10,6 +10,7 @@
 #include <gui/gui.h>
 #include <gui/gui.h>
 #include <gui/view.h>
 #include <gui/view.h>
 #include <gui/view_dispatcher.h>
 #include <gui/view_dispatcher.h>
+#include <gui/scene_manager.h>
 #include <cli/cli.h>
 #include <cli/cli.h>
 #include <notification/notification-messages.h>
 #include <notification/notification-messages.h>
 
 
@@ -20,43 +21,20 @@
 #include <gui/modules/byte_input.h>
 #include <gui/modules/byte_input.h>
 #include <gui/modules/text_box.h>
 #include <gui/modules/text_box.h>
 
 
+#include <nfc/scenes/nfc_scene.h>
+
 #include "views/nfc_detect.h"
 #include "views/nfc_detect.h"
 #include "views/nfc_emulate.h"
 #include "views/nfc_emulate.h"
 #include "views/nfc_emv.h"
 #include "views/nfc_emv.h"
 #include "views/nfc_mifare_ul.h"
 #include "views/nfc_mifare_ul.h"
 
 
-#include "scenes/nfc_scene_start.h"
-#include "scenes/nfc_scene_read_card.h"
-#include "scenes/nfc_scene_read_card_success.h"
-#include "scenes/nfc_scene_card_menu.h"
-#include "scenes/nfc_scene_emulate_uid.h"
-#include "scenes/nfc_scene_not_implemented.h"
-#include "scenes/nfc_scene_save_name.h"
-#include "scenes/nfc_scene_save_success.h"
-#include "scenes/nfc_scene_file_select.h"
-#include "scenes/nfc_scene_saved_menu.h"
-#include "scenes/nfc_scene_set_type.h"
-#include "scenes/nfc_scene_set_sak.h"
-#include "scenes/nfc_scene_set_atqa.h"
-#include "scenes/nfc_scene_set_uid.h"
-#include "scenes/nfc_scene_scripts_menu.h"
-#include "scenes/nfc_scene_read_mifare_ul.h"
-#include "scenes/nfc_scene_read_mifare_ul_success.h"
-#include "scenes/nfc_scene_mifare_ul_menu.h"
-
-// TODO delete debug scenes
-#include "scenes/nfc_scene_debug_menu.h"
-#include "scenes/nfc_scene_debug_detect.h"
-#include "scenes/nfc_scene_debug_emulate.h"
-#include "scenes/nfc_scene_debug_read_emv.h"
-#include "scenes/nfc_scene_debug_read_mifare_ul.h"
-
 #define NFC_TEXT_STORE_SIZE 128
 #define NFC_TEXT_STORE_SIZE 128
 
 
 struct Nfc {
 struct Nfc {
     NfcCommon nfc_common;
     NfcCommon nfc_common;
     Gui* gui;
     Gui* gui;
     NotificationApp* notifications;
     NotificationApp* notifications;
+    SceneManager* scene_manager;
     NfcDevice device;
     NfcDevice device;
 
 
     char text_store[NFC_TEXT_STORE_SIZE + 1];
     char text_store[NFC_TEXT_STORE_SIZE + 1];
@@ -75,33 +53,6 @@ struct Nfc {
     TextInput* text_input;
     TextInput* text_input;
     ByteInput* byte_input;
     ByteInput* byte_input;
     TextBox* text_box;
     TextBox* text_box;
-
-    // Scenes
-    AppScene* scene_start;
-    AppScene* scene_read_card;
-    AppScene* scene_read_card_success;
-    AppScene* scene_card_menu;
-    AppScene* scene_not_implemented;
-    AppScene* scene_emulate_uid;
-    AppScene* scene_save_name;
-    AppScene* scene_save_success;
-    AppScene* scene_file_select;
-    AppScene* scene_saved_menu;
-    AppScene* scene_set_type;
-    AppScene* scene_set_sak;
-    AppScene* scene_set_atqa;
-    AppScene* scene_set_uid;
-    AppScene* scene_scripts_menu;
-    AppScene* scene_read_mifare_ul;
-    AppScene* scene_read_mifare_ul_success;
-    AppScene* scene_mifare_ul_menu;
-
-    // TODO delete debug scenes
-    AppScene* scene_debug_menu;
-    AppScene* scene_debug_detect;
-    AppScene* scene_debug_emulate;
-    AppScene* scene_debug_read_emv;
-    AppScene* scene_debug_read_mifare_ul;
 };
 };
 
 
 typedef enum {
 typedef enum {
@@ -117,34 +68,10 @@ typedef enum {
     NfcViewMifareUl,
     NfcViewMifareUl,
 } NfcView;
 } NfcView;
 
 
-typedef enum {
-    NfcSceneStart,
-    NfcSceneReadCard,
-    NfcSceneReadCardSuccess,
-    NfcSceneCardMenu,
-    NfcSceneEmulateUID,
-    NfcSceneNotImplemented,
-    NfcSceneDebugMenu,
-    NfcSceneDebugDetect,
-    NfcSceneDebugEmulate,
-    NfcSceneDebugReadEmv,
-    NfcSceneDebugReadMifareUl,
-    NfcSceneSaveName,
-    NfcSceneSaveSuccess,
-    NfcSceneFileSelect,
-    NfcSceneSavedMenu,
-    NfcSceneSetType,
-    NfcSceneSetSak,
-    NfcSceneSetAtqa,
-    NfcSceneSetUid,
-    NfcSceneScriptsMenu,
-    NfcSceneReadMifareUl,
-    NfcSceneReadMifareUlSuccess,
-    NfcSceneReadMifareUlMenu,
-} NfcScene;
-
 Nfc* nfc_alloc();
 Nfc* nfc_alloc();
 
 
 int32_t nfc_task(void* p);
 int32_t nfc_task(void* p);
 
 
-void nfc_set_text_store(Nfc* nfc, const char* text, ...);
+void nfc_text_store_set(Nfc* nfc, const char* text, ...);
+
+void nfc_text_store_clear(Nfc* nfc);

+ 30 - 0
applications/nfc/scenes/nfc_scene.c

@@ -0,0 +1,30 @@
+#include "nfc_scene.h"
+
+// Generate scene on_enter handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
+void (*const nfc_on_enter_handlers[])(void*) = {
+#include "nfc_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Generate scene on_event handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
+bool (*const nfc_on_event_handlers[])(void* context, SceneManagerEvent event) = {
+#include "nfc_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Generate scene on_exit handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
+void (*const nfc_on_exit_handlers[])(void* context) = {
+#include "nfc_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Initialize scene handlers configuration structure
+const SceneManagerHandlers nfc_scene_handlers = {
+    .on_enter_handlers = nfc_on_enter_handlers,
+    .on_event_handlers = nfc_on_event_handlers,
+    .on_exit_handlers = nfc_on_exit_handlers,
+    .scene_num = NfcSceneNum,
+};

+ 29 - 0
applications/nfc/scenes/nfc_scene.h

@@ -0,0 +1,29 @@
+#pragma once
+
+#include <gui/scene_manager.h>
+
+// Generate scene id and total number
+#define ADD_SCENE(prefix, name, id) NfcScene##id,
+typedef enum {
+#include "nfc_scene_config.h"
+    NfcSceneNum,
+} NfcScene;
+#undef ADD_SCENE
+
+extern const SceneManagerHandlers nfc_scene_handlers;
+
+// Generate scene on_enter handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
+#include "nfc_scene_config.h"
+#undef ADD_SCENE
+
+// Generate scene on_event handlers declaration
+#define ADD_SCENE(prefix, name, id) \
+    bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
+#include "nfc_scene_config.h"
+#undef ADD_SCENE
+
+// Generate scene on_exit handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
+#include "nfc_scene_config.h"
+#undef ADD_SCENE

+ 26 - 44
applications/nfc/scenes/nfc_scene_card_menu.c

@@ -1,10 +1,5 @@
-#include "nfc_scene_card_menu.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-#include <gui/modules/submenu.h>
-#include <gui/view_dispatcher.h>
-
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexRunApp,
     SubmenuIndexRunApp,
     SubmenuIndexChooseScript,
     SubmenuIndexChooseScript,
@@ -38,37 +33,38 @@ const void nfc_scene_card_menu_on_enter(void* context) {
         submenu, "Emulate UID", SubmenuIndexEmulate, nfc_scene_card_menu_submenu_callback, nfc);
         submenu, "Emulate UID", SubmenuIndexEmulate, nfc_scene_card_menu_submenu_callback, nfc);
     submenu_add_item(
     submenu_add_item(
         submenu, "Name and save UID", SubmenuIndexSave, nfc_scene_card_menu_submenu_callback, nfc);
         submenu, "Name and save UID", SubmenuIndexSave, nfc_scene_card_menu_submenu_callback, nfc);
+    submenu_set_selected_item(
+        nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneCardMenu));
 
 
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
 }
 }
 
 
-const bool nfc_scene_card_menu_on_event(void* context, uint32_t event) {
+const bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SubmenuIndexRunApp) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexChooseScript) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexEmulate) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_emulate_uid);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexSave) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_save_name);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == ViewNavigatorEventBack) {
-        view_dispatcher_send_back_search_scene_event(
-            nfc->nfc_common.view_dispatcher, NfcSceneStart);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexRunApp) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexRunApp);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
+            return true;
+        } else if(event.event == SubmenuIndexChooseScript) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexChooseScript);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
+            return true;
+        } else if(event.event == SubmenuIndexEmulate) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexEmulate);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
+            return true;
+        } else if(event.event == SubmenuIndexSave) {
+            scene_manager_set_scene_state(nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexSave);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
+            return true;
+        }
+    } else if(event.type == SceneManagerEventTypeNavigation) {
+        return scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
     }
     }
 
 
     return false;
     return false;
@@ -79,17 +75,3 @@ const void nfc_scene_card_menu_on_exit(void* context) {
 
 
     submenu_clean(nfc->submenu);
     submenu_clean(nfc->submenu);
 }
 }
-
-AppScene* nfc_scene_card_menu_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneCardMenu;
-    scene->on_enter = nfc_scene_card_menu_on_enter;
-    scene->on_event = nfc_scene_card_menu_on_event;
-    scene->on_exit = nfc_scene_card_menu_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_card_menu_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_card_menu.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_card_menu_alloc();
-
-void nfc_scene_card_menu_free(AppScene* scene);

+ 23 - 0
applications/nfc/scenes/nfc_scene_config.h

@@ -0,0 +1,23 @@
+ADD_SCENE(nfc, start, Start)
+ADD_SCENE(nfc, read_card, ReadCard)
+ADD_SCENE(nfc, read_card_success, ReadCardSuccess)
+ADD_SCENE(nfc, card_menu, CardMenu)
+ADD_SCENE(nfc, not_implemented, NotImplemented)
+ADD_SCENE(nfc, emulate_uid, EmulateUid)
+ADD_SCENE(nfc, save_name, SaveName)
+ADD_SCENE(nfc, save_success, SaveSuccess)
+ADD_SCENE(nfc, file_select, FileSelect)
+ADD_SCENE(nfc, saved_menu, SavedMenu)
+ADD_SCENE(nfc, set_type, SetType)
+ADD_SCENE(nfc, set_sak, SetSak)
+ADD_SCENE(nfc, set_atqa, SetAtqua)
+ADD_SCENE(nfc, set_uid, SetUid)
+ADD_SCENE(nfc, scripts_menu, ScriptsMenu)
+ADD_SCENE(nfc, read_mifare_ul, ReadMifareUl)
+ADD_SCENE(nfc, read_mifare_ul_success, ReadMifareUlSuccess)
+ADD_SCENE(nfc, mifare_ul_menu, MifareUlMenu)
+ADD_SCENE(nfc, debug_menu, DebugMenu)
+ADD_SCENE(nfc, debug_detect, DebugDetect)
+ADD_SCENE(nfc, debug_emulate, DebugEmulate)
+ADD_SCENE(nfc, debug_read_emv, DebugReadEmv)
+ADD_SCENE(nfc, debug_read_mifare_ul, DebugReadMifareUl)

+ 1 - 18
applications/nfc/scenes/nfc_scene_debug_detect.c

@@ -1,31 +1,14 @@
-#include "nfc_scene_debug_detect.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-
 const void nfc_scene_debug_detect_on_enter(void* context) {
 const void nfc_scene_debug_detect_on_enter(void* context) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDetect);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDetect);
 }
 }
 
 
-const bool nfc_scene_debug_detect_on_event(void* context, uint32_t event) {
+const bool nfc_scene_debug_detect_on_event(void* context, SceneManagerEvent event) {
     return false;
     return false;
 }
 }
 
 
 const void nfc_scene_debug_detect_on_exit(void* context) {
 const void nfc_scene_debug_detect_on_exit(void* context) {
 }
 }
-
-AppScene* nfc_scene_debug_detect_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneDebugDetect;
-    scene->on_enter = nfc_scene_debug_detect_on_enter;
-    scene->on_event = nfc_scene_debug_detect_on_event;
-    scene->on_exit = nfc_scene_debug_detect_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_debug_detect_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_debug_detect.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_debug_detect_alloc();
-
-void nfc_scene_debug_detect_free(AppScene* scene);

+ 1 - 18
applications/nfc/scenes/nfc_scene_debug_emulate.c

@@ -1,31 +1,14 @@
-#include "nfc_scene_debug_emulate.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-
 const void nfc_scene_debug_emulate_on_enter(void* context) {
 const void nfc_scene_debug_emulate_on_enter(void* context) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewEmulate);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewEmulate);
 }
 }
 
 
-const bool nfc_scene_debug_emulate_on_event(void* context, uint32_t event) {
+const bool nfc_scene_debug_emulate_on_event(void* context, SceneManagerEvent event) {
     return false;
     return false;
 }
 }
 
 
 const void nfc_scene_debug_emulate_on_exit(void* context) {
 const void nfc_scene_debug_emulate_on_exit(void* context) {
 }
 }
-
-AppScene* nfc_scene_debug_emulate_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneDebugEmulate;
-    scene->on_enter = nfc_scene_debug_emulate_on_enter;
-    scene->on_event = nfc_scene_debug_emulate_on_event;
-    scene->on_exit = nfc_scene_debug_emulate_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_debug_emulate_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_debug_emulate.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_debug_emulate_alloc();
-
-void nfc_scene_debug_emulate_free(AppScene* scene);

+ 25 - 41
applications/nfc/scenes/nfc_scene_debug_menu.c

@@ -1,10 +1,5 @@
-#include "nfc_scene_debug_menu.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-#include <gui/modules/submenu.h>
-#include <gui/view_dispatcher.h>
-
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexDetect,
     SubmenuIndexDetect,
     SubmenuIndexEmulate,
     SubmenuIndexEmulate,
@@ -34,34 +29,37 @@ const void nfc_scene_debug_menu_on_enter(void* context) {
         SubmenuIndexReadMifareUl,
         SubmenuIndexReadMifareUl,
         nfc_scene_debug_menu_submenu_callback,
         nfc_scene_debug_menu_submenu_callback,
         nfc);
         nfc);
+    submenu_set_selected_item(
+        nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDebugMenu));
 
 
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
 }
 }
 
 
-const bool nfc_scene_debug_menu_on_event(void* context, uint32_t event) {
+const bool nfc_scene_debug_menu_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SubmenuIndexDetect) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_debug_detect);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexEmulate) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_debug_emulate);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexReadEmv) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_debug_read_emv);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexReadMifareUl) {
-        view_dispatcher_add_scene(
-            nfc->nfc_common.view_dispatcher, nfc->scene_debug_read_mifare_ul);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexDetect) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneDebugMenu, SubmenuIndexDetect);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugDetect);
+            return true;
+        } else if(event.event == SubmenuIndexEmulate) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneDebugMenu, SubmenuIndexEmulate);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugEmulate);
+            return true;
+        } else if(event.event == SubmenuIndexReadEmv) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneDebugMenu, SubmenuIndexReadEmv);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugReadEmv);
+            return true;
+        } else if(event.event == SubmenuIndexReadMifareUl) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneDebugMenu, SubmenuIndexReadMifareUl);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugReadMifareUl);
+            return true;
+        }
     }
     }
 
 
     return false;
     return false;
@@ -72,17 +70,3 @@ const void nfc_scene_debug_menu_on_exit(void* context) {
 
 
     submenu_clean(nfc->submenu);
     submenu_clean(nfc->submenu);
 }
 }
-
-AppScene* nfc_scene_debug_menu_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneDebugMenu;
-    scene->on_enter = nfc_scene_debug_menu_on_enter;
-    scene->on_event = nfc_scene_debug_menu_on_event;
-    scene->on_exit = nfc_scene_debug_menu_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_debug_menu_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_debug_menu.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_debug_menu_alloc();
-
-void nfc_scene_debug_menu_free(AppScene* scene);

+ 1 - 18
applications/nfc/scenes/nfc_scene_debug_read_emv.c

@@ -1,31 +1,14 @@
-#include "nfc_scene_debug_read_emv.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-
 const void nfc_scene_debug_read_emv_on_enter(void* context) {
 const void nfc_scene_debug_read_emv_on_enter(void* context) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewEmv);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewEmv);
 }
 }
 
 
-const bool nfc_scene_debug_read_emv_on_event(void* context, uint32_t event) {
+const bool nfc_scene_debug_read_emv_on_event(void* context, SceneManagerEvent event) {
     return false;
     return false;
 }
 }
 
 
 const void nfc_scene_debug_read_emv_on_exit(void* context) {
 const void nfc_scene_debug_read_emv_on_exit(void* context) {
 }
 }
-
-AppScene* nfc_scene_debug_read_emv_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneDebugReadEmv;
-    scene->on_enter = nfc_scene_debug_read_emv_on_enter;
-    scene->on_event = nfc_scene_debug_read_emv_on_event;
-    scene->on_exit = nfc_scene_debug_read_emv_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_debug_read_emv_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_debug_read_emv.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_debug_read_emv_alloc();
-
-void nfc_scene_debug_read_emv_free(AppScene* scene);

+ 1 - 18
applications/nfc/scenes/nfc_scene_debug_read_mifare_ul.c

@@ -1,31 +1,14 @@
-#include "nfc_scene_debug_read_mifare_ul.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-
 const void nfc_scene_debug_read_mifare_ul_on_enter(void* context) {
 const void nfc_scene_debug_read_mifare_ul_on_enter(void* context) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMifareUl);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMifareUl);
 }
 }
 
 
-const bool nfc_scene_debug_read_mifare_ul_on_event(void* context, uint32_t event) {
+const bool nfc_scene_debug_read_mifare_ul_on_event(void* context, SceneManagerEvent event) {
     return false;
     return false;
 }
 }
 
 
 const void nfc_scene_debug_read_mifare_ul_on_exit(void* context) {
 const void nfc_scene_debug_read_mifare_ul_on_exit(void* context) {
 }
 }
-
-AppScene* nfc_scene_debug_read_mifare_ul_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneDebugReadMifareUl;
-    scene->on_enter = nfc_scene_debug_read_mifare_ul_on_enter;
-    scene->on_event = nfc_scene_debug_read_mifare_ul_on_event;
-    scene->on_exit = nfc_scene_debug_read_mifare_ul_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_debug_read_mifare_ul_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_debug_read_mifare_ul.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_debug_read_mifare_ul_alloc();
-
-void nfc_scene_debug_read_mifare_ul_free(AppScene* scene);

+ 10 - 22
applications/nfc/scenes/nfc_scene_emulate_uid.c

@@ -1,7 +1,3 @@
-#include <nfc/scenes/nfc_scene_emulate_uid.h>
-
-#include <furi.h>
-
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
 const void nfc_scene_emulate_uid_on_enter(void* context) {
 const void nfc_scene_emulate_uid_on_enter(void* context) {
@@ -12,12 +8,12 @@ const void nfc_scene_emulate_uid_on_enter(void* context) {
     NfcDeviceData* data = &nfc->device.data;
     NfcDeviceData* data = &nfc->device.data;
 
 
     if(strcmp(nfc->device.dev_name, "")) {
     if(strcmp(nfc->device.dev_name, "")) {
-        nfc_set_text_store(nfc, "%s", nfc->device.dev_name);
+        nfc_text_store_set(nfc, "%s", nfc->device.dev_name);
     } else if(data->uid_len == 4) {
     } else if(data->uid_len == 4) {
-        nfc_set_text_store(
+        nfc_text_store_set(
             nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]);
             nfc, "%02X %02X %02X %02X", data->uid[0], data->uid[1], data->uid[2], data->uid[3]);
     } else if(data->uid_len == 7) {
     } else if(data->uid_len == 7) {
-        nfc_set_text_store(
+        nfc_text_store_set(
             nfc,
             nfc,
             "%02X %02X %02X %02X\n%02X %02X %02X",
             "%02X %02X %02X %02X\n%02X %02X %02X",
             data->uid[0],
             data->uid[0],
@@ -41,7 +37,13 @@ const void nfc_scene_emulate_uid_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
 }
 }
 
 
-const bool nfc_scene_emulate_uid_on_event(void* context, uint32_t event) {
+const bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) {
+    Nfc* nfc = (Nfc*)context;
+
+    if(event.type == SceneManagerEventTypeTick) {
+        notification_message(nfc->notifications, &sequence_blink_blue_10);
+        return true;
+    }
     return false;
     return false;
 }
 }
 
 
@@ -57,17 +59,3 @@ const void nfc_scene_emulate_uid_on_exit(void* context) {
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
     popup_set_icon(popup, 0, 0, NULL);
     popup_set_icon(popup, 0, 0, NULL);
 }
 }
-
-AppScene* nfc_scene_emulate_uid_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneEmulateUID;
-    scene->on_enter = nfc_scene_emulate_uid_on_enter;
-    scene->on_event = nfc_scene_emulate_uid_on_event;
-    scene->on_exit = nfc_scene_emulate_uid_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_emulate_uid_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_emulate_uid.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_emulate_uid_alloc();
-
-void nfc_scene_emulate_uid_free(AppScene* scene);

+ 3 - 24
applications/nfc/scenes/nfc_scene_file_select.c

@@ -1,39 +1,18 @@
-#include <nfc/scenes/nfc_scene_file_select.h>
-
-#include <furi.h>
-
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
 const void nfc_scene_file_select_on_enter(void* context) {
 const void nfc_scene_file_select_on_enter(void* context) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
     // Process file_select return
     // Process file_select return
     if(nfc_file_select(&nfc->device)) {
     if(nfc_file_select(&nfc->device)) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_saved_menu);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
+        scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
     } else {
     } else {
-        view_dispatcher_send_back_search_scene_event(
-            nfc->nfc_common.view_dispatcher, NfcSceneStart);
+        scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
     }
     }
 }
 }
 
 
-const bool nfc_scene_file_select_on_event(void* context, uint32_t event) {
+const bool nfc_scene_file_select_on_event(void* context, SceneManagerEvent event) {
     return false;
     return false;
 }
 }
 
 
 const void nfc_scene_file_select_on_exit(void* context) {
 const void nfc_scene_file_select_on_exit(void* context) {
 }
 }
-
-AppScene* nfc_scene_file_select_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneFileSelect;
-    scene->on_enter = nfc_scene_file_select_on_enter;
-    scene->on_event = nfc_scene_file_select_on_event;
-    scene->on_exit = nfc_scene_file_select_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_file_select_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_file_select.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_file_select_alloc();
-
-void nfc_scene_file_select_free(AppScene* scene);

+ 17 - 32
applications/nfc/scenes/nfc_scene_mifare_ul_menu.c

@@ -1,8 +1,5 @@
-#include "nfc_scene_mifare_ul_menu.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexSave,
     SubmenuIndexSave,
     SubmenuIndexEmulate,
     SubmenuIndexEmulate,
@@ -22,27 +19,29 @@ const void nfc_scene_mifare_ul_menu_on_enter(void* context) {
         submenu, "Name and save", SubmenuIndexSave, nfc_scene_mifare_ul_menu_submenu_callback, nfc);
         submenu, "Name and save", SubmenuIndexSave, nfc_scene_mifare_ul_menu_submenu_callback, nfc);
     submenu_add_item(
     submenu_add_item(
         submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_mifare_ul_menu_submenu_callback, nfc);
         submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_mifare_ul_menu_submenu_callback, nfc);
+    submenu_set_selected_item(
+        nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareUlMenu));
 
 
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
 }
 }
 
 
-const bool nfc_scene_mifare_ul_menu_on_event(void* context, uint32_t event) {
+const bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SubmenuIndexSave) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexEmulate) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == ViewNavigatorEventBack) {
-        view_dispatcher_send_back_search_scene_event(
-            nfc->nfc_common.view_dispatcher, NfcSceneStart);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexSave) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
+            return true;
+        } else if(event.event == SubmenuIndexEmulate) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexEmulate);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
+            return true;
+        }
+    } else if(event.type == SceneManagerEventTypeNavigation) {
+        return scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
     }
     }
 
 
     return false;
     return false;
@@ -53,17 +52,3 @@ const void nfc_scene_mifare_ul_menu_on_exit(void* context) {
 
 
     submenu_clean(nfc->submenu);
     submenu_clean(nfc->submenu);
 }
 }
-
-AppScene* nfc_scene_mifare_ul_menu_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneReadMifareUlMenu;
-    scene->on_enter = nfc_scene_mifare_ul_menu_on_enter;
-    scene->on_event = nfc_scene_mifare_ul_menu_on_event;
-    scene->on_exit = nfc_scene_mifare_ul_menu_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_mifare_ul_menu_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_mifare_ul_menu.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_mifare_ul_menu_alloc();
-
-void nfc_scene_mifare_ul_menu_free(AppScene* scene);

+ 5 - 24
applications/nfc/scenes/nfc_scene_not_implemented.c

@@ -1,10 +1,5 @@
-#include "nfc_scene_not_implemented.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-#include <gui/modules/dialog_ex.h>
-#include <gui/view_dispatcher.h>
-
 void nfc_scene_not_implemented_dialog_callback(DialogExResult result, void* context) {
 void nfc_scene_not_implemented_dialog_callback(DialogExResult result, void* context) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
@@ -24,13 +19,13 @@ const void nfc_scene_not_implemented_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
 }
 }
 
 
-const bool nfc_scene_not_implemented_on_event(void* context, uint32_t event) {
+const bool nfc_scene_not_implemented_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == DialogExResultLeft) {
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventBack);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == DialogExResultLeft) {
+            return scene_manager_previous_scene(nfc->scene_manager);
+        }
     }
     }
     return false;
     return false;
 }
 }
@@ -45,17 +40,3 @@ const void nfc_scene_not_implemented_on_exit(void* context) {
     dialog_ex_set_result_callback(dialog_ex, NULL);
     dialog_ex_set_result_callback(dialog_ex, NULL);
     dialog_ex_set_context(dialog_ex, NULL);
     dialog_ex_set_context(dialog_ex, NULL);
 }
 }
-
-AppScene* nfc_scene_not_implemented_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneReadCardSuccess;
-    scene->on_enter = nfc_scene_not_implemented_on_enter;
-    scene->on_event = nfc_scene_not_implemented_on_event;
-    scene->on_exit = nfc_scene_not_implemented_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_not_implemented_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_not_implemented.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_not_implemented_alloc();
-
-void nfc_scene_not_implemented_free(AppScene* scene);

+ 9 - 27
applications/nfc/scenes/nfc_scene_read_card.c

@@ -1,11 +1,4 @@
-#include <nfc/scenes/nfc_scene_read_card.h>
-
-#include <furi.h>
-
 #include "../nfc_i.h"
 #include "../nfc_i.h"
-#include "../views/nfc_detect.h"
-
-#include <gui/view_dispatcher.h>
 
 
 void nfc_read_card_worker_callback(void* context) {
 void nfc_read_card_worker_callback(void* context) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
@@ -30,14 +23,17 @@ const void nfc_scene_read_card_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
 }
 }
 
 
-const bool nfc_scene_read_card_on_event(void* context, uint32_t event) {
+const bool nfc_scene_read_card_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == NfcEventDetect) {
-        nfc->device.data = nfc->nfc_common.worker_result.nfc_detect_data;
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_read_card_success);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == NfcEventDetect) {
+            nfc->device.data = nfc->nfc_common.worker_result.nfc_detect_data;
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess);
+            return true;
+        }
+    } else if(event.type == SceneManagerEventTypeTick) {
+        notification_message(nfc->notifications, &sequence_blink_blue_10);
         return true;
         return true;
     }
     }
     return false;
     return false;
@@ -55,17 +51,3 @@ const void nfc_scene_read_card_on_exit(void* context) {
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
     popup_set_icon(popup, 0, 0, NULL);
     popup_set_icon(popup, 0, 0, NULL);
 }
 }
-
-AppScene* nfc_scene_read_card_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneReadCard;
-    scene->on_enter = nfc_scene_read_card_on_enter;
-    scene->on_event = nfc_scene_read_card_on_event;
-    scene->on_exit = nfc_scene_read_card_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_read_card_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_read_card.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_read_card_alloc();
-
-void nfc_scene_read_card_free(AppScene* scene);

+ 10 - 31
applications/nfc/scenes/nfc_scene_read_card_success.c

@@ -1,10 +1,5 @@
-#include "nfc_scene_read_card_success.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-#include <gui/modules/dialog_ex.h>
-#include <gui/view_dispatcher.h>
-
 #define NFC_SCENE_READ_SUCCESS_SHIFT "              "
 #define NFC_SCENE_READ_SUCCESS_SHIFT "              "
 
 
 void nfc_scene_read_card_success_dialog_callback(DialogExResult result, void* context) {
 void nfc_scene_read_card_success_dialog_callback(DialogExResult result, void* context) {
@@ -31,7 +26,7 @@ const void nfc_scene_read_card_success_on_enter(void* context) {
     dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21);
     dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21);
     // Display UID
     // Display UID
     if(data->uid_len == 4) {
     if(data->uid_len == 4) {
-        nfc_set_text_store(
+        nfc_text_store_set(
             nfc,
             nfc,
             NFC_SCENE_READ_SUCCESS_SHIFT "%s\n" NFC_SCENE_READ_SUCCESS_SHIFT
             NFC_SCENE_READ_SUCCESS_SHIFT "%s\n" NFC_SCENE_READ_SUCCESS_SHIFT
                                          "ATQA: %02X%02X SAK: %02X\nUID: %02X %02X %02X %02X",
                                          "ATQA: %02X%02X SAK: %02X\nUID: %02X %02X %02X %02X",
@@ -44,7 +39,7 @@ const void nfc_scene_read_card_success_on_enter(void* context) {
             data->uid[2],
             data->uid[2],
             data->uid[3]);
             data->uid[3]);
     } else if(data->uid_len == 7) {
     } else if(data->uid_len == 7) {
-        nfc_set_text_store(
+        nfc_text_store_set(
             nfc,
             nfc,
             NFC_SCENE_READ_SUCCESS_SHIFT
             NFC_SCENE_READ_SUCCESS_SHIFT
             "%s\n" NFC_SCENE_READ_SUCCESS_SHIFT
             "%s\n" NFC_SCENE_READ_SUCCESS_SHIFT
@@ -68,18 +63,16 @@ const void nfc_scene_read_card_success_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
 }
 }
 
 
-const bool nfc_scene_read_card_success_on_event(void* context, uint32_t event) {
+const bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == DialogExResultLeft) {
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventBack);
-        return true;
-    } else if(event == DialogExResultRight) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_card_menu);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == DialogExResultLeft) {
+            return scene_manager_previous_scene(nfc->scene_manager);
+        } else if(event.event == DialogExResultRight) {
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneCardMenu);
+            return true;
+        }
     }
     }
     return false;
     return false;
 }
 }
@@ -96,17 +89,3 @@ const void nfc_scene_read_card_success_on_exit(void* context) {
     dialog_ex_set_result_callback(dialog_ex, NULL);
     dialog_ex_set_result_callback(dialog_ex, NULL);
     dialog_ex_set_context(dialog_ex, NULL);
     dialog_ex_set_context(dialog_ex, NULL);
 }
 }
-
-AppScene* nfc_scene_read_card_success_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneReadCardSuccess;
-    scene->on_enter = nfc_scene_read_card_success_on_enter;
-    scene->on_event = nfc_scene_read_card_success_on_event;
-    scene->on_exit = nfc_scene_read_card_success_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_read_card_success_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_read_card_success.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_read_card_success_alloc();
-
-void nfc_scene_read_card_success_free(AppScene* scene);

+ 9 - 23
applications/nfc/scenes/nfc_scene_read_mifare_ul.c

@@ -1,5 +1,3 @@
-#include <nfc/scenes/nfc_scene_read_mifare_ul.h>
-#include <furi.h>
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
 void nfc_read_mifare_ul_worker_callback(void* context) {
 void nfc_read_mifare_ul_worker_callback(void* context) {
@@ -25,15 +23,17 @@ const void nfc_scene_read_mifare_ul_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
 }
 }
 
 
-const bool nfc_scene_read_mifare_ul_on_event(void* context, uint32_t event) {
+const bool nfc_scene_read_mifare_ul_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == NfcEventMifareUl) {
-        nfc->device.data = nfc->nfc_common.worker_result.nfc_detect_data;
-        view_dispatcher_add_scene(
-            nfc->nfc_common.view_dispatcher, nfc->scene_read_mifare_ul_success);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == NfcEventMifareUl) {
+            nfc->device.data = nfc->nfc_common.worker_result.nfc_detect_data;
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUlSuccess);
+            return true;
+        }
+    } else if(event.type == SceneManagerEventTypeTick) {
+        notification_message(nfc->notifications, &sequence_blink_blue_10);
         return true;
         return true;
     }
     }
     return false;
     return false;
@@ -51,17 +51,3 @@ const void nfc_scene_read_mifare_ul_on_exit(void* context) {
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
     popup_set_icon(popup, 0, 0, NULL);
     popup_set_icon(popup, 0, 0, NULL);
 }
 }
-
-AppScene* nfc_scene_read_mifare_ul_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneReadMifareUl;
-    scene->on_enter = nfc_scene_read_mifare_ul_on_enter;
-    scene->on_event = nfc_scene_read_mifare_ul_on_event;
-    scene->on_exit = nfc_scene_read_mifare_ul_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_read_mifare_ul_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_read_mifare_ul.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_read_mifare_ul_alloc();
-
-void nfc_scene_read_mifare_ul_free(AppScene* scene);

+ 33 - 46
applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c

@@ -1,10 +1,5 @@
-#include "nfc_scene_read_mifare_ul_success.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-#include <gui/modules/dialog_ex.h>
-#include <gui/view_dispatcher.h>
-
 #define NFC_SCENE_READ_SUCCESS_SHIFT "              "
 #define NFC_SCENE_READ_SUCCESS_SHIFT "              "
 #define NFC_SCENE_READ_MF_UL_CUSTOM_EVENT (0UL)
 #define NFC_SCENE_READ_MF_UL_CUSTOM_EVENT (0UL)
 
 
@@ -45,7 +40,7 @@ const void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
     dialog_ex_set_header(dialog_ex, "Mifare Ultralight", 22, 8, AlignLeft, AlignCenter);
     dialog_ex_set_header(dialog_ex, "Mifare Ultralight", 22, 8, AlignLeft, AlignCenter);
     dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21);
     dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21);
     // Display UID
     // Display UID
-    nfc_set_text_store(
+    nfc_text_store_set(
         nfc,
         nfc,
         NFC_SCENE_READ_SUCCESS_SHIFT "ATQA: %02X%02X\n" NFC_SCENE_READ_SUCCESS_SHIFT
         NFC_SCENE_READ_SUCCESS_SHIFT "ATQA: %02X%02X\n" NFC_SCENE_READ_SUCCESS_SHIFT
                                      "SAK: %02X\nUID: %02X %02X %02X %02X %02X %02X %02X",
                                      "SAK: %02X\nUID: %02X %02X %02X %02X %02X %02X %02X",
@@ -82,37 +77,43 @@ const void nfc_scene_read_mifare_ul_success_on_enter(void* context) {
     }
     }
     text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
     text_box_set_text(text_box, string_get_cstr(nfc->text_box_store));
 
 
-    nfc->scene_read_mifare_ul_success->state = ReadMifareUlStateShowUID;
+    scene_manager_set_scene_state(
+        nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowUID);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
 }
 }
 
 
-const bool nfc_scene_read_mifare_ul_success_on_event(void* context, uint32_t event) {
+const bool nfc_scene_read_mifare_ul_success_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if((nfc->scene_read_mifare_ul_success->state == ReadMifareUlStateShowUID) &&
-       (event == DialogExResultLeft)) {
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventBack);
-        return true;
-    } else if(
-        (nfc->scene_read_mifare_ul_success->state == ReadMifareUlStateShowUID) &&
-        (event == DialogExResultRight)) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_mifare_ul_menu);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(
-        (nfc->scene_read_mifare_ul_success->state == ReadMifareUlStateShowUID) &&
-        (event == DialogExResultCenter)) {
-        view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewTextBox);
-        nfc->scene_read_mifare_ul_success->state = ReadMifareUlStateShowData;
-        return true;
-    } else if(
-        (nfc->scene_read_mifare_ul_success->state == ReadMifareUlStateShowData) &&
-        (event == NFC_SCENE_READ_MF_UL_CUSTOM_EVENT)) {
-        view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
-        nfc->scene_read_mifare_ul_success->state = ReadMifareUlStateShowUID;
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if((scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) ==
+            ReadMifareUlStateShowUID) &&
+           (event.event == DialogExResultLeft)) {
+            scene_manager_previous_scene(nfc->scene_manager);
+            return true;
+        } else if(
+            (scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) ==
+             ReadMifareUlStateShowUID) &&
+            (event.event == DialogExResultRight)) {
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareUlMenu);
+            return true;
+        } else if(
+            (scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) ==
+             ReadMifareUlStateShowUID) &&
+            (event.event == DialogExResultCenter)) {
+            view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewTextBox);
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowData);
+            return true;
+        } else if(
+            (scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess) ==
+             ReadMifareUlStateShowData) &&
+            (event.event == NFC_SCENE_READ_MF_UL_CUSTOM_EVENT)) {
+            view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewDialogEx);
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowUID);
+            return true;
+        }
     }
     }
     return false;
     return false;
 }
 }
@@ -136,17 +137,3 @@ const void nfc_scene_read_mifare_ul_success_on_exit(void* context) {
     text_box_clean(text_box);
     text_box_clean(text_box);
     string_clean(nfc->text_box_store);
     string_clean(nfc->text_box_store);
 }
 }
-
-AppScene* nfc_scene_read_mifare_ul_success_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneReadMifareUlSuccess;
-    scene->on_enter = nfc_scene_read_mifare_ul_success_on_enter;
-    scene->on_event = nfc_scene_read_mifare_ul_success_on_event;
-    scene->on_exit = nfc_scene_read_mifare_ul_success_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_read_mifare_ul_success_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_read_mifare_ul_success.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_read_mifare_ul_success_alloc();
-
-void nfc_scene_read_mifare_ul_success_free(AppScene* scene);

+ 11 - 33
applications/nfc/scenes/nfc_scene_save_name.c

@@ -1,11 +1,4 @@
-#include <nfc/scenes/nfc_scene_save_name.h>
-
-#include <furi.h>
-
 #include "../nfc_i.h"
 #include "../nfc_i.h"
-#include "../views/nfc_detect.h"
-
-#include <gui/view_dispatcher.h>
 
 
 #define SCENE_SAVE_NAME_CUSTOM_EVENT (0UL)
 #define SCENE_SAVE_NAME_CUSTOM_EVENT (0UL)
 
 
@@ -21,7 +14,7 @@ const void nfc_scene_save_name_on_enter(void* context) {
 
 
     // Setup view
     // Setup view
     TextInput* text_input = nfc->text_input;
     TextInput* text_input = nfc->text_input;
-    nfc_set_text_store(nfc, "");
+    nfc_text_store_clear(nfc);
     text_input_set_header_text(text_input, "Name the card");
     text_input_set_header_text(text_input, "Name the card");
     text_input_set_result_callback(
     text_input_set_result_callback(
         text_input,
         text_input,
@@ -32,20 +25,19 @@ const void nfc_scene_save_name_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewTextInput);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewTextInput);
 }
 }
 
 
-const bool nfc_scene_save_name_on_event(void* context, uint32_t event) {
+const bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SCENE_SAVE_NAME_CUSTOM_EVENT) {
-        memcpy(&nfc->device.dev_name, nfc->text_store, strlen(nfc->text_store));
-        if(nfc_device_save(&nfc->device, "test")) {
-            view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_save_success);
-            view_dispatcher_send_navigation_event(
-                nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        } else {
-            view_dispatcher_send_back_search_scene_event(
-                nfc->nfc_common.view_dispatcher, NfcSceneStart);
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) {
+            memcpy(&nfc->device.dev_name, nfc->text_store, strlen(nfc->text_store));
+            if(nfc_device_save(&nfc->device, nfc->text_store)) {
+                scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
+                return true;
+            } else {
+                return scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
+            }
         }
         }
-        return true;
     }
     }
     return false;
     return false;
 }
 }
@@ -56,17 +48,3 @@ const void nfc_scene_save_name_on_exit(void* context) {
     // Clear view
     // Clear view
     text_input_set_header_text(nfc->text_input, NULL);
     text_input_set_header_text(nfc->text_input, NULL);
 }
 }
-
-AppScene* nfc_scene_save_name_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneSaveName;
-    scene->on_enter = nfc_scene_save_name_on_enter;
-    scene->on_event = nfc_scene_save_name_on_event;
-    scene->on_exit = nfc_scene_save_name_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_save_name_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_save_name.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_save_name_alloc();
-
-void nfc_scene_save_name_free(AppScene* scene);

+ 5 - 23
applications/nfc/scenes/nfc_scene_save_success.c

@@ -1,7 +1,3 @@
-#include <nfc/scenes/nfc_scene_save_success.h>
-
-#include <furi.h>
-
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
 #define SCENE_SAVE_SUCCESS_CUSTOM_EVENT (0UL)
 #define SCENE_SAVE_SUCCESS_CUSTOM_EVENT (0UL)
@@ -26,13 +22,13 @@ const void nfc_scene_save_success_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewPopup);
 }
 }
 
 
-const bool nfc_scene_save_success_on_event(void* context, uint32_t event) {
+const bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) {
-        view_dispatcher_send_back_search_scene_event(
-            nfc->nfc_common.view_dispatcher, NfcSceneStart);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) {
+            return scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
+        }
     }
     }
     return false;
     return false;
 }
 }
@@ -50,17 +46,3 @@ const void nfc_scene_save_success_on_exit(void* context) {
     popup_set_timeout(popup, 0);
     popup_set_timeout(popup, 0);
     popup_disable_timeout(popup);
     popup_disable_timeout(popup);
 }
 }
-
-AppScene* nfc_scene_save_success_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneSaveSuccess;
-    scene->on_enter = nfc_scene_save_success_on_enter;
-    scene->on_event = nfc_scene_save_success_on_event;
-    scene->on_exit = nfc_scene_save_success_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_save_success_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_save_success.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_save_success_alloc();
-
-void nfc_scene_save_success_free(AppScene* scene);

+ 23 - 40
applications/nfc/scenes/nfc_scene_saved_menu.c

@@ -1,10 +1,5 @@
-#include "nfc_scene_saved_menu.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-#include <gui/modules/submenu.h>
-#include <gui/view_dispatcher.h>
-
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexEmulate,
     SubmenuIndexEmulate,
     SubmenuIndexEdit,
     SubmenuIndexEdit,
@@ -30,33 +25,35 @@ const void nfc_scene_saved_menu_on_enter(void* context) {
         submenu, "Delete", SubmenuIndexDelete, nfc_scene_saved_menu_submenu_callback, nfc);
         submenu, "Delete", SubmenuIndexDelete, nfc_scene_saved_menu_submenu_callback, nfc);
     submenu_add_item(
     submenu_add_item(
         submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
         submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
+    submenu_set_selected_item(
+        nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu));
 
 
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
 }
 }
 
 
-const bool nfc_scene_saved_menu_on_event(void* context, uint32_t event) {
+const bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SubmenuIndexEmulate) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_emulate_uid);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexEdit) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexDelete) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexInfo) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexEmulate) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexEmulate);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid);
+            return true;
+        } else if(event.event == SubmenuIndexEdit) {
+            scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexEdit);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
+            return true;
+        } else if(event.event == SubmenuIndexDelete) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexDelete);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
+            return true;
+        } else if(event.event == SubmenuIndexInfo) {
+            scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, SubmenuIndexInfo);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
+            return true;
+        }
     }
     }
 
 
     return false;
     return false;
@@ -67,17 +64,3 @@ const void nfc_scene_saved_menu_on_exit(void* context) {
 
 
     submenu_clean(nfc->submenu);
     submenu_clean(nfc->submenu);
 }
 }
-
-AppScene* nfc_scene_saved_menu_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneSavedMenu;
-    scene->on_enter = nfc_scene_saved_menu_on_enter;
-    scene->on_event = nfc_scene_saved_menu_on_event;
-    scene->on_exit = nfc_scene_saved_menu_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_saved_menu_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_saved_menu.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_saved_menu_alloc();
-
-void nfc_scene_saved_menu_free(AppScene* scene);

+ 15 - 31
applications/nfc/scenes/nfc_scene_scripts_menu.c

@@ -1,10 +1,5 @@
-#include "nfc_scene_scripts_menu.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-#include <gui/modules/submenu.h>
-#include <gui/view_dispatcher.h>
-
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexBankCard,
     SubmenuIndexBankCard,
     SubmenuIndexMifareUltralight,
     SubmenuIndexMifareUltralight,
@@ -32,23 +27,26 @@ const void nfc_scene_scripts_menu_on_enter(void* context) {
         SubmenuIndexMifareUltralight,
         SubmenuIndexMifareUltralight,
         nfc_scene_scripts_menu_submenu_callback,
         nfc_scene_scripts_menu_submenu_callback,
         nfc);
         nfc);
-
+    submenu_set_selected_item(
+        nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneScriptsMenu));
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
 }
 }
 
 
-const bool nfc_scene_scripts_menu_on_event(void* context, uint32_t event) {
+const bool nfc_scene_scripts_menu_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SubmenuIndexBankCard) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_not_implemented);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexMifareUltralight) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_read_mifare_ul);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexBankCard) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIndexBankCard);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneNotImplemented);
+            return true;
+        } else if(event.event == SubmenuIndexMifareUltralight) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIndexMifareUltralight);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl);
+            return true;
+        }
     }
     }
 
 
     return false;
     return false;
@@ -59,17 +57,3 @@ const void nfc_scene_scripts_menu_on_exit(void* context) {
 
 
     submenu_clean(nfc->submenu);
     submenu_clean(nfc->submenu);
 }
 }
-
-AppScene* nfc_scene_scripts_menu_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneScriptsMenu;
-    scene->on_enter = nfc_scene_scripts_menu_on_enter;
-    scene->on_event = nfc_scene_scripts_menu_on_event;
-    scene->on_exit = nfc_scene_scripts_menu_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_scripts_menu_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_scripts_menu.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_scripts_menu_alloc();
-
-void nfc_scene_scripts_menu_free(AppScene* scene);

+ 6 - 26
applications/nfc/scenes/nfc_scene_set_atqa.c

@@ -1,11 +1,5 @@
-#include <nfc/scenes/nfc_scene_set_atqa.h>
-
-#include <furi.h>
-
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <gui/view_dispatcher.h>
-
 #define SCENE_SET_ATQA_CUSTOM_EVENT (0UL)
 #define SCENE_SET_ATQA_CUSTOM_EVENT (0UL)
 
 
 void nfc_scene_set_atqa_byte_input_callback(void* context) {
 void nfc_scene_set_atqa_byte_input_callback(void* context) {
@@ -26,14 +20,14 @@ const void nfc_scene_set_atqa_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
 }
 }
 
 
-const bool nfc_scene_set_atqa_on_event(void* context, uint32_t event) {
+const bool nfc_scene_set_atqa_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SCENE_SET_ATQA_CUSTOM_EVENT) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_uid);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SCENE_SET_ATQA_CUSTOM_EVENT) {
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneSetUid);
+            return true;
+        }
     }
     }
     return false;
     return false;
 }
 }
@@ -45,17 +39,3 @@ const void nfc_scene_set_atqa_on_exit(void* context) {
     byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0);
     byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0);
     byte_input_set_header_text(nfc->byte_input, "");
     byte_input_set_header_text(nfc->byte_input, "");
 }
 }
-
-AppScene* nfc_scene_set_atqa_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneSetAtqa;
-    scene->on_enter = nfc_scene_set_atqa_on_enter;
-    scene->on_event = nfc_scene_set_atqa_on_event;
-    scene->on_exit = nfc_scene_set_atqa_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_set_atqa_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_set_atqa.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_set_atqa_alloc();
-
-void nfc_scene_set_atqa_free(AppScene* scene);

+ 6 - 26
applications/nfc/scenes/nfc_scene_set_sak.c

@@ -1,11 +1,5 @@
-#include <nfc/scenes/nfc_scene_set_sak.h>
-
-#include <furi.h>
-
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <gui/view_dispatcher.h>
-
 #define SCENE_SET_SAK_CUSTOM_EVENT (0UL)
 #define SCENE_SET_SAK_CUSTOM_EVENT (0UL)
 
 
 void nfc_scene_set_sak_byte_input_callback(void* context) {
 void nfc_scene_set_sak_byte_input_callback(void* context) {
@@ -25,14 +19,14 @@ const void nfc_scene_set_sak_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
 }
 }
 
 
-const bool nfc_scene_set_sak_on_event(void* context, uint32_t event) {
+const bool nfc_scene_set_sak_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SCENE_SET_SAK_CUSTOM_EVENT) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_atqa);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SCENE_SET_SAK_CUSTOM_EVENT) {
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqua);
+            return true;
+        }
     }
     }
     return false;
     return false;
 }
 }
@@ -44,17 +38,3 @@ const void nfc_scene_set_sak_on_exit(void* context) {
     byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0);
     byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0);
     byte_input_set_header_text(nfc->byte_input, "");
     byte_input_set_header_text(nfc->byte_input, "");
 }
 }
-
-AppScene* nfc_scene_set_sak_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneSetSak;
-    scene->on_enter = nfc_scene_set_sak_on_enter;
-    scene->on_event = nfc_scene_set_sak_on_event;
-    scene->on_exit = nfc_scene_set_sak_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_set_sak_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_set_sak.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_set_sak_alloc();
-
-void nfc_scene_set_sak_free(AppScene* scene);

+ 11 - 32
applications/nfc/scenes/nfc_scene_set_type.c

@@ -1,10 +1,5 @@
-#include "nfc_scene_set_type.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-#include <gui/modules/submenu.h>
-#include <gui/view_dispatcher.h>
-
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexNFCA4,
     SubmenuIndexNFCA4,
     SubmenuIndexNFCA7,
     SubmenuIndexNFCA7,
@@ -27,21 +22,19 @@ const void nfc_scene_set_type_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
 }
 }
 
 
-const bool nfc_scene_set_type_on_event(void* context, uint32_t event) {
+const bool nfc_scene_set_type_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SubmenuIndexNFCA7) {
-        nfc->device.data.uid_len = 7;
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_sak);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexNFCA4) {
-        nfc->device.data.uid_len = 4;
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_sak);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexNFCA7) {
+            nfc->device.data.uid_len = 7;
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
+            return true;
+        } else if(event.event == SubmenuIndexNFCA4) {
+            nfc->device.data.uid_len = 4;
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneSetSak);
+            return true;
+        }
     }
     }
     return false;
     return false;
 }
 }
@@ -51,17 +44,3 @@ const void nfc_scene_set_type_on_exit(void* context) {
 
 
     submenu_clean(nfc->submenu);
     submenu_clean(nfc->submenu);
 }
 }
-
-AppScene* nfc_scene_set_type_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneSetType;
-    scene->on_enter = nfc_scene_set_type_on_enter;
-    scene->on_event = nfc_scene_set_type_on_event;
-    scene->on_exit = nfc_scene_set_type_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_set_type_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_set_type.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_set_type_alloc();
-
-void nfc_scene_set_type_free(AppScene* scene);

+ 6 - 26
applications/nfc/scenes/nfc_scene_set_uid.c

@@ -1,11 +1,5 @@
-#include <nfc/scenes/nfc_scene_set_uid.h>
-
-#include <furi.h>
-
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <gui/view_dispatcher.h>
-
 #define SCENE_SET_UID_CUSTOM_EVENT (0UL)
 #define SCENE_SET_UID_CUSTOM_EVENT (0UL)
 
 
 void nfc_scene_set_uid_byte_input_callback(void* context) {
 void nfc_scene_set_uid_byte_input_callback(void* context) {
@@ -30,14 +24,14 @@ const void nfc_scene_set_uid_on_enter(void* context) {
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewByteInput);
 }
 }
 
 
-const bool nfc_scene_set_uid_on_event(void* context, uint32_t event) {
+const bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SCENE_SET_UID_CUSTOM_EVENT) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_save_name);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SCENE_SET_UID_CUSTOM_EVENT) {
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
+            return true;
+        }
     }
     }
     return false;
     return false;
 }
 }
@@ -49,17 +43,3 @@ const void nfc_scene_set_uid_on_exit(void* context) {
     byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0);
     byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0);
     byte_input_set_header_text(nfc->byte_input, "");
     byte_input_set_header_text(nfc->byte_input, "");
 }
 }
-
-AppScene* nfc_scene_set_uid_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneSetUid;
-    scene->on_enter = nfc_scene_set_uid_on_enter;
-    scene->on_event = nfc_scene_set_uid_on_event;
-    scene->on_exit = nfc_scene_set_uid_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_set_uid_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_set_uid.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_set_uid_alloc();
-
-void nfc_scene_set_uid_free(AppScene* scene);

+ 27 - 44
applications/nfc/scenes/nfc_scene_start.c

@@ -1,10 +1,5 @@
-#include "nfc_scene_start.h"
 #include "../nfc_i.h"
 #include "../nfc_i.h"
 
 
-#include <furi.h>
-#include <gui/modules/submenu.h>
-#include <gui/view_dispatcher.h>
-
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexRead,
     SubmenuIndexRead,
     SubmenuIndexRunScript,
     SubmenuIndexRunScript,
@@ -36,37 +31,39 @@ const void nfc_scene_start_on_enter(void* context) {
     submenu_add_item(
     submenu_add_item(
         submenu, "Add manually", SubmenuIndexAddManualy, nfc_scene_start_submenu_callback, nfc);
         submenu, "Add manually", SubmenuIndexAddManualy, nfc_scene_start_submenu_callback, nfc);
     submenu_add_item(submenu, "Debug", SubmenuIndexDebug, nfc_scene_start_submenu_callback, nfc);
     submenu_add_item(submenu, "Debug", SubmenuIndexDebug, nfc_scene_start_submenu_callback, nfc);
+    submenu_set_selected_item(
+        submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneStart));
 
 
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
     view_dispatcher_switch_to_view(nfc->nfc_common.view_dispatcher, NfcViewMenu);
 }
 }
 
 
-const bool nfc_scene_start_on_event(void* context, uint32_t event) {
+const bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
     Nfc* nfc = (Nfc*)context;
 
 
-    if(event == SubmenuIndexRead) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_read_card);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexRunScript) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_scripts_menu);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexSaved) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_file_select);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexAddManualy) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_set_type);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
-        return true;
-    } else if(event == SubmenuIndexDebug) {
-        view_dispatcher_add_scene(nfc->nfc_common.view_dispatcher, nfc->scene_debug_menu);
-        view_dispatcher_send_navigation_event(
-            nfc->nfc_common.view_dispatcher, ViewNavigatorEventNext);
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexRead) {
+            scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexRead);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCard);
+            return true;
+        } else if(event.event == SubmenuIndexRunScript) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneStart, SubmenuIndexRunScript);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneScriptsMenu);
+            return true;
+        } else if(event.event == SubmenuIndexSaved) {
+            scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexSaved);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect);
+            return true;
+        } else if(event.event == SubmenuIndexAddManualy) {
+            scene_manager_set_scene_state(
+                nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManualy);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType);
+            return true;
+        } else if(event.event == SubmenuIndexDebug) {
+            scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneDebugMenu);
+            return true;
+        }
     }
     }
     return false;
     return false;
 }
 }
@@ -76,17 +73,3 @@ const void nfc_scene_start_on_exit(void* context) {
 
 
     submenu_clean(nfc->submenu);
     submenu_clean(nfc->submenu);
 }
 }
-
-AppScene* nfc_scene_start_alloc() {
-    AppScene* scene = furi_alloc(sizeof(AppScene));
-    scene->id = NfcSceneStart;
-    scene->on_enter = nfc_scene_start_on_enter;
-    scene->on_event = nfc_scene_start_on_event;
-    scene->on_exit = nfc_scene_start_on_exit;
-
-    return scene;
-}
-
-void nfc_scene_start_free(AppScene* scene) {
-    free(scene);
-}

+ 0 - 7
applications/nfc/scenes/nfc_scene_start.h

@@ -1,7 +0,0 @@
-#pragma once
-
-#include "app_scene.h"
-
-AppScene* nfc_scene_start_alloc();
-
-void nfc_scene_start_free(AppScene* scene);

+ 0 - 4
firmware/targets/f5/api-hal/api-hal-nfc.c

@@ -125,10 +125,6 @@ bool api_hal_nfc_listen(uint8_t* uid, uint8_t uid_len, uint8_t* atqa, uint8_t sa
             rfalNfcDeactivate(true);
             rfalNfcDeactivate(true);
             return false;
             return false;
         }
         }
-        if(state == RFAL_NFC_STATE_LISTEN_ACTIVATION) {
-            start = DWT->CYCCNT;
-            continue;
-        }
         osThreadYield();
         osThreadYield();
     }
     }
     return true;
     return true;

+ 0 - 4
firmware/targets/f6/api-hal/api-hal-nfc.c

@@ -125,10 +125,6 @@ bool api_hal_nfc_listen(uint8_t* uid, uint8_t uid_len, uint8_t* atqa, uint8_t sa
             rfalNfcDeactivate(true);
             rfalNfcDeactivate(true);
             return false;
             return false;
         }
         }
-        if(state == RFAL_NFC_STATE_LISTEN_ACTIVATION) {
-            start = DWT->CYCCNT;
-            continue;
-        }
         osThreadYield();
         osThreadYield();
     }
     }
     return true;
     return true;

+ 0 - 12
lib/app_scene_template/app_scene.h

@@ -1,12 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include <stdbool.h>
-
-typedef struct {
-    uint32_t id;
-    uint32_t state;
-    const void (*on_enter)(void* context);
-    const bool (*on_event)(void* context, uint32_t event);
-    const void (*on_exit)(void* context);
-} AppScene;