scene_items.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include <furi.h>
  2. #include <gui/view_dispatcher.h>
  3. #include <gui/scene_manager.h>
  4. #include <gui/modules/button_menu.h>
  5. #include <gui/modules/dialog_ex.h>
  6. #include <notification/notification_messages.h>
  7. #include "quac.h"
  8. #include "scenes.h"
  9. #include "scene_items.h"
  10. #include "../actions/action.h"
  11. #include <lib/toolbox/path.h>
  12. void scene_items_item_callback(void* context, int32_t index, InputType type) {
  13. App* app = context;
  14. if(type == InputTypeShort || type == InputTypeRelease) {
  15. app->selected_item = index;
  16. view_dispatcher_send_custom_event(app->view_dispatcher, Event_ButtonPressed);
  17. } else {
  18. // do nothing
  19. }
  20. }
  21. // For each scene, implement handler callbacks
  22. void scene_items_on_enter(void* context) {
  23. App* app = context;
  24. ButtonMenu* menu = app->btn_menu;
  25. button_menu_reset(menu);
  26. DialogEx* dialog = app->dialog;
  27. dialog_ex_reset(dialog);
  28. ItemsView* items_view = app->items_view;
  29. FURI_LOG_I(TAG, "items on_enter: [%d] %s", app->depth, furi_string_get_cstr(items_view->path));
  30. const char* header = furi_string_get_cstr(items_view->name);
  31. button_menu_set_header(menu, header);
  32. if(ItemArray_size(items_view->items)) {
  33. ItemArray_it_t iter;
  34. int32_t index = 0;
  35. for(ItemArray_it(iter, items_view->items); !ItemArray_end_p(iter);
  36. ItemArray_next(iter), ++index) {
  37. const char* label = furi_string_get_cstr(ItemArray_cref(iter)->name);
  38. ButtonMenuItemType type = ItemArray_cref(iter)->type == Item_Action ?
  39. ButtonMenuItemTypeCommon :
  40. ButtonMenuItemTypeControl;
  41. button_menu_add_item(menu, label, index, scene_items_item_callback, type, app);
  42. }
  43. } else {
  44. FURI_LOG_W(TAG, "No items for: %s", furi_string_get_cstr(items_view->path));
  45. // TODO: Display Error popup? Empty folder?
  46. }
  47. // ...
  48. view_dispatcher_switch_to_view(app->view_dispatcher, SR_ButtonMenu);
  49. }
  50. bool scene_items_on_event(void* context, SceneManagerEvent event) {
  51. App* app = context;
  52. bool consumed = false;
  53. FURI_LOG_I(TAG, "device on_event");
  54. switch(event.type) {
  55. case SceneManagerEventTypeCustom:
  56. if(event.event == Event_ButtonPressed) {
  57. consumed = true;
  58. FURI_LOG_I(TAG, "button pressed is %d", app->selected_item);
  59. Item* item = ItemArray_get(app->items_view->items, app->selected_item);
  60. if(item->type == Item_Group) {
  61. app->depth++;
  62. ItemsView* new_items = item_get_items_view_from_path(app, item->path);
  63. item_items_view_free(app->items_view);
  64. app->items_view = new_items;
  65. scene_manager_next_scene(app->scene_manager, SR_Scene_Items);
  66. } else {
  67. FURI_LOG_I(TAG, "Initiating item action: %s", furi_string_get_cstr(item->name));
  68. // LED goes blinky blinky
  69. App* app = context;
  70. notification_message(app->notifications, &sequence_blink_start_blue);
  71. // Prepare error string for action calls
  72. FuriString* error;
  73. error = furi_string_alloc();
  74. action_tx(app, item, error);
  75. if(furi_string_size(error)) {
  76. FURI_LOG_E(TAG, furi_string_get_cstr(error));
  77. // Change LED to Red and Vibrate!
  78. notification_message(app->notifications, &sequence_error);
  79. // Display DialogEx popup or something?
  80. }
  81. furi_string_free(error);
  82. // Turn off LED light
  83. notification_message(app->notifications, &sequence_blink_stop);
  84. }
  85. }
  86. break;
  87. case SceneManagerEventTypeBack:
  88. FURI_LOG_I(TAG, "Back button pressed!");
  89. consumed = false; // Ensure Back event continues to propagate
  90. if(app->depth >= 0) {
  91. // take our current ItemsView path, and go back up a level
  92. FuriString* parent_path;
  93. parent_path = furi_string_alloc();
  94. path_extract_dirname(furi_string_get_cstr(app->items_view->path), parent_path);
  95. app->depth--;
  96. ItemsView* new_items = item_get_items_view_from_path(app, parent_path);
  97. item_items_view_free(app->items_view);
  98. app->items_view = new_items;
  99. furi_string_free(parent_path);
  100. } else {
  101. FURI_LOG_W(TAG, "At the root level!");
  102. }
  103. break;
  104. default:
  105. break;
  106. }
  107. return consumed;
  108. }
  109. void scene_items_on_exit(void* context) {
  110. App* app = context;
  111. ButtonMenu* menu = app->btn_menu;
  112. button_menu_reset(menu);
  113. DialogEx* dialog = app->dialog;
  114. dialog_ex_reset(dialog);
  115. FURI_LOG_I(TAG, "on_exit. depth = %d", app->depth);
  116. }