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

feat: animated stage background (#39)(#32)

* wip encapsulate current stage mechanism

* add animations for stages

* fix incorrect documentation commit

* remove duplications in view

* enable re-render after animation is assigned
Mikhail Gubenko 3 лет назад
Родитель
Сommit
925ebc6456

+ 8 - 2
flipp_pomodoro_app.c

@@ -30,16 +30,22 @@ static bool flipp_pomodoro_app_custom_event_callback(void *ctx, uint32_t event)
     {
     case FlippPomodoroAppCustomEventStageSkip:
         flipp_pomodoro__toggle_stage(app->state);
+        view_dispatcher_send_custom_event(
+            app->view_dispatcher,
+            FlippPomodoroAppCustomEventStateUpdated);
         return CustomEventConsumed;
     case FlippPomodoroAppCustomEventStageComplete:
-        if (app->state->stage == Work)
+        if (flipp_pomodoro__get_stage(app->state) == Work)
         {
             // REGISTER a deed on work stage complete to get an acheivement
             DOLPHIN_DEED(DolphinDeedPluginGameWin);
         };
 
         flipp_pomodoro__toggle_stage(app->state);
-        notification_message(app->notification_app, stage_start_notification_sequence_map[app->state->stage]);
+        notification_message(app->notification_app, stage_start_notification_sequence_map[flipp_pomodoro__get_stage(app->state)]);
+        view_dispatcher_send_custom_event(
+            app->view_dispatcher,
+            FlippPomodoroAppCustomEventStateUpdated);
         return CustomEventConsumed;
     default:
         break;

+ 1 - 0
flipp_pomodoro_app.h

@@ -16,6 +16,7 @@ typedef enum
     FlippPomodoroAppCustomEventStageSkip = 100,
     FlippPomodoroAppCustomEventStageComplete, // By Expiration
     FlippPomodoroAppCustomEventTimerTick,
+    FlippPomodoroAppCustomEventStateUpdated,
 } FlippPomodoroAppCustomEvent;
 
 typedef struct

BIN
images/flipp_pomodoro_focus_64/frame_00.png


+ 0 - 0
images/flipp_pomodoro_work_64.png → images/flipp_pomodoro_focus_64/frame_01.png


+ 1 - 0
images/flipp_pomodoro_focus_64/frame_rate

@@ -0,0 +1 @@
+1

+ 0 - 0
images/flipp_pomodoro_rest_64.png → images/flipp_pomodoro_rest_64/frame_00.png


BIN
images/flipp_pomodoro_rest_64/frame_01.png


+ 1 - 0
images/flipp_pomodoro_rest_64/frame_rate

@@ -0,0 +1 @@
+1

+ 9 - 3
modules/flipp_pomodoro.c

@@ -18,14 +18,20 @@ const PomodoroStage default_stage = Work;
 void flipp_pomodoro__toggle_stage(FlippPomodoroState *state)
 {
     furi_assert(state);
-    state->stage = stage_rotaion_map[state->stage];
+    state->stage = stage_rotaion_map[flipp_pomodoro__get_stage(state)];
     state->started_at_timestamp = time_now();
 };
 
+PomodoroStage flipp_pomodoro__get_stage(FlippPomodoroState *state)
+{
+    furi_assert(state);
+    return state->stage;
+};
+
 char *flipp_pomodoro__next_stage_label(FlippPomodoroState *state)
 {
     furi_assert(state);
-    return next_stage_label[state->stage];
+    return next_stage_label[flipp_pomodoro__get_stage(state)];
 };
 
 void flipp_pomodoro__destroy(FlippPomodoroState *state)
@@ -41,7 +47,7 @@ uint32_t flipp_pomodoro__current_stage_total_duration(FlippPomodoroState *state)
         [Rest] = 5 * TIME_SECONDS_IN_MINUTE,
     };
 
-    return stage_duration_seconds_map[state->stage];
+    return stage_duration_seconds_map[flipp_pomodoro__get_stage(state)];
 };
 
 uint32_t flipp_pomodoro__stage_expires_timestamp(FlippPomodoroState *state)

+ 6 - 2
modules/flipp_pomodoro.h

@@ -18,15 +18,19 @@ typedef struct
 } FlippPomodoroState;
 
 /// @brief Generates initial state
-/// @param state - pointer to the state of pomorodo.
 /// @returns A new pre-populated state for pomodoro timer
 FlippPomodoroState *flipp_pomodoro__new();
 
+/// @brief Extract current stage of pomodoro
+/// @param state - pointer to the state of pomorodo
+/// @returns Current stage value
+PomodoroStage flipp_pomodoro__get_stage(FlippPomodoroState *state);
+
 /// @brief Destroys state of timer and it's dependencies
 void flipp_pomodoro__destroy(FlippPomodoroState *state);
 
 /// @brief Get remaining stage time.
-/// @param state - pointer to the state of pomorodo.
+/// @param state - pointer to the state of pomorodo
 /// @returns Time difference to the end of current stage
 TimeDifference flipp_pomodoro__stage_remaining_duration(FlippPomodoroState *state);
 

+ 17 - 3
scenes/flipp_pomodoro_scene_timer.c

@@ -12,6 +12,17 @@ enum
 
 uint8_t ExitSignal = 0;
 
+void flipp_pomodoro_scene_timer_sync_view_state(void *context)
+{
+    furi_assert(context);
+
+    FlippPomodoroApp *app = context;
+
+    flipp_pomodoro_view_timer_set_state(
+        flipp_pomodoro_view_timer_get_view(app->timer_view),
+        app->state);
+};
+
 void flipp_pomodoro_scene_timer_on_next_stage(void *ctx)
 {
     furi_assert(ctx);
@@ -30,9 +41,7 @@ void flipp_pomodoro_scene_timer_on_enter(void *context)
     FlippPomodoroApp *app = context;
 
     view_dispatcher_switch_to_view(app->view_dispatcher, FlippPomodoroAppViewTimer);
-    flipp_pomodoro_view_timer_set_state(
-        flipp_pomodoro_view_timer_get_view(app->timer_view),
-        app->state);
+    flipp_pomodoro_scene_timer_sync_view_state(app);
     flipp_pomodoro_view_timer_set_on_right_cb(
         app->timer_view,
         flipp_pomodoro_scene_timer_on_next_stage,
@@ -47,6 +56,11 @@ void flipp_pomodoro_scene_timer_handle_custom_event(FlippPomodoroApp *app, Flipp
             app->view_dispatcher,
             FlippPomodoroAppCustomEventStageComplete);
     }
+
+    if (custom_event == FlippPomodoroAppCustomEventStateUpdated)
+    {
+        flipp_pomodoro_scene_timer_sync_view_state(app);
+    }
 };
 
 bool flipp_pomodoro_scene_timer_on_event(void *ctx, SceneManagerEvent event)

+ 36 - 3
views/flipp_pomodoro_timer_view.c

@@ -25,12 +25,13 @@ struct FlippPomodoroTimerView
 
 typedef struct
 {
+    IconAnimation *icon;
     FlippPomodoroState *state;
 } FlippPomodoroTimerViewModel;
 
 static const Icon *stage_background_image[] = {
-    [Work] = &I_flipp_pomodoro_work_64,
-    [Rest] = &I_flipp_pomodoro_rest_64,
+    [Work] = &A_flipp_pomodoro_focus_64,
+    [Rest] = &A_flipp_pomodoro_rest_64,
 };
 
 static void flipp_pomodoro_view_timer_draw_countdown(Canvas *canvas, TimeDifference remaining_time)
@@ -73,7 +74,11 @@ static void flipp_pomodoro_view_timer_draw_callback(Canvas *canvas, void *_model
     FlippPomodoroTimerViewModel *model = _model;
 
     canvas_clear(canvas);
-    canvas_draw_icon(canvas, 0, 0, stage_background_image[model->state->stage]);
+    if (model->icon)
+    {
+        canvas_draw_icon_animation(canvas, 0, 0, model->icon);
+    }
+
     flipp_pomodoro_view_timer_draw_countdown(
         canvas,
         flipp_pomodoro__stage_remaining_duration(model->state));
@@ -109,6 +114,25 @@ View *flipp_pomodoro_view_timer_get_view(FlippPomodoroTimerView *timer)
     return timer->view;
 };
 
+void flipp_pomodoro_view_timer_assign_animation(View *view)
+{
+    with_view_model(
+        view,
+        FlippPomodoroTimerViewModel * model,
+        {
+            furi_assert(model->state);
+            if (model->icon)
+            {
+                icon_animation_free(model->icon);
+            }
+            model->icon = icon_animation_alloc(
+                stage_background_image[flipp_pomodoro__get_stage(model->state)]);
+            view_tie_icon_animation(view, model->icon);
+            icon_animation_start(model->icon);
+        },
+        true);
+}
+
 FlippPomodoroTimerView *flipp_pomodoro_view_timer_alloc()
 {
     FlippPomodoroTimerView *timer = malloc(sizeof(FlippPomodoroTimerView));
@@ -141,11 +165,20 @@ void flipp_pomodoro_view_timer_set_state(View *view, FlippPomodoroState *state)
             model->state = state;
         },
         false);
+    flipp_pomodoro_view_timer_assign_animation(view);
 };
 
 void flipp_pomodoro_view_timer_free(FlippPomodoroTimerView *timer)
 {
     furi_assert(timer);
+    with_view_model(
+        timer->view,
+        FlippPomodoroTimerViewModel * model,
+        {
+            icon_animation_free(model->icon);
+        },
+        false);
     view_free(timer->view);
+
     free(timer);
 };