@@ -20,13 +20,16 @@ struct FlippPomodoroTimerView
20
20
{
21
21
View * view ;
22
22
FlippPomodoroTimerViewInputCb right_cb ;
23
- void * right_cb_ctx ;
23
+ FlippPomodoroTimerViewInputCb ok_cb ;
24
+ void * callback_context ;
24
25
};
25
26
26
27
typedef struct
27
28
{
28
29
IconAnimation * icon ;
29
30
FlippPomodoroState * state ;
31
+ size_t scroll_counter ;
32
+ char * current_hint ;
30
33
} FlippPomodoroTimerViewModel ;
31
34
32
35
static const Icon * stage_background_image [] = {
@@ -108,6 +111,58 @@ static void flipp_pomodoro_view_timer_draw_current_stage_label(Canvas *canvas, F
108
111
flipp_pomodoro__current_stage_label (state ));
109
112
}
110
113
114
+ static void flipp_pomodoro_view_timer_draw_hint (Canvas * canvas , FlippPomodoroTimerViewModel * model )
115
+ {
116
+ size_t MAX_SCROLL_COUNTER = 300 ;
117
+ uint8_t SCROLL_DELAY_FRAMES = 3 ;
118
+
119
+ if (model -> scroll_counter >= MAX_SCROLL_COUNTER || model -> current_hint == NULL )
120
+ {
121
+ return ;
122
+ }
123
+
124
+ uint8_t hint_width = 90 ;
125
+ uint8_t hint_height = 18 ;
126
+
127
+ uint8_t hint_x = canvas_width (canvas ) - hint_width - 6 ;
128
+ uint8_t hint_y = 35 ;
129
+
130
+ FuriString * displayed_hint_string = furi_string_alloc ();
131
+
132
+ furi_string_printf (
133
+ displayed_hint_string ,
134
+ "%s" ,
135
+ model -> current_hint );
136
+
137
+ size_t perfect_duration = furi_string_size (displayed_hint_string ) * 1.5 ;
138
+
139
+ if (model -> scroll_counter > perfect_duration )
140
+ {
141
+ model -> scroll_counter = MAX_SCROLL_COUNTER ;
142
+ furi_string_free (displayed_hint_string );
143
+ return ;
144
+ }
145
+
146
+ size_t scroll_offset = (model -> scroll_counter < SCROLL_DELAY_FRAMES ) ? 0 : model -> scroll_counter - SCROLL_DELAY_FRAMES ;
147
+
148
+ canvas_set_color (canvas , ColorWhite );
149
+ canvas_draw_box (canvas , hint_x , hint_y , hint_width + 3 , hint_height );
150
+ canvas_set_color (canvas , ColorBlack );
151
+
152
+ elements_bubble (canvas , hint_x , hint_y , hint_width , hint_height );
153
+
154
+ elements_scrollable_text_line (
155
+ canvas ,
156
+ hint_x + 6 ,
157
+ hint_y + 12 ,
158
+ hint_width - 4 ,
159
+ displayed_hint_string ,
160
+ scroll_offset ,
161
+ true);
162
+ furi_string_free (displayed_hint_string );
163
+ model -> scroll_counter ++ ;
164
+ }
165
+
111
166
static void flipp_pomodoro_view_timer_draw_callback (Canvas * canvas , void * _model )
112
167
{
113
168
if (!_model )
@@ -128,10 +183,12 @@ static void flipp_pomodoro_view_timer_draw_callback(Canvas *canvas, void *_model
128
183
flipp_pomodoro__stage_remaining_duration (model -> state ));
129
184
130
185
flipp_pomodoro_view_timer_draw_current_stage_label (canvas , model -> state );
186
+
131
187
canvas_set_color (canvas , ColorBlack );
132
188
133
189
canvas_set_font (canvas , FontSecondary );
134
190
elements_button_right (canvas , flipp_pomodoro__next_stage_label (model -> state ));
191
+ flipp_pomodoro_view_timer_draw_hint (canvas , model );
135
192
};
136
193
137
194
bool flipp_pomodoro_view_timer_input_callback (InputEvent * event , void * ctx )
@@ -140,19 +197,24 @@ bool flipp_pomodoro_view_timer_input_callback(InputEvent *event, void *ctx)
140
197
furi_assert (event );
141
198
FlippPomodoroTimerView * timer = ctx ;
142
199
143
- const bool should_trigger_right_event_cb = (event -> type == InputTypePress ) &&
144
- (event -> key == InputKeyRight ) &&
145
- (timer -> right_cb != NULL );
200
+ const bool is_press_event = event -> type == InputTypePress ;
146
201
147
- if (should_trigger_right_event_cb )
202
+ if (! is_press_event )
148
203
{
149
- furi_assert (timer -> right_cb );
150
- furi_assert (timer -> right_cb_ctx );
151
- timer -> right_cb (timer -> right_cb_ctx );
152
- return ViewInputConsumed ;
153
- };
204
+ return ViewInputNotConusmed ;
205
+ }
154
206
155
- return ViewInputNotConusmed ;
207
+ switch (event -> key )
208
+ {
209
+ case InputKeyRight :
210
+ timer -> right_cb (timer -> callback_context );
211
+ return ViewInputConsumed ;
212
+ case InputKeyOk :
213
+ timer -> ok_cb (timer -> callback_context );
214
+ return ViewInputConsumed ;
215
+ default :
216
+ return ViewInputNotConusmed ;
217
+ }
156
218
};
157
219
158
220
View * flipp_pomodoro_view_timer_get_view (FlippPomodoroTimerView * timer )
@@ -161,13 +223,24 @@ View *flipp_pomodoro_view_timer_get_view(FlippPomodoroTimerView *timer)
161
223
return timer -> view ;
162
224
};
163
225
226
+ void flipp_pomodoro_view_timer_display_hint (View * view , char * hint )
227
+ {
228
+ with_view_model (
229
+ view ,
230
+ FlippPomodoroTimerViewModel * model ,
231
+ {
232
+ model -> scroll_counter = 0 ;
233
+ model -> current_hint = hint ;
234
+ },
235
+ true);
236
+ }
237
+
164
238
void flipp_pomodoro_view_timer_assign_animation (View * view )
165
239
{
166
240
with_view_model (
167
241
view ,
168
242
FlippPomodoroTimerViewModel * model ,
169
243
{
170
- furi_assert (model -> state );
171
244
if (model -> icon )
172
245
{
173
246
icon_animation_free (model -> icon );
@@ -186,21 +259,43 @@ FlippPomodoroTimerView *flipp_pomodoro_view_timer_alloc()
186
259
timer -> view = view_alloc ();
187
260
188
261
view_allocate_model (flipp_pomodoro_view_timer_get_view (timer ), ViewModelTypeLockFree , sizeof (FlippPomodoroTimerViewModel ));
262
+
189
263
view_set_context (flipp_pomodoro_view_timer_get_view (timer ), timer );
190
264
view_set_draw_callback (timer -> view , flipp_pomodoro_view_timer_draw_callback );
191
265
view_set_input_callback (timer -> view , flipp_pomodoro_view_timer_input_callback );
192
266
267
+ with_view_model (
268
+ flipp_pomodoro_view_timer_get_view (timer ),
269
+ FlippPomodoroTimerViewModel * model ,
270
+ {
271
+ model -> scroll_counter = 0 ;
272
+ },
273
+ false);
274
+
193
275
return timer ;
194
276
};
195
277
196
- void flipp_pomodoro_view_timer_set_on_right_cb (FlippPomodoroTimerView * timer , FlippPomodoroTimerViewInputCb right_cb , void * right_cb_ctx )
278
+ void flipp_pomodoro_view_timer_set_callback_context (FlippPomodoroTimerView * timer , void * callback_ctx )
279
+ {
280
+ furi_assert (timer );
281
+ furi_assert (callback_ctx );
282
+ timer -> callback_context = callback_ctx ;
283
+ }
284
+
285
+ void flipp_pomodoro_view_timer_set_on_right_cb (FlippPomodoroTimerView * timer , FlippPomodoroTimerViewInputCb right_cb )
197
286
{
287
+ furi_assert (timer );
198
288
furi_assert (right_cb );
199
- furi_assert (right_cb_ctx );
200
289
timer -> right_cb = right_cb ;
201
- timer -> right_cb_ctx = right_cb_ctx ;
202
290
};
203
291
292
+ void flipp_pomodoro_view_timer_set_on_ok_cb (FlippPomodoroTimerView * timer , FlippPomodoroTimerViewInputCb ok_kb )
293
+ {
294
+ furi_assert (ok_kb );
295
+ furi_assert (timer );
296
+ timer -> ok_cb = ok_kb ;
297
+ }
298
+
204
299
void flipp_pomodoro_view_timer_set_state (View * view , FlippPomodoroState * state )
205
300
{
206
301
furi_assert (view );
@@ -210,6 +305,7 @@ void flipp_pomodoro_view_timer_set_state(View *view, FlippPomodoroState *state)
210
305
FlippPomodoroTimerViewModel * model ,
211
306
{
212
307
model -> state = state ;
308
+ model -> current_hint = NULL ;
213
309
},
214
310
false);
215
311
flipp_pomodoro_view_timer_assign_animation (view );
0 commit comments