소스 검색

[FL-1543] Scene manager search scene API (#611)

* scene_manager: search -> search_and_switch_to previous_scene
* scene_manager: add search and switch to another scene API
* scene_manager: Navigation -> Back event
gornekich 4 년 전
부모
커밋
91c1eaf5a8

+ 47 - 3
applications/gui/scene_manager.c

@@ -53,11 +53,11 @@ bool scene_manager_handle_custom_event(SceneManager* scene_manager, uint32_t cus
         scene_manager->context, event);
 }
 
-bool scene_manager_handle_navigation_event(SceneManager* scene_manager) {
+bool scene_manager_handle_back_event(SceneManager* scene_manager) {
     furi_assert(scene_manager);
 
     SceneManagerEvent event = {
-        .type = SceneManagerEventTypeNavigation,
+        .type = SceneManagerEventTypeBack,
     };
     uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
     bool consumed =
@@ -109,7 +109,9 @@ bool scene_manager_previous_scene(SceneManager* scene_manager) {
     return true;
 }
 
-bool scene_manager_search_previous_scene(SceneManager* scene_manager, uint32_t scene_id) {
+bool scene_manager_search_and_switch_to_previous_scene(
+    SceneManager* scene_manager,
+    uint32_t scene_id) {
     furi_assert(scene_manager);
 
     uint32_t prev_scene_id = 0;
@@ -137,3 +139,45 @@ bool scene_manager_search_previous_scene(SceneManager* scene_manager, uint32_t s
 
     return true;
 }
+
+bool scene_manager_has_previous_scene(SceneManager* scene_manager, uint32_t scene_id) {
+    furi_assert(scene_manager);
+    bool scene_found = false;
+    uint32_t prev_scene_id;
+    SceneManagerIdStack_it_t scene_it;
+    SceneManagerIdStack_it_last(scene_it, scene_manager->scene_id_stack);
+
+    // Perform search in scene stack
+    while(!scene_found) {
+        SceneManagerIdStack_previous(scene_it);
+        if(SceneManagerIdStack_end_p(scene_it)) {
+            break;
+        }
+        prev_scene_id = *SceneManagerIdStack_ref(scene_it);
+        if(prev_scene_id == scene_id) {
+            scene_found = true;
+        }
+    }
+    return scene_found;
+}
+
+bool scene_manager_search_and_switch_to_another_scene(
+    SceneManager* scene_manager,
+    uint32_t scene_id) {
+    furi_assert(scene_manager);
+    furi_assert(scene_id < scene_manager->scene_handlers->scene_num);
+
+    uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
+    SceneManagerIdStack_it_t scene_it;
+    SceneManagerIdStack_it(scene_it, scene_manager->scene_id_stack);
+    SceneManagerIdStack_next(scene_it);
+    // Remove all scene id from navigation stack until first scene
+    SceneManagerIdStack_pop_until(scene_manager->scene_id_stack, scene_it);
+    // Add next scene
+    SceneManagerIdStack_push_back(scene_manager->scene_id_stack, scene_id);
+
+    scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
+    scene_manager->scene_handlers->on_enter_handlers[scene_id](scene_manager->context);
+
+    return true;
+}

+ 24 - 6
applications/gui/scene_manager.h

@@ -11,7 +11,7 @@ extern "C" {
  */
 typedef enum {
     SceneManagerEventTypeCustom,
-    SceneManagerEventTypeNavigation,
+    SceneManagerEventTypeBack,
     SceneManagerEventTypeTick,
 } SceneManagerEventType;
 
@@ -78,12 +78,12 @@ void scene_manager_free(SceneManager* scene_manager);
  */
 bool scene_manager_handle_custom_event(SceneManager* scene_manager, uint32_t custom_event);
 
-/** Navigation event handler
- * Calls Scene event handler with Navigation event parameter
+/** Back event handler
+ * Calls Scene event handler with Back event parameter
  * @param scene_manager SceneManager instance
  * @return true if event was consumed, false otherwise
  */
-bool scene_manager_handle_navigation_event(SceneManager* scene_manager);
+bool scene_manager_handle_back_event(SceneManager* scene_manager);
 
 /** Tick event handler
  * Calls Scene event handler with Tick event parameter
@@ -104,12 +104,30 @@ void scene_manager_next_scene(SceneManager* scene_manager, uint32_t next_scene_i
  */
 bool scene_manager_previous_scene(SceneManager* scene_manager);
 
-/** Search previous Scene by ID
+/** Search previous Scene
  * @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);
+bool scene_manager_has_previous_scene(SceneManager* scene_manager, uint32_t scene_id);
+
+/** Search and switch to previous Scene
+ * @param scene_manager SceneManager instance
+ * @param scene_id Scene ID
+ * @return true if previous scene was found, false otherwise
+ */
+bool scene_manager_search_and_switch_to_previous_scene(
+    SceneManager* scene_manager,
+    uint32_t scene_id);
+
+/** Clear Scene stack and switch to another Scene
+ * @param scene_manager SceneManager instance
+ * @param scene_id Scene ID
+ * @return true if previous scene was found, false otherwise
+ */
+bool scene_manager_search_and_switch_to_another_scene(
+    SceneManager* scene_manager,
+    uint32_t scene_id);
 
 #ifdef __cplusplus
 }

+ 3 - 4
applications/nfc/nfc.c

@@ -7,10 +7,10 @@ bool nfc_custom_event_callback(void* context, uint32_t event) {
     return scene_manager_handle_custom_event(nfc->scene_manager, event);
 }
 
-bool nfc_navigation_event_callback(void* context) {
+bool nfc_back_event_callback(void* context) {
     furi_assert(context);
     Nfc* nfc = (Nfc*)context;
-    return scene_manager_handle_navigation_event(nfc->scene_manager);
+    return scene_manager_handle_back_event(nfc->scene_manager);
 }
 
 void nfc_tick_event_callback(void* context) {
@@ -28,8 +28,7 @@ Nfc* nfc_alloc() {
     view_dispatcher_enable_queue(nfc->view_dispatcher);
     view_dispatcher_set_event_callback_context(nfc->view_dispatcher, nfc);
     view_dispatcher_set_custom_event_callback(nfc->view_dispatcher, nfc_custom_event_callback);
-    view_dispatcher_set_navigation_event_callback(
-        nfc->view_dispatcher, nfc_navigation_event_callback);
+    view_dispatcher_set_navigation_event_callback(nfc->view_dispatcher, nfc_back_event_callback);
     view_dispatcher_set_tick_event_callback(nfc->view_dispatcher, nfc_tick_event_callback, 100);
 
     // Open GUI record

+ 3 - 2
applications/nfc/scenes/nfc_scene_card_menu.c

@@ -70,8 +70,9 @@ const bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event)
             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);
+    } else if(event.type == SceneManagerEventTypeBack) {
+        return scene_manager_search_and_switch_to_previous_scene(
+            nfc->scene_manager, NfcSceneStart);
     }
 
     return false;

+ 2 - 1
applications/nfc/scenes/nfc_scene_delete.c

@@ -75,7 +75,8 @@ const bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) {
             if(nfc_device_delete(&nfc->dev)) {
                 scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
             } else {
-                scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
+                scene_manager_search_and_switch_to_previous_scene(
+                    nfc->scene_manager, NfcSceneStart);
             }
             return true;
         }

+ 2 - 1
applications/nfc/scenes/nfc_scene_delete_success.c

@@ -26,7 +26,8 @@ const bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent ev
 
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) {
-            return scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
+            return scene_manager_search_and_switch_to_previous_scene(
+                nfc->scene_manager, NfcSceneStart);
         }
     }
     return false;

+ 1 - 1
applications/nfc/scenes/nfc_scene_file_select.c

@@ -6,7 +6,7 @@ const void nfc_scene_file_select_on_enter(void* context) {
     if(nfc_file_select(&nfc->dev)) {
         scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
     } else {
-        scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
+        scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart);
     }
 }
 

+ 3 - 2
applications/nfc/scenes/nfc_scene_mifare_ul_menu.c

@@ -41,8 +41,9 @@ const bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent ev
             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);
+    } else if(event.type == SceneManagerEventTypeBack) {
+        return scene_manager_search_and_switch_to_previous_scene(
+            nfc->scene_manager, NfcSceneStart);
     }
 
     return false;

+ 4 - 3
applications/nfc/scenes/nfc_scene_read_emv_data_success.c

@@ -68,15 +68,16 @@ const bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerE
 
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == GuiButtonTypeLeft) {
-            return scene_manager_search_previous_scene(
+            return scene_manager_search_and_switch_to_previous_scene(
                 nfc->scene_manager, NfcSceneReadEmvAppSuccess);
         } else if(event.event == GuiButtonTypeRight) {
             nfc->dev.format = NfcDeviceSaveFormatBankCard;
             scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
             return true;
         }
-    } else if(event.type == SceneManagerEventTypeNavigation) {
-        return scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneReadEmvAppSuccess);
+    } else if(event.type == SceneManagerEventTypeBack) {
+        return scene_manager_search_and_switch_to_previous_scene(
+            nfc->scene_manager, NfcSceneReadEmvAppSuccess);
     }
     return false;
 }

+ 2 - 1
applications/nfc/scenes/nfc_scene_save_name.c

@@ -45,7 +45,8 @@ const bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event)
                 scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
                 return true;
             } else {
-                return scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
+                return scene_manager_search_and_switch_to_previous_scene(
+                    nfc->scene_manager, NfcSceneStart);
             }
         }
     }

+ 12 - 2
applications/nfc/scenes/nfc_scene_save_success.c

@@ -23,13 +23,23 @@ const void nfc_scene_save_success_on_enter(void* context) {
 
 const bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
     Nfc* nfc = (Nfc*)context;
+    bool consumed = false;
 
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) {
-            return scene_manager_search_previous_scene(nfc->scene_manager, NfcSceneStart);
+            if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneCardMenu)) {
+                consumed = scene_manager_search_and_switch_to_previous_scene(
+                    nfc->scene_manager, NfcSceneCardMenu);
+            } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
+                consumed = scene_manager_search_and_switch_to_another_scene(
+                    nfc->scene_manager, NfcSceneFileSelect);
+            } else {
+                consumed = scene_manager_search_and_switch_to_previous_scene(
+                    nfc->scene_manager, NfcSceneStart);
+            }
         }
     }
-    return false;
+    return consumed;
 }
 
 const void nfc_scene_save_success_on_exit(void* context) {

+ 5 - 4
applications/storage-settings/scenes/storage-settings-scene-ejected.c

@@ -40,12 +40,13 @@ bool storage_settings_scene_unmounted_on_event(void* context, SceneManagerEvent
     if(event.type == SceneManagerEventTypeCustom) {
         switch(event.event) {
         case DialogExResultLeft:
-            consumed =
-                scene_manager_search_previous_scene(app->scene_manager, StorageSettingsStart);
+            consumed = scene_manager_search_and_switch_to_previous_scene(
+                app->scene_manager, StorageSettingsStart);
             break;
         }
-    } else if(event.type == SceneManagerEventTypeNavigation) {
-        consumed = scene_manager_search_previous_scene(app->scene_manager, StorageSettingsStart);
+    } else if(event.type == SceneManagerEventTypeBack) {
+        consumed = scene_manager_search_and_switch_to_previous_scene(
+            app->scene_manager, StorageSettingsStart);
     }
 
     return consumed;

+ 5 - 4
applications/storage-settings/scenes/storage-settings-scene-formatting.c

@@ -60,12 +60,13 @@ bool storage_settings_scene_formatting_on_event(void* context, SceneManagerEvent
     if(event.type == SceneManagerEventTypeCustom) {
         switch(event.event) {
         case DialogExResultLeft:
-            consumed =
-                scene_manager_search_previous_scene(app->scene_manager, StorageSettingsStart);
+            consumed = scene_manager_search_and_switch_to_previous_scene(
+                app->scene_manager, StorageSettingsStart);
             break;
         }
-    } else if(event.type == SceneManagerEventTypeNavigation) {
-        consumed = scene_manager_search_previous_scene(app->scene_manager, StorageSettingsStart);
+    } else if(event.type == SceneManagerEventTypeBack) {
+        consumed = scene_manager_search_and_switch_to_previous_scene(
+            app->scene_manager, StorageSettingsStart);
     }
 
     return consumed;

+ 3 - 3
applications/storage-settings/storage-settings.c

@@ -6,10 +6,10 @@ static bool storage_settings_custom_event_callback(void* context, uint32_t event
     return scene_manager_handle_custom_event(app->scene_manager, event);
 }
 
-static bool storage_settings_navigation_event_callback(void* context) {
+static bool storage_settings_back_event_callback(void* context) {
     furi_assert(context);
     StorageSettings* app = context;
-    return scene_manager_handle_navigation_event(app->scene_manager);
+    return scene_manager_handle_back_event(app->scene_manager);
 }
 
 static StorageSettings* storage_settings_alloc() {
@@ -29,7 +29,7 @@ static StorageSettings* storage_settings_alloc() {
     view_dispatcher_set_custom_event_callback(
         app->view_dispatcher, storage_settings_custom_event_callback);
     view_dispatcher_set_navigation_event_callback(
-        app->view_dispatcher, storage_settings_navigation_event_callback);
+        app->view_dispatcher, storage_settings_back_event_callback);
 
     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);