#include #include #include #include #include #include #include #include #include #include "desktop_view_pin_timeout.h" struct DesktopViewPinTimeout { View* view; TimerHandle_t timer; DesktopViewPinTimeoutDoneCallback callback; void* context; }; typedef struct { uint32_t time_left; } DesktopViewPinTimeoutModel; void desktop_view_pin_timeout_set_callback( DesktopViewPinTimeout* instance, DesktopViewPinTimeoutDoneCallback callback, void* context) { furi_assert(instance); instance->callback = callback; instance->context = context; } static void desktop_view_pin_timeout_timer_callback(TimerHandle_t timer) { DesktopViewPinTimeout* instance = pvTimerGetTimerID(timer); bool stop = false; DesktopViewPinTimeoutModel* model = view_get_model(instance->view); if(model->time_left > 0) { --model->time_left; } else { stop = true; } view_commit_model(instance->view, true); if(stop) { xTimerStop(instance->timer, portMAX_DELAY); instance->callback(instance->context); } } static bool desktop_view_pin_timeout_input(InputEvent* event, void* context) { return true; } static void desktop_view_pin_timeout_draw(Canvas* canvas, void* _model) { furi_assert(canvas); furi_assert(_model); DesktopViewPinTimeoutModel* model = _model; canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 36, 31, "Wrong PIN!"); canvas_set_font(canvas, FontSecondary); char str[30] = {0}; snprintf(str, sizeof(str), "Timeout: %lds", model->time_left); canvas_draw_str_aligned(canvas, 64, 38, AlignCenter, AlignCenter, str); } void desktop_view_pin_timeout_free(DesktopViewPinTimeout* instance) { view_free(instance->view); xTimerDelete(instance->timer, portMAX_DELAY); free(instance); } DesktopViewPinTimeout* desktop_view_pin_timeout_alloc(void) { DesktopViewPinTimeout* instance = furi_alloc(sizeof(DesktopViewPinTimeout)); instance->timer = xTimerCreate( NULL, pdMS_TO_TICKS(1000), pdTRUE, instance, desktop_view_pin_timeout_timer_callback); instance->view = view_alloc(); view_allocate_model(instance->view, ViewModelTypeLockFree, sizeof(DesktopViewPinTimeoutModel)); view_set_context(instance->view, instance); view_set_draw_callback(instance->view, desktop_view_pin_timeout_draw); view_set_input_callback(instance->view, desktop_view_pin_timeout_input); return instance; } void desktop_view_pin_timeout_start(DesktopViewPinTimeout* instance, uint32_t time_left) { furi_assert(instance); DesktopViewPinTimeoutModel* model = view_get_model(instance->view); // no race - always called when timer is stopped model->time_left = time_left; view_commit_model(instance->view, true); xTimerStart(instance->timer, portMAX_DELAY); } View* desktop_view_pin_timeout_get_view(DesktopViewPinTimeout* instance) { furi_assert(instance); return instance->view; }