updater_main.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include <gui/gui_i.h>
  2. #include <gui/view.h>
  3. #include <gui/elements.h>
  4. #include <gui/canvas.h>
  5. #include <furi.h>
  6. #include <input/input.h>
  7. #include "../updater_i.h"
  8. #include "updater_main.h"
  9. struct UpdaterMainView {
  10. View* view;
  11. ViewDispatcher* view_dispatcher;
  12. FuriPubSubSubscription* subscription;
  13. void* context;
  14. };
  15. static const uint8_t PROGRESS_RENDER_STEP = 3; /* percent, to limit rendering rate */
  16. typedef struct {
  17. string_t status;
  18. uint8_t progress, rendered_progress;
  19. uint8_t idx_stage, total_stages;
  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. uint8_t idx_stage,
  27. uint8_t total_stages,
  28. bool failed) {
  29. with_view_model(
  30. main_view->view, (UpdaterProgressModel * model) {
  31. model->failed = failed;
  32. model->idx_stage = idx_stage;
  33. model->total_stages = total_stages;
  34. model->progress = progress;
  35. if(string_cmp_str(model->status, message)) {
  36. string_set(model->status, message);
  37. model->rendered_progress = progress;
  38. return true;
  39. }
  40. if((model->rendered_progress > progress) ||
  41. ((progress - model->rendered_progress) > PROGRESS_RENDER_STEP)) {
  42. model->rendered_progress = progress;
  43. return true;
  44. }
  45. return false;
  46. });
  47. }
  48. View* updater_main_get_view(UpdaterMainView* main_view) {
  49. furi_assert(main_view);
  50. return main_view->view;
  51. }
  52. bool updater_main_input(InputEvent* event, void* context) {
  53. furi_assert(event);
  54. furi_assert(context);
  55. UpdaterMainView* main_view = context;
  56. if(!main_view->view_dispatcher) {
  57. return true;
  58. }
  59. if(event->type != InputTypeShort) {
  60. return true;
  61. }
  62. if(event->key == InputKeyOk) {
  63. view_dispatcher_send_custom_event(
  64. main_view->view_dispatcher, UpdaterCustomEventRetryUpdate);
  65. } else if(event->key == InputKeyBack) {
  66. view_dispatcher_send_custom_event(
  67. main_view->view_dispatcher, UpdaterCustomEventCancelUpdate);
  68. }
  69. return true;
  70. }
  71. static void updater_main_draw_callback(Canvas* canvas, void* _model) {
  72. UpdaterProgressModel* model = _model;
  73. canvas_set_font(canvas, FontPrimary);
  74. uint16_t y_offset = model->failed ? 5 : 13;
  75. string_t status_text;
  76. if(!model->failed && (model->idx_stage != 0) && (model->idx_stage <= model->total_stages)) {
  77. string_init_printf(
  78. status_text,
  79. "[%d/%d] %s",
  80. model->idx_stage,
  81. model->total_stages,
  82. string_get_cstr(model->status));
  83. } else {
  84. string_init_set(status_text, model->status);
  85. }
  86. canvas_draw_str_aligned(
  87. canvas, 128 / 2, y_offset, AlignCenter, AlignTop, string_get_cstr(status_text));
  88. string_clear(status_text);
  89. if(model->failed) {
  90. canvas_set_font(canvas, FontSecondary);
  91. canvas_draw_str_aligned(
  92. canvas, 128 / 2, 20, AlignCenter, AlignTop, "[OK] to retry, [Back] to abort");
  93. }
  94. elements_progress_bar(canvas, 14, 35, 100, (float)model->progress / 100);
  95. }
  96. UpdaterMainView* updater_main_alloc() {
  97. UpdaterMainView* main_view = malloc(sizeof(UpdaterMainView));
  98. main_view->view = view_alloc();
  99. view_allocate_model(main_view->view, ViewModelTypeLocking, sizeof(UpdaterProgressModel));
  100. with_view_model(
  101. main_view->view, (UpdaterProgressModel * model) {
  102. string_init_set(model->status, "Waiting for storage");
  103. return true;
  104. });
  105. view_set_context(main_view->view, main_view);
  106. view_set_input_callback(main_view->view, updater_main_input);
  107. view_set_draw_callback(main_view->view, updater_main_draw_callback);
  108. return main_view;
  109. }
  110. void updater_main_free(UpdaterMainView* main_view) {
  111. furi_assert(main_view);
  112. with_view_model(
  113. main_view->view, (UpdaterProgressModel * model) {
  114. string_clear(model->status);
  115. return false;
  116. });
  117. view_free(main_view->view);
  118. free(main_view);
  119. }
  120. void updater_main_set_storage_pubsub(UpdaterMainView* main_view, FuriPubSubSubscription* sub) {
  121. main_view->subscription = sub;
  122. }
  123. FuriPubSubSubscription* updater_main_get_storage_pubsub(UpdaterMainView* main_view) {
  124. return main_view->subscription;
  125. }
  126. void updater_main_set_view_dispatcher(UpdaterMainView* main_view, ViewDispatcher* view_dispatcher) {
  127. main_view->view_dispatcher = view_dispatcher;
  128. }