[FL-1178] Idle screen improvements (#444)
* Dolphin idle screen: Cleanup of debug views; Hold [down] to open debug view; Sequential input for unlocking; * Lock screen popup, WIP * Fix reverse modulus * Lock popup added * Dolphin: timer for handling UI animation sequences * Allow tick events to be discarded on queue overflow and prevent timer service from crash Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									469e2dffec
								
							
						
					
					
						commit
						920b3c3dee
					
				| @ -2,8 +2,7 @@ | ||||
| #include <stdlib.h> | ||||
| #include "applications.h" | ||||
| 
 | ||||
| static void | ||||
| dolphin_switch_to_interactive_scene(Dolphin* dolphin, const FlipperApplication* flipper_app) { | ||||
| static void dolphin_switch_to_app(Dolphin* dolphin, const FlipperApplication* flipper_app) { | ||||
|     furi_assert(dolphin); | ||||
|     furi_assert(flipper_app); | ||||
|     furi_assert(flipper_app->app); | ||||
| @ -42,98 +41,126 @@ bool dolphin_view_first_start_input(InputEvent* event, void* context) { | ||||
|     furi_assert(context); | ||||
|     Dolphin* dolphin = context; | ||||
|     if(event->type == InputTypeShort) { | ||||
|         DolphinViewFirstStartModel* model = view_get_model(dolphin->idle_view_first_start); | ||||
|         if(event->key == InputKeyLeft) { | ||||
|             with_view_model( | ||||
|                 dolphin->idle_view_first_start, (DolphinViewFirstStartModel * model) { | ||||
|             if(model->page > 0) model->page--; | ||||
|                     return true; | ||||
|                 }); | ||||
|         } else if(event->key == InputKeyRight) { | ||||
|             uint32_t page; | ||||
|             with_view_model( | ||||
|                 dolphin->idle_view_first_start, (DolphinViewFirstStartModel * model) { | ||||
|                     page = ++model->page; | ||||
|                     return true; | ||||
|                 }); | ||||
|             uint32_t page = ++model->page; | ||||
|             if(page > 8) { | ||||
|                 dolphin_save(dolphin); | ||||
|                 view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|             } | ||||
|         } | ||||
|         view_commit_model(dolphin->idle_view_first_start, true); | ||||
|     } | ||||
|     // All events consumed
 | ||||
|     // All evennts cosumed
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void dolphin_lock_handler(InputEvent* event, Dolphin* dolphin) { | ||||
|     furi_assert(event); | ||||
|     furi_assert(dolphin); | ||||
|     if(event->key == InputKeyBack) { | ||||
|         uint32_t press_time = HAL_GetTick(); | ||||
| 
 | ||||
|         // check if pressed sequentially
 | ||||
|         if(press_time - dolphin->lock_lastpress < 200) { | ||||
|             dolphin->lock_lastpress = press_time; | ||||
|             dolphin->lock_count++; | ||||
|         } else if(press_time - dolphin->lock_lastpress > 200) { | ||||
|             dolphin->lock_lastpress = press_time; | ||||
|             dolphin->lock_count = 0; | ||||
|         } | ||||
| 
 | ||||
|         if(dolphin->lock_count == 3) { | ||||
|             dolphin->locked = false; | ||||
|             dolphin->lock_count = 0; | ||||
| 
 | ||||
|             with_view_model( | ||||
|                 dolphin->view_lockmenu, (DolphinViewLockMenuModel * model) { | ||||
|                     model->locked = false; | ||||
|                     return true; | ||||
|                 }); | ||||
| 
 | ||||
|             with_view_model( | ||||
|                 dolphin->idle_view_main, (DolphinViewMainModel * model) { | ||||
|                     model->hint_timeout = 0; | ||||
|                     return true; | ||||
|                 }); | ||||
| 
 | ||||
|             view_port_enabled_set(dolphin->lock_viewport, false); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool dolphin_view_idle_main_input(InputEvent* event, void* context) { | ||||
|     furi_assert(event); | ||||
|     furi_assert(context); | ||||
|     Dolphin* dolphin = context; | ||||
| 
 | ||||
|     if(event->type == InputTypeShort) { | ||||
|     // unlocked
 | ||||
|     if(!dolphin->locked) { | ||||
|             if(event->key == InputKeyOk) { | ||||
|         if(event->key == InputKeyOk && event->type == InputTypeShort) { | ||||
|             with_value_mutex( | ||||
|                 dolphin->menu_vm, (Menu * menu) { menu_ok(menu); }); | ||||
|             } else if(event->key == InputKeyUp) { | ||||
|         } else if(event->key == InputKeyUp && event->type == InputTypeShort) { | ||||
|             osTimerStart(dolphin->timeout_timer, 40); | ||||
|             view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewLockMenu); | ||||
|             } else if(event->key == InputKeyLeft) { | ||||
|                 view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleUp); | ||||
|             } else if(event->key == InputKeyRight) { | ||||
|                 dolphin_switch_to_interactive_scene(dolphin, &FLIPPER_SCENE); | ||||
|             } else if(event->key == InputKeyDown) { | ||||
|                 view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleDown); | ||||
|             } | ||||
|             if(event->key == InputKeyBack) { | ||||
|         } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { | ||||
| #if 0 | ||||
|             dolphin_switch_to_app(dolphin, &FAV_APP); | ||||
| #endif | ||||
|         } else if(event->key == InputKeyRight && event->type == InputTypeShort) { | ||||
|             dolphin_switch_to_app(dolphin, &FLIPPER_SCENE); | ||||
|         } else if(event->key == InputKeyDown && event->type == InputTypeShort) { | ||||
| #if 0 | ||||
|             dolphin_switch_to_app(dolphin, &ARCHIVE_APP); | ||||
| #endif | ||||
|         } else if(event->key == InputKeyDown && event->type == InputTypeLong) { | ||||
|             view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewStats); | ||||
|         } else if(event->key == InputKeyBack && event->type == InputTypeShort) { | ||||
|             view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|         } | ||||
|     } else { | ||||
|             if(event->key == InputKeyBack) { | ||||
|                 dolphin->lock_count++; | ||||
|                 if(dolphin->lock_count == 3) { | ||||
|                     dolphin->locked = false; | ||||
|                     dolphin->lock_count = 0; | ||||
|                     view_dispatcher_switch_to_view( | ||||
|                         dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|                     view_port_enabled_set(dolphin->lock_viewport, false); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // locked
 | ||||
| 
 | ||||
|         with_view_model( | ||||
|             dolphin->idle_view_main, (DolphinViewMainModel * model) { | ||||
|                 model->hint_timeout = 3; | ||||
|                 return true; | ||||
|             }); | ||||
| 
 | ||||
|         dolphin_lock_handler(event, dolphin); | ||||
|         dolphin_scene_handler_switch_scene(dolphin); | ||||
|     } | ||||
| 
 | ||||
|     // All events consumed
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool dolphin_view_idle_up_input(InputEvent* event, void* context) { | ||||
|     furi_assert(event); | ||||
|     furi_assert(context); | ||||
|     Dolphin* dolphin = context; | ||||
| 
 | ||||
|     if(event->type != InputTypeShort) return false; | ||||
| 
 | ||||
|     if(event->key == InputKeyLeft) { | ||||
|         dolphin_deed(dolphin, DolphinDeedWrong); | ||||
|     } else if(event->key == InputKeyRight) { | ||||
|         dolphin_deed(dolphin, DolphinDeedIButtonRead); | ||||
|     } else if(event->key == InputKeyOk) { | ||||
|         dolphin_save(dolphin); | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
| void lock_menu_refresh_handler(void* p) { | ||||
|     osMessageQueueId_t event_queue = p; | ||||
|     DolphinEvent event; | ||||
|     event.type = DolphinEventTypeTick; | ||||
|     // Some tick events may lost and we don't care.
 | ||||
|     osMessageQueuePut(event_queue, &event, 0, 0); | ||||
| } | ||||
| 
 | ||||
| static void lock_menu_callback(void* context, uint8_t index) { | ||||
|     furi_assert(context); | ||||
|     Dolphin* dolphin = context; | ||||
|     switch(index) { | ||||
|     // lock
 | ||||
|     case 0: | ||||
|         dolphin->locked = true; | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|         view_port_enabled_set(dolphin->lock_viewport, true); | ||||
|         DolphinViewLockMenuModel* model = view_get_model(dolphin->view_lockmenu); | ||||
| 
 | ||||
|         model->locked = true; | ||||
|         model->exit_timeout = 20; | ||||
| 
 | ||||
|         view_port_enabled_set(dolphin->lock_viewport, dolphin->locked); | ||||
|         view_commit_model(dolphin->view_lockmenu, true); | ||||
| 
 | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| @ -152,42 +179,24 @@ bool dolphin_view_lockmenu_input(InputEvent* event, void* context) { | ||||
| 
 | ||||
|     if(event->type != InputTypeShort) return false; | ||||
| 
 | ||||
|     DolphinViewLockMenuModel* model = view_get_model(dolphin->view_lockmenu); | ||||
| 
 | ||||
|     if(event->key == InputKeyUp) { | ||||
|         with_view_model( | ||||
|             dolphin->view_lockmenu, (DolphinViewMenuModel * model) { | ||||
|                 if(model->idx <= 0) | ||||
|                     model->idx = 0; | ||||
|                 else | ||||
|                     --model->idx; | ||||
|                 return true; | ||||
|             }); | ||||
|         model->idx = CLAMP(model->idx - 1, 2, 0); | ||||
|     } else if(event->key == InputKeyDown) { | ||||
|         with_view_model( | ||||
|             dolphin->view_lockmenu, (DolphinViewMenuModel * model) { | ||||
|                 if(model->idx >= 2) | ||||
|                     model->idx = 2; | ||||
|                 else | ||||
|                     ++model->idx; | ||||
|                 return true; | ||||
|             }); | ||||
|         model->idx = CLAMP(model->idx + 1, 2, 0); | ||||
|     } else if(event->key == InputKeyOk) { | ||||
|         with_view_model( | ||||
|             dolphin->view_lockmenu, (DolphinViewMenuModel * model) { | ||||
|         lock_menu_callback(context, model->idx); | ||||
|                 return true; | ||||
|             }); | ||||
|     } else if(event->key == InputKeyBack) { | ||||
|         with_view_model( | ||||
|             dolphin->view_lockmenu, (DolphinViewMenuModel * model) { | ||||
|         model->idx = 0; | ||||
|                 return true; | ||||
|             }); | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
| 
 | ||||
|         if(random() % 100 > 50) | ||||
|             dolphin_scene_handler_set_scene(dolphin, idle_scenes[random() % sizeof(idle_scenes)]); | ||||
|     } | ||||
| 
 | ||||
|     view_commit_model(dolphin->view_lockmenu, true); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| @ -195,27 +204,40 @@ bool dolphin_view_idle_down_input(InputEvent* event, void* context) { | ||||
|     furi_assert(event); | ||||
|     furi_assert(context); | ||||
|     Dolphin* dolphin = context; | ||||
|     DolphinViewStatsScreens current; | ||||
| 
 | ||||
|     if(event->type != InputTypeShort) return false; | ||||
| 
 | ||||
|     if((event->key == InputKeyLeft) || (event->key == InputKeyRight)) { | ||||
|         with_view_model( | ||||
|             dolphin->idle_view_down, (DolphinViewIdleDownModel * model) { | ||||
|                 model->show_fw_or_boot = !model->show_fw_or_boot; | ||||
|                 return true; | ||||
|             }); | ||||
|     DolphinViewStatsModel* model = view_get_model(dolphin->idle_view_dolphin_stats); | ||||
| 
 | ||||
|     current = model->screen; | ||||
| 
 | ||||
|     if(event->key == InputKeyDown) { | ||||
|         model->screen = (model->screen + 1) % DolphinViewStatsTotalCount; | ||||
|     } else if(event->key == InputKeyUp) { | ||||
|         model->screen = | ||||
|             ((model->screen - 1) + DolphinViewStatsTotalCount) % DolphinViewStatsTotalCount; | ||||
|     } | ||||
| 
 | ||||
|     view_commit_model(dolphin->idle_view_dolphin_stats, true); | ||||
| 
 | ||||
|     if(current == DolphinViewStatsMeta) { | ||||
|         if(event->key == InputKeyLeft) { | ||||
|             dolphin_deed(dolphin, DolphinDeedWrong); | ||||
|         } else if(event->key == InputKeyRight) { | ||||
|             dolphin_deed(dolphin, DolphinDeedIButtonRead); | ||||
|         } else if(event->key == InputKeyOk) { | ||||
|             dolphin_save(dolphin); | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if(event->key == InputKeyBack) { | ||||
|         with_view_model( | ||||
|             dolphin->idle_view_down, (DolphinViewIdleDownModel * model) { | ||||
|                 model->show_fw_or_boot = 0; | ||||
|                 return true; | ||||
|             }); | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| Dolphin* dolphin_alloc() { | ||||
| @ -229,10 +251,8 @@ Dolphin* dolphin_alloc() { | ||||
|     dolphin->menu_vm = furi_record_open("menu"); | ||||
|     // Scene thread
 | ||||
|     dolphin->scene_thread = furi_thread_alloc(); | ||||
| 
 | ||||
|     // GUI
 | ||||
|     dolphin->gui = furi_record_open("gui"); | ||||
| 
 | ||||
|     // Dispatcher
 | ||||
|     dolphin->idle_view_dispatcher = view_dispatcher_alloc(); | ||||
| 
 | ||||
| @ -250,46 +270,45 @@ Dolphin* dolphin_alloc() { | ||||
|     dolphin->idle_view_main = view_alloc(); | ||||
|     view_set_context(dolphin->idle_view_main, dolphin); | ||||
|     view_allocate_model( | ||||
|         dolphin->idle_view_main, ViewModelTypeLockFree, sizeof(DolphinViewIdleUpModel)); | ||||
|         dolphin->idle_view_main, ViewModelTypeLockFree, sizeof(DolphinViewMainModel)); | ||||
| 
 | ||||
|     view_set_draw_callback(dolphin->idle_view_main, dolphin_view_idle_main_draw); | ||||
|     view_set_input_callback(dolphin->idle_view_main, dolphin_view_idle_main_input); | ||||
|     view_dispatcher_add_view( | ||||
|         dolphin->idle_view_dispatcher, DolphinViewIdleMain, dolphin->idle_view_main); | ||||
| 
 | ||||
|     // Stats Idle View
 | ||||
|     dolphin->idle_view_up = view_alloc(); | ||||
|     view_set_context(dolphin->idle_view_up, dolphin); | ||||
| 
 | ||||
|     view_allocate_model( | ||||
|         dolphin->idle_view_up, ViewModelTypeLockFree, sizeof(DolphinViewMainModel)); | ||||
|     view_set_draw_callback(dolphin->idle_view_up, dolphin_view_idle_up_draw); | ||||
|     view_set_input_callback(dolphin->idle_view_up, dolphin_view_idle_up_input); | ||||
|     view_set_previous_callback(dolphin->idle_view_up, dolphin_view_idle_back); | ||||
|     view_dispatcher_add_view( | ||||
|         dolphin->idle_view_dispatcher, DolphinViewIdleUp, dolphin->idle_view_up); | ||||
| 
 | ||||
|     // Lock Menu View
 | ||||
|     dolphin->view_lockmenu = view_alloc(); | ||||
|     view_set_context(dolphin->view_lockmenu, dolphin); | ||||
|     view_allocate_model( | ||||
|         dolphin->view_lockmenu, ViewModelTypeLockFree, sizeof(DolphinViewMenuModel)); | ||||
|         dolphin->view_lockmenu, ViewModelTypeLockFree, sizeof(DolphinViewLockMenuModel)); | ||||
|     view_set_draw_callback(dolphin->view_lockmenu, dolphin_view_lockmenu_draw); | ||||
|     view_set_input_callback(dolphin->view_lockmenu, dolphin_view_lockmenu_input); | ||||
|     view_set_previous_callback(dolphin->view_lockmenu, dolphin_view_idle_back); | ||||
|     view_dispatcher_add_view( | ||||
|         dolphin->idle_view_dispatcher, DolphinViewLockMenu, dolphin->view_lockmenu); | ||||
| 
 | ||||
|     // Down Idle View
 | ||||
|     dolphin->idle_view_down = view_alloc(); | ||||
|     view_set_context(dolphin->idle_view_down, dolphin); | ||||
|     // default doors xpos
 | ||||
|     with_view_model( | ||||
|         dolphin->view_lockmenu, (DolphinViewLockMenuModel * model) { | ||||
|             model->door_left_x = -57; // defaults
 | ||||
|             model->door_right_x = 115; // defaults
 | ||||
|             return true; | ||||
|         }); | ||||
| 
 | ||||
|     dolphin->timeout_timer = | ||||
|         osTimerNew(lock_menu_refresh_handler, osTimerPeriodic, dolphin->event_queue, NULL); | ||||
| 
 | ||||
|     // Stats Idle View
 | ||||
|     dolphin->idle_view_dolphin_stats = view_alloc(); | ||||
|     view_set_context(dolphin->idle_view_dolphin_stats, dolphin); | ||||
|     view_allocate_model( | ||||
|         dolphin->idle_view_down, ViewModelTypeLockFree, sizeof(DolphinViewIdleDownModel)); | ||||
|     view_set_draw_callback(dolphin->idle_view_down, dolphin_view_idle_down_draw); | ||||
|     view_set_input_callback(dolphin->idle_view_down, dolphin_view_idle_down_input); | ||||
|     view_set_previous_callback(dolphin->idle_view_down, dolphin_view_idle_back); | ||||
|         dolphin->idle_view_dolphin_stats, ViewModelTypeLockFree, sizeof(DolphinViewStatsModel)); | ||||
|     view_set_draw_callback(dolphin->idle_view_dolphin_stats, dolphin_view_idle_down_draw); | ||||
|     view_set_input_callback(dolphin->idle_view_dolphin_stats, dolphin_view_idle_down_input); | ||||
|     view_set_previous_callback(dolphin->idle_view_dolphin_stats, dolphin_view_idle_back); | ||||
|     view_dispatcher_add_view( | ||||
|         dolphin->idle_view_dispatcher, DolphinViewIdleDown, dolphin->idle_view_down); | ||||
|         dolphin->idle_view_dispatcher, DolphinViewStats, dolphin->idle_view_dolphin_stats); | ||||
|     // HW Mismatch
 | ||||
|     dolphin->view_hw_mismatch = view_alloc(); | ||||
|     view_set_draw_callback(dolphin->view_hw_mismatch, dolphin_view_hw_mismatch_draw); | ||||
| @ -321,6 +340,8 @@ void dolphin_free(Dolphin* dolphin) { | ||||
|     view_port_free(dolphin->lock_viewport); | ||||
|     icon_free(dolphin->lock_icon); | ||||
| 
 | ||||
|     osTimerDelete(dolphin->timeout_timer); | ||||
| 
 | ||||
|     view_dispatcher_free(dolphin->idle_view_dispatcher); | ||||
| 
 | ||||
|     furi_record_close("gui"); | ||||
| @ -361,8 +382,9 @@ int32_t dolphin_task() { | ||||
|     } else { | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewFirstStart); | ||||
|     } | ||||
| 
 | ||||
|     with_view_model( | ||||
|         dolphin->idle_view_up, (DolphinViewIdleUpModel * model) { | ||||
|         dolphin->idle_view_dolphin_stats, (DolphinViewStatsModel * model) { | ||||
|             model->icounter = dolphin_state_get_icounter(dolphin->state); | ||||
|             model->butthurt = dolphin_state_get_butthurt(dolphin->state); | ||||
|             return true; | ||||
| @ -373,13 +395,27 @@ int32_t dolphin_task() { | ||||
|     if(!api_hal_version_do_i_belong_here()) { | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewHwMismatch); | ||||
|     } | ||||
| 
 | ||||
|     DolphinEvent event; | ||||
|     while(1) { | ||||
|         furi_check(osMessageQueueGet(dolphin->event_queue, &event, NULL, osWaitForever) == osOK); | ||||
|         if(event.type == DolphinEventTypeDeed) { | ||||
| 
 | ||||
|         DolphinViewLockMenuModel* lock_model = view_get_model(dolphin->view_lockmenu); | ||||
| 
 | ||||
|         if(lock_model->locked && lock_model->exit_timeout == 0 && | ||||
|            osTimerIsRunning(dolphin->timeout_timer)) { | ||||
|             osTimerStop(dolphin->timeout_timer); | ||||
|             osDelay(1); // smol enterprise delay
 | ||||
|             view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|         } | ||||
| 
 | ||||
|         if(event.type == DolphinEventTypeTick) { | ||||
|             view_commit_model(dolphin->view_lockmenu, true); | ||||
| 
 | ||||
|         } else if(event.type == DolphinEventTypeDeed) { | ||||
|             dolphin_state_on_deed(dolphin->state, event.deed); | ||||
|             with_view_model( | ||||
|                 dolphin->idle_view_up, (DolphinViewIdleUpModel * model) { | ||||
|                 dolphin->idle_view_dolphin_stats, (DolphinViewStatsModel * model) { | ||||
|                     model->icounter = dolphin_state_get_icounter(dolphin->state); | ||||
|                     model->butthurt = dolphin_state_get_butthurt(dolphin->state); | ||||
|                     return true; | ||||
|  | ||||
| @ -17,6 +17,7 @@ | ||||
| typedef enum { | ||||
|     DolphinEventTypeDeed, | ||||
|     DolphinEventTypeSave, | ||||
|     DolphinEventTypeTick, | ||||
| } DolphinEventType; | ||||
| 
 | ||||
| typedef struct { | ||||
| @ -40,7 +41,7 @@ struct Dolphin { | ||||
|     ViewDispatcher* idle_view_dispatcher; | ||||
|     View* idle_view_first_start; | ||||
|     View* idle_view_main; | ||||
|     View* idle_view_up; | ||||
|     View* idle_view_dolphin_stats; | ||||
|     View* idle_view_down; | ||||
|     View* idle_view_meta; | ||||
|     View* view_hw_mismatch; | ||||
| @ -50,6 +51,8 @@ struct Dolphin { | ||||
| 
 | ||||
|     bool locked; | ||||
|     uint8_t lock_count; | ||||
|     uint32_t lock_lastpress; | ||||
|     osTimerId_t timeout_timer; | ||||
| }; | ||||
| 
 | ||||
| // Temporary
 | ||||
|  | ||||
| @ -59,50 +59,63 @@ void dolphin_view_first_start_draw(Canvas* canvas, void* model) { | ||||
| void dolphin_view_idle_main_draw(Canvas* canvas, void* model) { | ||||
|     canvas_clear(canvas); | ||||
|     DolphinViewMainModel* m = model; | ||||
|     if(m->animation) canvas_draw_icon(canvas, 0, -3, m->animation); | ||||
|     if(m->animation) { | ||||
|         canvas_draw_icon(canvas, 0, -3, m->animation); | ||||
|     } | ||||
| 
 | ||||
| void dolphin_view_idle_up_draw(Canvas* canvas, void* model) { | ||||
|     DolphinViewIdleUpModel* m = model; | ||||
|     canvas_clear(canvas); | ||||
| 
 | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
|     canvas_set_font(canvas, FontPrimary); | ||||
|     canvas_draw_str(canvas, 2, 15, "Dolphin stats:"); | ||||
| 
 | ||||
|     char buffer[64]; | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
|     snprintf(buffer, 64, "Icounter: %ld", m->icounter); | ||||
|     canvas_draw_str(canvas, 5, 30, buffer); | ||||
|     snprintf(buffer, 64, "Butthurt: %ld", m->butthurt); | ||||
|     canvas_draw_str(canvas, 5, 40, buffer); | ||||
|     canvas_draw_str(canvas, 0, 53, "[< >] icounter value   [ok] save"); | ||||
|     if(m->hint_timeout > 0) { | ||||
|         m->hint_timeout--; | ||||
|         canvas_draw_icon_name(canvas, 13, 5, I_LockPopup_100x49); | ||||
|         elements_multiline_text(canvas, 65, 20, "To unlock\npress:"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void dolphin_view_lockmenu_draw(Canvas* canvas, void* model) { | ||||
|     DolphinViewMenuModel* m = model; | ||||
|     DolphinViewLockMenuModel* m = model; | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
|     canvas_draw_icon_name(canvas, 5, 0, I_DoorLeft_8x56); | ||||
|     canvas_draw_icon_name(canvas, 115, 0, I_DoorRight_8x56); | ||||
|     canvas_draw_icon_name(canvas, m->door_left_x, 0, I_DoorLeft_70x55); | ||||
|     canvas_draw_icon_name(canvas, m->door_right_x, 0, I_DoorRight_70x55); | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
| 
 | ||||
|     if(m->locked) { | ||||
|         m->exit_timeout--; | ||||
| 
 | ||||
|         m->door_left_x = CLAMP(m->door_left_x + 10, 0, -57); | ||||
|         m->door_right_x = CLAMP(m->door_right_x - 10, 115, 60); | ||||
| 
 | ||||
|         if(m->door_left_x > -10) { | ||||
|             canvas_set_font(canvas, FontPrimary); | ||||
|             elements_multiline_text_framed(canvas, 42, 30, "Locked"); | ||||
|         } | ||||
| 
 | ||||
|     } else { | ||||
|         m->door_left_x = CLAMP(m->door_left_x - 10, 0, -57); | ||||
|         m->door_right_x = CLAMP(m->door_right_x + 10, 115, 60); | ||||
| 
 | ||||
|         if(m->door_left_x == -57) { | ||||
|             for(uint8_t i = 0; i < 3; ++i) { | ||||
|                 canvas_draw_str_aligned( | ||||
|                     canvas, 64, 13 + (i * 17), AlignCenter, AlignCenter, Lockmenu_Items[i]); | ||||
|                 if(m->idx == i) elements_frame(canvas, 15, 5 + (i * 17), 98, 15); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void dolphin_view_idle_down_draw(Canvas* canvas, void* model) { | ||||
|     DolphinViewIdleDownModel* m = model; | ||||
|     DolphinViewStatsModel* m = model; | ||||
|     const Version* ver; | ||||
|     char buffer[64]; | ||||
| 
 | ||||
|     static const char* headers[] = {"Boot Version info:", "FW Version info:", "Dolphin info:"}; | ||||
| 
 | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
|     canvas_set_font(canvas, FontPrimary); | ||||
|     canvas_draw_str(canvas, 2, 13, m->show_fw_or_boot ? "Boot Version info:" : "FW Version info:"); | ||||
|     canvas_draw_str(canvas, 2, 13, headers[m->screen]); | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
| 
 | ||||
|     if(m->screen != DolphinViewStatsMeta) { | ||||
|         // Hardware version
 | ||||
|         snprintf( | ||||
|             buffer, | ||||
| @ -115,7 +128,7 @@ void dolphin_view_idle_down_draw(Canvas* canvas, void* model) { | ||||
|             api_hal_version_get_name_ptr()); | ||||
|         canvas_draw_str(canvas, 5, 23, buffer); | ||||
| 
 | ||||
|     ver = m->show_fw_or_boot ? api_hal_version_get_boot_version() : | ||||
|         ver = m->screen == DolphinViewStatsBoot ? api_hal_version_get_boot_version() : | ||||
|                                                   api_hal_version_get_fw_version(); | ||||
| 
 | ||||
|         if(!ver) { | ||||
| @ -124,16 +137,34 @@ void dolphin_view_idle_down_draw(Canvas* canvas, void* model) { | ||||
|         } | ||||
| 
 | ||||
|         snprintf( | ||||
|         buffer, sizeof(buffer), "%s [%s]", version_get_version(ver), version_get_builddate(ver)); | ||||
|             buffer, | ||||
|             sizeof(buffer), | ||||
|             "%s [%s]", | ||||
|             version_get_version(ver), | ||||
|             version_get_builddate(ver)); | ||||
|         canvas_draw_str(canvas, 5, 33, buffer); | ||||
| 
 | ||||
|         snprintf( | ||||
|         buffer, sizeof(buffer), "%s [%s]", version_get_githash(ver), version_get_gitbranchnum(ver)); | ||||
|             buffer, | ||||
|             sizeof(buffer), | ||||
|             "%s [%s]", | ||||
|             version_get_githash(ver), | ||||
|             version_get_gitbranchnum(ver)); | ||||
|         canvas_draw_str(canvas, 5, 43, buffer); | ||||
| 
 | ||||
|         snprintf( | ||||
|             buffer, sizeof(buffer), "[%s] %s", version_get_target(ver), version_get_gitbranch(ver)); | ||||
|         canvas_draw_str(canvas, 5, 53, buffer); | ||||
| 
 | ||||
|     } else { | ||||
|         char buffer[64]; | ||||
|         canvas_set_font(canvas, FontSecondary); | ||||
|         snprintf(buffer, 64, "Icounter: %ld", m->icounter); | ||||
|         canvas_draw_str(canvas, 5, 30, buffer); | ||||
|         snprintf(buffer, 64, "Butthurt: %ld", m->butthurt); | ||||
|         canvas_draw_str(canvas, 5, 40, buffer); | ||||
|         canvas_draw_str(canvas, 0, 53, "[< >] icounter value   [ok] save"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void dolphin_view_hw_mismatch_draw(Canvas* canvas, void* model) { | ||||
|  | ||||
| @ -6,16 +6,35 @@ | ||||
| #include <input/input.h> | ||||
| #include <furi.h> | ||||
| 
 | ||||
| // Idle scree
 | ||||
| #ifndef MAX | ||||
| #define MAX(x, y) (((x) > (y)) ? (x) : (y)) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MIN | ||||
| #define MIN(x, y) (((x) < (y)) ? (x) : (y)) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef CLAMP | ||||
| #define CLAMP(x, upper, lower) (MIN(upper, MAX(x, lower))) | ||||
| #endif | ||||
| 
 | ||||
| // Idle screen
 | ||||
| typedef enum { | ||||
|     DolphinViewIdleMain, | ||||
|     DolphinViewFirstStart, | ||||
|     DolphinViewIdleUp, | ||||
|     DolphinViewIdleDown, | ||||
|     DolphinViewStats, | ||||
|     DolphinViewHwMismatch, | ||||
|     DolphinViewLockMenu, | ||||
| } DolphinViewIdle; | ||||
| 
 | ||||
| // Debug info
 | ||||
| typedef enum { | ||||
|     DolphinViewStatsFw, | ||||
|     DolphinViewStatsBoot, | ||||
|     DolphinViewStatsMeta, | ||||
|     DolphinViewStatsTotalCount, | ||||
| } DolphinViewStatsScreens; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint32_t page; | ||||
| } DolphinViewFirstStartModel; | ||||
| @ -26,20 +45,21 @@ bool dolphin_view_first_start_input(InputEvent* event, void* context); | ||||
| typedef struct { | ||||
|     uint32_t icounter; | ||||
|     uint32_t butthurt; | ||||
| } DolphinViewIdleUpModel; | ||||
| 
 | ||||
| typedef struct { | ||||
|     bool show_fw_or_boot; | ||||
| } DolphinViewIdleDownModel; | ||||
|     DolphinViewStatsScreens screen; | ||||
| } DolphinViewStatsModel; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint8_t idx; | ||||
| } DolphinViewMenuModel; | ||||
|     int8_t door_left_x; | ||||
|     int8_t door_right_x; | ||||
|     uint8_t exit_timeout; | ||||
|     bool locked; | ||||
| } DolphinViewLockMenuModel; | ||||
| 
 | ||||
| typedef struct { | ||||
|     Icon* animation; | ||||
|     uint8_t scene_num; | ||||
| 
 | ||||
|     uint8_t hint_timeout; | ||||
| } DolphinViewMainModel; | ||||
| 
 | ||||
| void dolphin_view_idle_main_draw(Canvas* canvas, void* model); | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/DoorLeft_70x55.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Interface/DoorLeft_70x55.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 564 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/DoorRight_70x55.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Interface/DoorRight_70x55.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 570 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/LockPopup_100x49.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Interface/LockPopup_100x49.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 577 B | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 its your bedtime
						its your bedtime