updater_main.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include <gui/gui_i.h>
  2. #include <gui/view.h>
  3. #include <gui/elements.h>
  4. #include <gui/canvas.h>
  5. #include <assets_icons.h>
  6. #include <furi.h>
  7. #include <input/input.h>
  8. #include "../updater_i.h"
  9. #include "updater_main.h"
  10. struct UpdaterMainView {
  11. View* view;
  12. ViewDispatcher* view_dispatcher;
  13. FuriPubSubSubscription* subscription;
  14. void* context;
  15. };
  16. static const uint8_t PROGRESS_RENDER_STEP = 1; /* percent, to limit rendering rate */
  17. typedef struct {
  18. FuriString* status;
  19. uint8_t progress, rendered_progress;
  20. bool failed;
  21. } UpdaterProgressModel;
  22. void updater_main_model_set_state(
  23. UpdaterMainView* main_view,
  24. const char* message,
  25. uint8_t progress,
  26. bool failed) {
  27. bool update = false;
  28. with_view_model(
  29. main_view->view,
  30. UpdaterProgressModel * model,
  31. {
  32. model->failed = failed;
  33. model->progress = progress;
  34. if(furi_string_cmp_str(model->status, message)) {
  35. furi_string_set(model->status, message);
  36. model->rendered_progress = progress;
  37. update = true;
  38. } else if(
  39. (model->rendered_progress > progress) ||
  40. ((progress - model->rendered_progress) > PROGRESS_RENDER_STEP)) {
  41. model->rendered_progress = progress;
  42. update = true;
  43. }
  44. },
  45. update);
  46. }
  47. View* updater_main_get_view(UpdaterMainView* main_view) {
  48. furi_assert(main_view);
  49. return main_view->view;
  50. }
  51. bool updater_main_input(InputEvent* event, void* context) {
  52. furi_assert(event);
  53. furi_assert(context);
  54. UpdaterMainView* main_view = context;
  55. if(!main_view->view_dispatcher) {
  56. return true;
  57. }
  58. if((event->type == InputTypeShort) && (event->key == InputKeyOk)) {
  59. view_dispatcher_send_custom_event(
  60. main_view->view_dispatcher, UpdaterCustomEventRetryUpdate);
  61. } else if((event->type == InputTypeLong) && (event->key == InputKeyBack)) {
  62. view_dispatcher_send_custom_event(
  63. main_view->view_dispatcher, UpdaterCustomEventCancelUpdate);
  64. }
  65. return true;
  66. }
  67. static void updater_main_draw_callback(Canvas* canvas, void* _model) {
  68. UpdaterProgressModel* model = _model;
  69. canvas_set_font(canvas, FontPrimary);
  70. if(model->failed) {
  71. canvas_draw_str_aligned(canvas, 42, 16, AlignLeft, AlignTop, "Update Failed!");
  72. canvas_set_font(canvas, FontSecondary);
  73. canvas_draw_str_aligned(
  74. canvas, 42, 32, AlignLeft, AlignTop, furi_string_get_cstr(model->status));
  75. canvas_draw_icon(canvas, 7, 16, &I_Warning_30x23);
  76. canvas_draw_str_aligned(
  77. canvas, 18, 51, AlignLeft, AlignTop, "to retry, hold to abort");
  78. canvas_draw_icon(canvas, 7, 50, &I_Ok_btn_9x9);
  79. canvas_draw_icon(canvas, 75, 51, &I_Pin_back_arrow_10x8);
  80. } else {
  81. canvas_draw_str_aligned(canvas, 55, 14, AlignLeft, AlignTop, "UPDATING");
  82. canvas_set_font(canvas, FontSecondary);
  83. canvas_draw_str_aligned(
  84. canvas, 64, 51, AlignCenter, AlignTop, furi_string_get_cstr(model->status));
  85. canvas_draw_icon(canvas, 4, 5, &I_Updating_32x40);
  86. elements_progress_bar(canvas, 42, 29, 80, (float)model->progress / 100);
  87. }
  88. }
  89. UpdaterMainView* updater_main_alloc() {
  90. UpdaterMainView* main_view = malloc(sizeof(UpdaterMainView));
  91. main_view->view = view_alloc();
  92. view_allocate_model(main_view->view, ViewModelTypeLocking, sizeof(UpdaterProgressModel));
  93. with_view_model(
  94. main_view->view,
  95. UpdaterProgressModel * model,
  96. { model->status = furi_string_alloc_set("Waiting for SD card"); },
  97. true);
  98. view_set_context(main_view->view, main_view);
  99. view_set_input_callback(main_view->view, updater_main_input);
  100. view_set_draw_callback(main_view->view, updater_main_draw_callback);
  101. return main_view;
  102. }
  103. void updater_main_free(UpdaterMainView* main_view) {
  104. furi_assert(main_view);
  105. with_view_model(
  106. main_view->view, UpdaterProgressModel * model, { furi_string_free(model->status); }, false);
  107. view_free(main_view->view);
  108. free(main_view);
  109. }
  110. void updater_main_set_storage_pubsub(UpdaterMainView* main_view, FuriPubSubSubscription* sub) {
  111. main_view->subscription = sub;
  112. }
  113. FuriPubSubSubscription* updater_main_get_storage_pubsub(UpdaterMainView* main_view) {
  114. return main_view->subscription;
  115. }
  116. void updater_main_set_view_dispatcher(UpdaterMainView* main_view, ViewDispatcher* view_dispatcher) {
  117. main_view->view_dispatcher = view_dispatcher;
  118. }