[FL-2152] New PIN lock (#989)
* [Fl-2152] New PIN Lock, part 1 * Fix errors & leaks, renaming * Add support to f6 * Fix error, remove duplicate code * Fix drawing corners of Lock Popup * FuriHal: insomnia if usb connected * Applications: cleanup timers use Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
@@ -81,7 +81,7 @@ OneShotView* one_shot_view_alloc(void) {
|
||||
OneShotView* view = furi_alloc(sizeof(OneShotView));
|
||||
view->view = view_alloc();
|
||||
view->update_timer =
|
||||
xTimerCreate("Update timer", 1000, pdTRUE, view, one_shot_view_update_timer_callback);
|
||||
xTimerCreate(NULL, 1000, pdTRUE, view, one_shot_view_update_timer_callback);
|
||||
|
||||
view_allocate_model(view->view, ViewModelTypeLocking, sizeof(OneShotViewModel));
|
||||
view_set_context(view->view, view);
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
#include "animations/animation_manager.h"
|
||||
#include "desktop/scenes/desktop_scene.h"
|
||||
#include "desktop/scenes/desktop_scene_i.h"
|
||||
#include "desktop/views/desktop_locked.h"
|
||||
#include "desktop_i.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <assets_icons.h>
|
||||
#include <gui/view_stack.h>
|
||||
@@ -12,23 +6,38 @@
|
||||
#include <portmacro.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "animations/animation_manager.h"
|
||||
#include "desktop/scenes/desktop_scene.h"
|
||||
#include "desktop/scenes/desktop_scene_i.h"
|
||||
#include "desktop/views/desktop_view_locked.h"
|
||||
#include "desktop/views/desktop_view_pin_input.h"
|
||||
#include "desktop/views/desktop_view_pin_timeout.h"
|
||||
#include "desktop_i.h"
|
||||
#include "desktop_helpers.h"
|
||||
|
||||
static void desktop_lock_icon_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(canvas);
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8);
|
||||
}
|
||||
|
||||
bool desktop_custom_event_callback(void* context, uint32_t event) {
|
||||
static bool desktop_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
return scene_manager_handle_custom_event(desktop->scene_manager, event);
|
||||
}
|
||||
|
||||
bool desktop_back_event_callback(void* context) {
|
||||
static bool desktop_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
return scene_manager_handle_back_event(desktop->scene_manager);
|
||||
}
|
||||
|
||||
static void desktop_tick_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
Desktop* app = context;
|
||||
scene_manager_handle_tick_event(app->scene_manager);
|
||||
}
|
||||
|
||||
Desktop* desktop_alloc() {
|
||||
Desktop* desktop = furi_alloc(sizeof(Desktop));
|
||||
|
||||
@@ -42,6 +51,8 @@ Desktop* desktop_alloc() {
|
||||
view_dispatcher_enable_queue(desktop->view_dispatcher);
|
||||
view_dispatcher_attach_to_gui(
|
||||
desktop->view_dispatcher, desktop->gui, ViewDispatcherTypeDesktop);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
desktop->view_dispatcher, desktop_tick_event_callback, 500);
|
||||
|
||||
view_dispatcher_set_event_callback_context(desktop->view_dispatcher, desktop);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
@@ -49,37 +60,60 @@ Desktop* desktop_alloc() {
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
desktop->view_dispatcher, desktop_back_event_callback);
|
||||
|
||||
desktop->locked_view = desktop_locked_alloc();
|
||||
desktop->lock_menu = desktop_lock_menu_alloc();
|
||||
desktop->debug_view = desktop_debug_alloc();
|
||||
desktop->first_start_view = desktop_first_start_alloc();
|
||||
desktop->hw_mismatch_popup = popup_alloc();
|
||||
desktop->code_input = code_input_alloc();
|
||||
desktop->locked_view = desktop_view_locked_alloc();
|
||||
desktop->pin_input_view = desktop_view_pin_input_alloc();
|
||||
desktop->pin_timeout_view = desktop_view_pin_timeout_alloc();
|
||||
|
||||
desktop->main_view_stack = view_stack_alloc();
|
||||
desktop->main_view = desktop_main_alloc();
|
||||
View* dolphin_view = animation_manager_get_animation_view(desktop->animation_manager);
|
||||
view_stack_add_view(desktop->main_view_stack, desktop_main_get_view(desktop->main_view));
|
||||
view_stack_add_view(desktop->main_view_stack, dolphin_view);
|
||||
view_stack_add_view(desktop->main_view_stack, desktop_locked_get_view(desktop->locked_view));
|
||||
view_stack_add_view(
|
||||
desktop->main_view_stack, desktop_view_locked_get_view(desktop->locked_view));
|
||||
|
||||
/* locked view (as animation view) attends in 2 scenes: main & locked,
|
||||
* because it has to draw "Unlocked" label on main scene */
|
||||
desktop->locked_view_stack = view_stack_alloc();
|
||||
view_stack_add_view(desktop->locked_view_stack, dolphin_view);
|
||||
view_stack_add_view(
|
||||
desktop->locked_view_stack, desktop_view_locked_get_view(desktop->locked_view));
|
||||
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher, DesktopViewMain, view_stack_get_view(desktop->main_view_stack));
|
||||
desktop->view_dispatcher,
|
||||
DesktopViewIdMain,
|
||||
view_stack_get_view(desktop->main_view_stack));
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher,
|
||||
DesktopViewLockMenu,
|
||||
DesktopViewIdLocked,
|
||||
view_stack_get_view(desktop->locked_view_stack));
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher,
|
||||
DesktopViewIdLockMenu,
|
||||
desktop_lock_menu_get_view(desktop->lock_menu));
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher, DesktopViewDebug, desktop_debug_get_view(desktop->debug_view));
|
||||
desktop->view_dispatcher, DesktopViewIdDebug, desktop_debug_get_view(desktop->debug_view));
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher,
|
||||
DesktopViewFirstStart,
|
||||
DesktopViewIdFirstStart,
|
||||
desktop_first_start_get_view(desktop->first_start_view));
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher,
|
||||
DesktopViewHwMismatch,
|
||||
DesktopViewIdHwMismatch,
|
||||
popup_get_view(desktop->hw_mismatch_popup));
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher, DesktopViewPinSetup, code_input_get_view(desktop->code_input));
|
||||
desktop->view_dispatcher,
|
||||
DesktopViewIdPinTimeout,
|
||||
desktop_view_pin_timeout_get_view(desktop->pin_timeout_view));
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher,
|
||||
DesktopViewIdPinInput,
|
||||
desktop_view_pin_input_get_view(desktop->pin_input_view));
|
||||
|
||||
// Lock icon
|
||||
desktop->lock_viewport = view_port_alloc();
|
||||
view_port_set_width(desktop->lock_viewport, icon_get_width(&I_Lock_8x8));
|
||||
@@ -93,27 +127,29 @@ Desktop* desktop_alloc() {
|
||||
void desktop_free(Desktop* desktop) {
|
||||
furi_assert(desktop);
|
||||
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewMain);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewLockMenu);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewLocked);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewDebug);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewFirstStart);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewHwMismatch);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewPinSetup);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdMain);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdDebug);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdFirstStart);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdHwMismatch);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinInput);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinTimeout);
|
||||
|
||||
view_dispatcher_free(desktop->view_dispatcher);
|
||||
scene_manager_free(desktop->scene_manager);
|
||||
|
||||
animation_manager_free(desktop->animation_manager);
|
||||
view_stack_free(desktop->main_view_stack);
|
||||
view_stack_free(desktop->locked_view_stack);
|
||||
desktop_main_free(desktop->main_view);
|
||||
view_stack_free(desktop->locked_view_stack);
|
||||
desktop_view_locked_free(desktop->locked_view);
|
||||
desktop_lock_menu_free(desktop->lock_menu);
|
||||
desktop_locked_free(desktop->locked_view);
|
||||
desktop_view_locked_free(desktop->locked_view);
|
||||
desktop_debug_free(desktop->debug_view);
|
||||
desktop_first_start_free(desktop->first_start_view);
|
||||
popup_free(desktop->hw_mismatch_popup);
|
||||
code_input_free(desktop->code_input);
|
||||
desktop_view_pin_timeout_free(desktop->pin_timeout_view);
|
||||
|
||||
osSemaphoreDelete(desktop->unload_animation_semaphore);
|
||||
|
||||
@@ -145,14 +181,18 @@ int32_t desktop_srv(void* p) {
|
||||
SAVE_DESKTOP_SETTINGS(&desktop->settings);
|
||||
}
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
|
||||
furi_hal_usb_disable();
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedWithPin);
|
||||
}
|
||||
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
|
||||
if(desktop->settings.pin_code.length > 0) {
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
||||
} else {
|
||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
||||
}
|
||||
}
|
||||
|
||||
if(desktop_is_first_start()) {
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneFirstStart);
|
||||
}
|
||||
|
||||
82
applications/desktop/desktop_helpers.c
Normal file
82
applications/desktop/desktop_helpers.c
Normal file
@@ -0,0 +1,82 @@
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <stddef.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/gui.h>
|
||||
|
||||
#include "desktop_helpers.h"
|
||||
#include "desktop_i.h"
|
||||
|
||||
static const NotificationSequence sequence_pin_fail = {
|
||||
&message_display_on,
|
||||
|
||||
&message_red_255,
|
||||
&message_vibro_on,
|
||||
&message_delay_100,
|
||||
&message_vibro_off,
|
||||
&message_red_0,
|
||||
|
||||
&message_delay_250,
|
||||
|
||||
&message_red_255,
|
||||
&message_vibro_on,
|
||||
&message_delay_100,
|
||||
&message_vibro_off,
|
||||
&message_red_0,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const uint8_t desktop_helpers_fails_timeout[] = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
30,
|
||||
60,
|
||||
90,
|
||||
120,
|
||||
150,
|
||||
180,
|
||||
/* +60 for every next fail */
|
||||
};
|
||||
|
||||
void desktop_helpers_emit_error_notification() {
|
||||
NotificationApp* notification = furi_record_open("notification");
|
||||
notification_message(notification, &sequence_pin_fail);
|
||||
furi_record_close("notification");
|
||||
}
|
||||
|
||||
void desktop_helpers_lock_system(Desktop* desktop, bool hard_lock) {
|
||||
view_port_enabled_set(desktop->lock_viewport, true);
|
||||
if(hard_lock) {
|
||||
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
|
||||
furi_hal_usb_disable();
|
||||
}
|
||||
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_set_lockdown(gui, true);
|
||||
furi_record_close("gui");
|
||||
}
|
||||
|
||||
void desktop_helpers_unlock_system(Desktop* desktop) {
|
||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
||||
furi_hal_usb_enable();
|
||||
view_port_enabled_set(desktop->lock_viewport, false);
|
||||
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_set_lockdown(gui, false);
|
||||
furi_record_close("gui");
|
||||
}
|
||||
|
||||
uint32_t desktop_helpers_get_pin_fail_timeout(uint32_t pin_fails) {
|
||||
uint32_t pin_timeout = 0;
|
||||
uint32_t max_index = COUNT_OF(desktop_helpers_fails_timeout) - 1;
|
||||
if(pin_fails <= max_index) {
|
||||
pin_timeout = desktop_helpers_fails_timeout[pin_fails];
|
||||
} else {
|
||||
pin_timeout = desktop_helpers_fails_timeout[max_index] + (pin_fails - max_index) * 60;
|
||||
}
|
||||
|
||||
return pin_timeout;
|
||||
}
|
||||
9
applications/desktop/desktop_helpers.h
Normal file
9
applications/desktop/desktop_helpers.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "desktop.h"
|
||||
|
||||
void desktop_helpers_emit_error_notification();
|
||||
void desktop_helpers_lock_system(Desktop* desktop, bool hard_lock);
|
||||
void desktop_helpers_unlock_system(Desktop* desktop);
|
||||
uint32_t desktop_helpers_get_pin_fail_timeout(uint32_t pin_fails);
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
#include "desktop.h"
|
||||
#include "animations/animation_manager.h"
|
||||
#include "views/desktop_main.h"
|
||||
#include "views/desktop_first_start.h"
|
||||
#include "views/desktop_lock_menu.h"
|
||||
#include "views/desktop_locked.h"
|
||||
#include "views/desktop_debug.h"
|
||||
#include "views/desktop_view_pin_timeout.h"
|
||||
#include "views/desktop_view_pin_input.h"
|
||||
#include "views/desktop_view_locked.h"
|
||||
#include "views/desktop_view_main.h"
|
||||
#include "views/desktop_view_first_start.h"
|
||||
#include "views/desktop_view_lock_menu.h"
|
||||
#include "views/desktop_view_debug.h"
|
||||
#include "desktop/desktop_settings/desktop_settings.h"
|
||||
|
||||
#include <furi.h>
|
||||
@@ -14,21 +16,21 @@
|
||||
#include <gui/view_stack.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/modules/code_input.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#define STATUS_BAR_Y_SHIFT 13
|
||||
|
||||
typedef enum {
|
||||
DesktopViewMain,
|
||||
DesktopViewLockMenu,
|
||||
DesktopViewLocked,
|
||||
DesktopViewDebug,
|
||||
DesktopViewFirstStart,
|
||||
DesktopViewHwMismatch,
|
||||
DesktopViewPinSetup,
|
||||
DesktopViewTotal,
|
||||
} DesktopViewEnum;
|
||||
DesktopViewIdMain,
|
||||
DesktopViewIdLockMenu,
|
||||
DesktopViewIdLocked,
|
||||
DesktopViewIdDebug,
|
||||
DesktopViewIdFirstStart,
|
||||
DesktopViewIdHwMismatch,
|
||||
DesktopViewIdPinInput,
|
||||
DesktopViewIdPinTimeout,
|
||||
DesktopViewIdTotal,
|
||||
} DesktopViewId;
|
||||
|
||||
struct Desktop {
|
||||
// Scene
|
||||
@@ -42,16 +44,15 @@ struct Desktop {
|
||||
Popup* hw_mismatch_popup;
|
||||
DesktopLockMenuView* lock_menu;
|
||||
DesktopDebugView* debug_view;
|
||||
CodeInput* code_input;
|
||||
|
||||
DesktopViewLocked* locked_view;
|
||||
DesktopMainView* main_view;
|
||||
DesktopLockedView* locked_view;
|
||||
DesktopViewPinTimeout* pin_timeout_view;
|
||||
|
||||
ViewStack* main_view_stack;
|
||||
ViewStack* locked_view_stack;
|
||||
|
||||
DesktopSettings settings;
|
||||
PinCode pincode_buffer;
|
||||
DesktopViewPinInput* pin_input_view;
|
||||
|
||||
ViewPort* lock_viewport;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <toolbox/saved_struct.h>
|
||||
@@ -9,6 +10,8 @@
|
||||
#define DESKTOP_SETTINGS_MAGIC (0x17)
|
||||
#define PIN_MAX_LENGTH 12
|
||||
|
||||
#define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup"
|
||||
|
||||
#define SAVE_DESKTOP_SETTINGS(x) \
|
||||
saved_struct_save( \
|
||||
DESKTOP_SETTINGS_PATH, \
|
||||
@@ -25,12 +28,27 @@
|
||||
DESKTOP_SETTINGS_MAGIC, \
|
||||
DESKTOP_SETTINGS_VER)
|
||||
|
||||
#define MAX_PIN_SIZE 10
|
||||
#define MIN_PIN_SIZE 4
|
||||
|
||||
typedef struct {
|
||||
InputKey data[MAX_PIN_SIZE];
|
||||
uint8_t length;
|
||||
uint8_t data[PIN_MAX_LENGTH];
|
||||
} PinCode;
|
||||
|
||||
typedef struct {
|
||||
uint16_t favorite;
|
||||
PinCode pincode;
|
||||
PinCode pin_code;
|
||||
} DesktopSettings;
|
||||
|
||||
static inline bool pins_are_equal(const PinCode* pin_code1, const PinCode* pin_code2) {
|
||||
furi_assert(pin_code1);
|
||||
furi_assert(pin_code2);
|
||||
bool result = false;
|
||||
|
||||
if(pin_code1->length == pin_code2->length) {
|
||||
result = !memcmp(pin_code1->data, pin_code2->data, pin_code1->length);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "desktop_settings_app.h"
|
||||
#include <furi.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#include "desktop_settings_app.h"
|
||||
#include "scenes/desktop_settings_scene.h"
|
||||
#include "../views/desktop_view_pin_input.h"
|
||||
|
||||
static bool desktop_settings_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
@@ -30,17 +34,28 @@ DesktopSettingsApp* desktop_settings_app_alloc() {
|
||||
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
app->popup = popup_alloc();
|
||||
app->submenu = submenu_alloc();
|
||||
app->pin_input_view = desktop_view_pin_input_alloc();
|
||||
app->pin_setup_howto_view = desktop_settings_view_pin_setup_howto_alloc();
|
||||
app->pin_setup_howto2_view = desktop_settings_view_pin_setup_howto2_alloc();
|
||||
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, DesktopSettingsAppViewMenu, submenu_get_view(app->submenu));
|
||||
|
||||
app->code_input = code_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, DesktopSettingsAppViewIdPopup, popup_get_view(app->popup));
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
DesktopSettingsAppViewPincodeInput,
|
||||
code_input_get_view(app->code_input));
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart);
|
||||
DesktopSettingsAppViewIdPinInput,
|
||||
desktop_view_pin_input_get_view(app->pin_input_view));
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
DesktopSettingsAppViewIdPinSetupHowto,
|
||||
desktop_settings_view_pin_setup_howto_get_view(app->pin_setup_howto_view));
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
DesktopSettingsAppViewIdPinSetupHowto2,
|
||||
desktop_settings_view_pin_setup_howto2_get_view(app->pin_setup_howto2_view));
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -48,9 +63,15 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
|
||||
furi_assert(app);
|
||||
// Variable item list
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPopup);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto2);
|
||||
submenu_free(app->submenu);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewPincodeInput);
|
||||
code_input_free(app->code_input);
|
||||
popup_free(app->popup);
|
||||
desktop_view_pin_input_free(app->pin_input_view);
|
||||
desktop_settings_view_pin_setup_howto_free(app->pin_setup_howto_view);
|
||||
desktop_settings_view_pin_setup_howto2_free(app->pin_setup_howto2_view);
|
||||
// View dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
scene_manager_free(app->scene_manager);
|
||||
@@ -62,6 +83,12 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
|
||||
extern int32_t desktop_settings_app(void* p) {
|
||||
DesktopSettingsApp* app = desktop_settings_app_alloc();
|
||||
LOAD_DESKTOP_SETTINGS(&app->settings);
|
||||
if(!strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG)) {
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto);
|
||||
} else {
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart);
|
||||
}
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
desktop_settings_app_free(app);
|
||||
return 0;
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/code_input.h>
|
||||
|
||||
#include "desktop_settings.h"
|
||||
|
||||
typedef enum {
|
||||
CodeEventsSetPin,
|
||||
CodeEventsChangePin,
|
||||
CodeEventsDisablePin,
|
||||
} CodeEventsEnum;
|
||||
#include "desktop/views/desktop_view_pin_input.h"
|
||||
#include "views/desktop_settings_view_pin_setup_howto.h"
|
||||
#include "views/desktop_settings_view_pin_setup_howto2.h"
|
||||
|
||||
typedef enum {
|
||||
DesktopSettingsAppViewMenu,
|
||||
DesktopSettingsAppViewPincodeInput,
|
||||
DesktopSettingsAppViewIdPopup,
|
||||
DesktopSettingsAppViewIdPinInput,
|
||||
DesktopSettingsAppViewIdPinSetupHowto,
|
||||
DesktopSettingsAppViewIdPinSetupHowto2,
|
||||
} DesktopSettingsAppView;
|
||||
|
||||
typedef struct {
|
||||
@@ -26,7 +26,13 @@ typedef struct {
|
||||
SceneManager* scene_manager;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Submenu* submenu;
|
||||
CodeInput* code_input;
|
||||
Popup* popup;
|
||||
DesktopViewPinInput* pin_input_view;
|
||||
DesktopSettingsViewPinSetupHowto* pin_setup_howto_view;
|
||||
DesktopSettingsViewPinSetupHowto2* pin_setup_howto2_view;
|
||||
|
||||
PinCode pincode_buffer;
|
||||
bool pincode_buffer_filled;
|
||||
|
||||
uint8_t menu_idx;
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
ADD_SCENE(desktop_settings, start, Start)
|
||||
ADD_SCENE(desktop_settings, favorite, Favorite)
|
||||
ADD_SCENE(desktop_settings, pincode_menu, PinCodeMenu)
|
||||
ADD_SCENE(desktop_settings, pincode_input, PinCodeInput)
|
||||
ADD_SCENE(desktop_settings, pin_menu, PinMenu)
|
||||
|
||||
ADD_SCENE(desktop_settings, pin_auth, PinAuth)
|
||||
ADD_SCENE(desktop_settings, pin_error, PinError)
|
||||
ADD_SCENE(desktop_settings, pin_disable, PinDisable)
|
||||
ADD_SCENE(desktop_settings, pin_setup, PinSetup)
|
||||
ADD_SCENE(desktop_settings, pin_setup_howto, PinSetupHowto)
|
||||
ADD_SCENE(desktop_settings, pin_setup_howto2, PinSetupHowto2)
|
||||
ADD_SCENE(desktop_settings, pin_setup_done, PinSetupDone)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define SCENE_STATE_PIN_AUTH_DISABLE (0)
|
||||
#define SCENE_STATE_PIN_AUTH_CHANGE_PIN (1)
|
||||
|
||||
#define SCENE_STATE_PIN_ERROR_MISMATCH (0)
|
||||
#define SCENE_STATE_PIN_ERROR_WRONG (1)
|
||||
@@ -0,0 +1,95 @@
|
||||
#include <stdint.h>
|
||||
#include <furi/check.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "desktop/desktop_settings/desktop_settings.h"
|
||||
#include "desktop/views/desktop_view_pin_input.h"
|
||||
#include "desktop_settings_scene.h"
|
||||
#include "desktop_settings_scene_i.h"
|
||||
|
||||
#define SCENE_EVENT_EXIT (0U)
|
||||
#define SCENE_EVENT_PINS_EQUAL (1U)
|
||||
#define SCENE_EVENT_PINS_DIFFERENT (2U)
|
||||
|
||||
static void pin_auth_done_callback(const PinCode* pin_code, void* context) {
|
||||
furi_assert(pin_code);
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
|
||||
app->pincode_buffer = *pin_code;
|
||||
if(pins_are_equal(&app->settings.pin_code, pin_code)) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_EQUAL);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_DIFFERENT);
|
||||
}
|
||||
}
|
||||
|
||||
static void pin_auth_back_callback(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT);
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_auth_on_enter(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
|
||||
LOAD_DESKTOP_SETTINGS(&app->settings);
|
||||
furi_assert(app->settings.pin_code.length > 0);
|
||||
|
||||
desktop_view_pin_input_set_context(app->pin_input_view, app);
|
||||
desktop_view_pin_input_set_back_callback(app->pin_input_view, pin_auth_back_callback);
|
||||
desktop_view_pin_input_set_done_callback(app->pin_input_view, pin_auth_done_callback);
|
||||
desktop_view_pin_input_set_label_button(app->pin_input_view, "OK");
|
||||
desktop_view_pin_input_set_label_primary(app->pin_input_view, 0, 0, NULL);
|
||||
desktop_view_pin_input_set_label_secondary(
|
||||
app->pin_input_view, 0, 8, "Enter your current PIN:");
|
||||
desktop_view_pin_input_reset_pin(app->pin_input_view);
|
||||
desktop_view_pin_input_unlock_input(app->pin_input_view);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pin_auth_on_event(void* context, SceneManagerEvent event) {
|
||||
DesktopSettingsApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SCENE_EVENT_PINS_DIFFERENT:
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, DesktopSettingsAppScenePinError, SCENE_STATE_PIN_ERROR_WRONG);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinError);
|
||||
consumed = true;
|
||||
break;
|
||||
case SCENE_EVENT_PINS_EQUAL: {
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppScenePinAuth);
|
||||
if(state == SCENE_STATE_PIN_AUTH_CHANGE_PIN) {
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto);
|
||||
} else if(state == SCENE_STATE_PIN_AUTH_DISABLE) {
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinDisable);
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
case SCENE_EVENT_EXIT:
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, DesktopSettingsAppScenePinMenu);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_auth_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL);
|
||||
desktop_view_pin_input_set_done_callback(app->pin_input_view, NULL);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#include <stdint.h>
|
||||
#include <furi/check.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/popup.h>
|
||||
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "../desktop_settings.h"
|
||||
#include "desktop/desktop_settings/desktop_settings.h"
|
||||
#include "desktop_settings_scene.h"
|
||||
|
||||
#define SCENE_EVENT_EXIT (0U)
|
||||
|
||||
static void pin_disable_back_callback(void* context) {
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT);
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_disable_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
app->settings.pin_code.length = 0;
|
||||
memset(app->settings.pin_code.data, '0', sizeof(app->settings.pin_code.data));
|
||||
SAVE_DESKTOP_SETTINGS(&app->settings);
|
||||
|
||||
popup_set_context(app->popup, app);
|
||||
popup_set_callback(app->popup, pin_disable_back_callback);
|
||||
popup_set_icon(app->popup, 0, 2, &I_DolphinMafia_115x62);
|
||||
popup_set_header(app->popup, "PIN\ndeleted!", 95, 9, AlignCenter, AlignCenter);
|
||||
popup_set_timeout(app->popup, 1500);
|
||||
popup_enable_timeout(app->popup);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPopup);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pin_disable_on_event(void* context, SceneManagerEvent event) {
|
||||
DesktopSettingsApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SCENE_EVENT_EXIT:
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, DesktopSettingsAppScenePinMenu);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_disable_on_exit(void* context) {
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#include <stdint.h>
|
||||
#include <furi/check.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#include "desktop/desktop_settings/desktop_settings.h"
|
||||
#include "desktop/views/desktop_view_pin_input.h"
|
||||
#include "desktop_settings_scene.h"
|
||||
#include "desktop_settings_scene_i.h"
|
||||
#include "../../desktop_helpers.h"
|
||||
#include "../desktop_settings_app.h"
|
||||
|
||||
#define SCENE_EVENT_EXIT (0U)
|
||||
|
||||
static void pin_error_back_callback(void* context) {
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT);
|
||||
}
|
||||
|
||||
static void pin_error_done_callback(const PinCode* pin_code, void* context) {
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT);
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_error_on_enter(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
desktop_helpers_emit_error_notification();
|
||||
|
||||
desktop_view_pin_input_set_context(app->pin_input_view, app);
|
||||
desktop_view_pin_input_set_back_callback(app->pin_input_view, pin_error_back_callback);
|
||||
desktop_view_pin_input_set_done_callback(app->pin_input_view, pin_error_done_callback);
|
||||
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppScenePinError);
|
||||
if(state == SCENE_STATE_PIN_ERROR_MISMATCH) {
|
||||
desktop_view_pin_input_set_label_primary(app->pin_input_view, 29, 8, "PIN mismatch!");
|
||||
} else if(state == SCENE_STATE_PIN_ERROR_WRONG) {
|
||||
desktop_view_pin_input_set_label_primary(app->pin_input_view, 35, 8, "Wrong PIN!");
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
desktop_view_pin_input_set_label_secondary(app->pin_input_view, 0, 8, NULL);
|
||||
desktop_view_pin_input_set_label_button(app->pin_input_view, "Retry");
|
||||
desktop_view_pin_input_lock_input(app->pin_input_view);
|
||||
desktop_view_pin_input_set_pin(app->pin_input_view, &app->pincode_buffer);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pin_error_on_event(void* context, SceneManagerEvent event) {
|
||||
DesktopSettingsApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SCENE_EVENT_EXIT:
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_error_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
desktop_view_pin_input_unlock_input(app->pin_input_view);
|
||||
desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL);
|
||||
desktop_view_pin_input_set_done_callback(app->pin_input_view, NULL);
|
||||
}
|
||||
@@ -1,38 +1,45 @@
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "applications.h"
|
||||
#include "desktop_settings_scene.h"
|
||||
#include <gui/scene_manager.h>
|
||||
#include <applications.h>
|
||||
|
||||
static void desktop_settings_scene_pincode_menu_submenu_callback(void* context, uint32_t index) {
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "desktop_settings_scene.h"
|
||||
#include "desktop_settings_scene_i.h"
|
||||
|
||||
#define SCENE_EVENT_SET_PIN 0
|
||||
#define SCENE_EVENT_CHANGE_PIN 1
|
||||
#define SCENE_EVENT_DISABLE_PIN 2
|
||||
|
||||
static void desktop_settings_scene_pin_menu_submenu_callback(void* context, uint32_t index) {
|
||||
DesktopSettingsApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pincode_menu_on_enter(void* context) {
|
||||
void desktop_settings_scene_pin_menu_on_enter(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
Submenu* submenu = app->submenu;
|
||||
submenu_reset(submenu);
|
||||
|
||||
if(!app->settings.pincode.length) {
|
||||
if(!app->settings.pin_code.length) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Set Pin",
|
||||
CodeEventsSetPin,
|
||||
desktop_settings_scene_pincode_menu_submenu_callback,
|
||||
SCENE_EVENT_SET_PIN,
|
||||
desktop_settings_scene_pin_menu_submenu_callback,
|
||||
app);
|
||||
|
||||
} else {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Change Pin",
|
||||
CodeEventsChangePin,
|
||||
desktop_settings_scene_pincode_menu_submenu_callback,
|
||||
SCENE_EVENT_CHANGE_PIN,
|
||||
desktop_settings_scene_pin_menu_submenu_callback,
|
||||
app);
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Disable",
|
||||
CodeEventsDisablePin,
|
||||
desktop_settings_scene_pincode_menu_submenu_callback,
|
||||
SCENE_EVENT_DISABLE_PIN,
|
||||
desktop_settings_scene_pin_menu_submenu_callback,
|
||||
app);
|
||||
}
|
||||
|
||||
@@ -41,28 +48,28 @@ void desktop_settings_scene_pincode_menu_on_enter(void* context) {
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pincode_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
bool desktop_settings_scene_pin_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
DesktopSettingsApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case CodeEventsSetPin:
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, DesktopSettingsAppScenePinCodeInput, event.event);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeInput);
|
||||
case SCENE_EVENT_SET_PIN:
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto);
|
||||
consumed = true;
|
||||
break;
|
||||
case CodeEventsChangePin:
|
||||
case SCENE_EVENT_CHANGE_PIN:
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, DesktopSettingsAppScenePinCodeInput, event.event);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeInput);
|
||||
app->scene_manager,
|
||||
DesktopSettingsAppScenePinAuth,
|
||||
SCENE_STATE_PIN_AUTH_CHANGE_PIN);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinAuth);
|
||||
consumed = true;
|
||||
break;
|
||||
case CodeEventsDisablePin:
|
||||
case SCENE_EVENT_DISABLE_PIN:
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, DesktopSettingsAppScenePinCodeInput, event.event);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeInput);
|
||||
app->scene_manager, DesktopSettingsAppScenePinAuth, SCENE_STATE_PIN_AUTH_DISABLE);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinAuth);
|
||||
consumed = true;
|
||||
break;
|
||||
default:
|
||||
@@ -73,7 +80,7 @@ bool desktop_settings_scene_pincode_menu_on_event(void* context, SceneManagerEve
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pincode_menu_on_exit(void* context) {
|
||||
void desktop_settings_scene_pin_menu_on_exit(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
submenu_reset(app->submenu);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
#include <stdint.h>
|
||||
#include <furi/check.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "desktop/desktop_settings/desktop_settings.h"
|
||||
#include "desktop/views/desktop_view_pin_input.h"
|
||||
#include "desktop_settings_scene.h"
|
||||
#include "desktop_settings_scene_i.h"
|
||||
|
||||
#define SCENE_EVENT_EXIT (0U)
|
||||
#define SCENE_EVENT_1ST_PIN_ENTERED (1U)
|
||||
#define SCENE_EVENT_PINS_EQUAL (2U)
|
||||
#define SCENE_EVENT_PINS_DIFFERENT (3U)
|
||||
|
||||
static void pin_setup_done_callback(const PinCode* pin_code, void* context) {
|
||||
furi_assert(pin_code);
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
|
||||
if(!app->pincode_buffer_filled) {
|
||||
app->pincode_buffer = *pin_code;
|
||||
app->pincode_buffer_filled = true;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_1ST_PIN_ENTERED);
|
||||
} else {
|
||||
app->pincode_buffer_filled = false;
|
||||
if(pins_are_equal(&app->pincode_buffer, pin_code)) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_EQUAL);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_DIFFERENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pin_setup_back_callback(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT);
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_setup_on_enter(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
|
||||
app->pincode_buffer_filled = false;
|
||||
desktop_view_pin_input_set_context(app->pin_input_view, app);
|
||||
desktop_view_pin_input_set_back_callback(app->pin_input_view, pin_setup_back_callback);
|
||||
desktop_view_pin_input_set_done_callback(app->pin_input_view, pin_setup_done_callback);
|
||||
desktop_view_pin_input_set_label_button(app->pin_input_view, "OK");
|
||||
desktop_view_pin_input_set_label_primary(app->pin_input_view, 0, 0, NULL);
|
||||
desktop_view_pin_input_set_label_secondary(
|
||||
app->pin_input_view, 0, 8, "Enter from 4 to 10 arrows:");
|
||||
desktop_view_pin_input_reset_pin(app->pin_input_view);
|
||||
desktop_view_pin_input_unlock_input(app->pin_input_view);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pin_setup_on_event(void* context, SceneManagerEvent event) {
|
||||
DesktopSettingsApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SCENE_EVENT_1ST_PIN_ENTERED:
|
||||
desktop_view_pin_input_set_label_button(app->pin_input_view, "OK");
|
||||
desktop_view_pin_input_set_label_primary(app->pin_input_view, 0, 0, NULL);
|
||||
desktop_view_pin_input_set_label_secondary(
|
||||
app->pin_input_view, 0, 8, "Confirm your PIN:");
|
||||
desktop_view_pin_input_reset_pin(app->pin_input_view);
|
||||
desktop_view_pin_input_unlock_input(app->pin_input_view);
|
||||
consumed = true;
|
||||
break;
|
||||
case SCENE_EVENT_PINS_DIFFERENT:
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager,
|
||||
DesktopSettingsAppScenePinError,
|
||||
SCENE_STATE_PIN_ERROR_MISMATCH);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinError);
|
||||
consumed = true;
|
||||
break;
|
||||
case SCENE_EVENT_PINS_EQUAL:
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto2);
|
||||
consumed = true;
|
||||
break;
|
||||
case SCENE_EVENT_EXIT: {
|
||||
uint32_t scene_found;
|
||||
scene_found = scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, DesktopSettingsAppScenePinMenu);
|
||||
if(!scene_found) {
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_setup_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL);
|
||||
desktop_view_pin_input_set_done_callback(app->pin_input_view, NULL);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#include <furi.h>
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <stdint.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "desktop/desktop_settings/desktop_settings.h"
|
||||
#include "desktop/views/desktop_view_pin_input.h"
|
||||
#include "desktop_settings_scene.h"
|
||||
|
||||
#define SCENE_EVENT_DONE (0U)
|
||||
|
||||
static void pin_setup_done_callback(const PinCode* pin_code, void* context) {
|
||||
furi_assert(pin_code);
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_DONE);
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_setup_done_on_enter(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
|
||||
app->settings.pin_code = app->pincode_buffer;
|
||||
SAVE_DESKTOP_SETTINGS(&app->settings);
|
||||
NotificationApp* notification = furi_record_open("notification");
|
||||
notification_message(notification, &sequence_single_vibro);
|
||||
furi_record_close("notification");
|
||||
|
||||
desktop_view_pin_input_set_context(app->pin_input_view, app);
|
||||
desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL);
|
||||
desktop_view_pin_input_set_done_callback(app->pin_input_view, pin_setup_done_callback);
|
||||
desktop_view_pin_input_set_pin(app->pin_input_view, &app->settings.pin_code);
|
||||
desktop_view_pin_input_set_label_button(app->pin_input_view, "Done");
|
||||
desktop_view_pin_input_set_label_primary(app->pin_input_view, 29, 8, "PIN activated!");
|
||||
desktop_view_pin_input_set_label_secondary(
|
||||
app->pin_input_view, 7, 45, "Remember or write it down");
|
||||
desktop_view_pin_input_lock_input(app->pin_input_view);
|
||||
desktop_view_pin_input_set_pin_position(app->pin_input_view, 64, 24);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pin_setup_done_on_event(void* context, SceneManagerEvent event) {
|
||||
DesktopSettingsApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SCENE_EVENT_DONE: {
|
||||
bool scene_found = false;
|
||||
scene_found = scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, DesktopSettingsAppScenePinMenu);
|
||||
if(!scene_found) {
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = true;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_setup_done_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
DesktopSettingsApp* app = context;
|
||||
desktop_view_pin_input_set_pin_position(app->pin_input_view, 64, 32);
|
||||
desktop_view_pin_input_set_back_callback(app->pin_input_view, NULL);
|
||||
desktop_view_pin_input_set_done_callback(app->pin_input_view, NULL);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <furi.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
|
||||
#include "desktop_settings_scene.h"
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "../views/desktop_settings_view_pin_setup_howto.h"
|
||||
|
||||
#define SCENE_EXIT_EVENT (0U)
|
||||
|
||||
static void desktop_settings_scene_pin_lock_done_callback(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EXIT_EVENT);
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_setup_howto_on_enter(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
|
||||
desktop_settings_view_pin_setup_howto_set_callback(
|
||||
app->pin_setup_howto_view, desktop_settings_scene_pin_lock_done_callback, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pin_setup_howto_on_event(void* context, SceneManagerEvent event) {
|
||||
DesktopSettingsApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SCENE_EXIT_EVENT:
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetup);
|
||||
consumed = true;
|
||||
break;
|
||||
default:
|
||||
furi_assert(0);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_setup_howto_on_exit(void* context) {
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#include <furi.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "desktop_settings_scene.h"
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "../views/desktop_settings_view_pin_setup_howto2.h"
|
||||
|
||||
#define SCENE_EXIT_EVENT (0U)
|
||||
#define SCENE_DONE_EVENT (1U)
|
||||
|
||||
static void desktop_settings_scene_pin_setup_howto2_done_callback(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_DONE_EVENT);
|
||||
}
|
||||
|
||||
static void desktop_settings_scene_pin_setup_howto2_exit_callback(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EXIT_EVENT);
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_setup_howto2_on_enter(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
|
||||
desktop_settings_view_pin_setup_howto2_set_context(app->pin_setup_howto2_view, app);
|
||||
desktop_settings_view_pin_setup_howto2_set_ok_callback(
|
||||
app->pin_setup_howto2_view, desktop_settings_scene_pin_setup_howto2_done_callback);
|
||||
desktop_settings_view_pin_setup_howto2_set_cancel_callback(
|
||||
app->pin_setup_howto2_view, desktop_settings_scene_pin_setup_howto2_exit_callback);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto2);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pin_setup_howto2_on_event(void* context, SceneManagerEvent event) {
|
||||
DesktopSettingsApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SCENE_DONE_EVENT: {
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupDone);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
case SCENE_EXIT_EVENT: {
|
||||
bool scene_found = false;
|
||||
scene_found = scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, DesktopSettingsAppScenePinMenu);
|
||||
if(!scene_found) {
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
furi_assert(0);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pin_setup_howto2_on_exit(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
desktop_settings_view_pin_setup_howto2_set_ok_callback(app->pin_setup_howto2_view, NULL);
|
||||
desktop_settings_view_pin_setup_howto2_set_cancel_callback(app->pin_setup_howto2_view, NULL);
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "desktop_settings_scene.h"
|
||||
|
||||
#define SCENE_EXIT_EVENT (0U)
|
||||
|
||||
void desktop_settings_scene_ok_callback(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppScenePinCodeInput);
|
||||
|
||||
if(state == CodeEventsDisablePin) {
|
||||
memset(app->settings.pincode.data, 0, app->settings.pincode.length * sizeof(uint8_t));
|
||||
app->settings.pincode.length = 0;
|
||||
}
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EXIT_EVENT);
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pincode_input_on_enter(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
CodeInput* code_input = app->code_input;
|
||||
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppScenePinCodeInput);
|
||||
bool update = state != CodeEventsDisablePin;
|
||||
|
||||
code_input_set_header_text(code_input, "PIN Code Setup");
|
||||
code_input_set_result_callback(
|
||||
code_input,
|
||||
desktop_settings_scene_ok_callback,
|
||||
NULL,
|
||||
app,
|
||||
app->settings.pincode.data,
|
||||
&app->settings.pincode.length,
|
||||
update);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewPincodeInput);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pincode_input_on_event(void* context, SceneManagerEvent event) {
|
||||
DesktopSettingsApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SCENE_EXIT_EVENT:
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pincode_input_on_exit(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
SAVE_DESKTOP_SETTINGS(&app->settings);
|
||||
code_input_set_result_callback(app->code_input, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
code_input_set_header_text(app->code_input, "");
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
#include <applications.h>
|
||||
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "applications.h"
|
||||
#include "desktop_settings_scene.h"
|
||||
|
||||
enum DesktopSettingsStartSubmenuIndex {
|
||||
DesktopSettingsStartSubmenuIndexFavorite,
|
||||
DesktopSettingsStartSubmenuIndexPinSetup,
|
||||
};
|
||||
#define SCENE_EVENT_SELECT_FAVORITE 0
|
||||
#define SCENE_EVENT_SELECT_PIN_SETUP 1
|
||||
|
||||
static void desktop_settings_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
DesktopSettingsApp* app = context;
|
||||
@@ -19,14 +18,14 @@ void desktop_settings_scene_start_on_enter(void* context) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Favorite App",
|
||||
DesktopSettingsStartSubmenuIndexFavorite,
|
||||
SCENE_EVENT_SELECT_FAVORITE,
|
||||
desktop_settings_scene_start_submenu_callback,
|
||||
app);
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"PIN Setup",
|
||||
DesktopSettingsStartSubmenuIndexPinSetup,
|
||||
SCENE_EVENT_SELECT_PIN_SETUP,
|
||||
desktop_settings_scene_start_submenu_callback,
|
||||
app);
|
||||
|
||||
@@ -39,12 +38,12 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case DesktopSettingsStartSubmenuIndexFavorite:
|
||||
case SCENE_EVENT_SELECT_FAVORITE:
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopSettingsStartSubmenuIndexPinSetup:
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeMenu);
|
||||
case SCENE_EVENT_SELECT_PIN_SETUP:
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinMenu);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/canvas.h>
|
||||
#include <toolbox/version.h>
|
||||
#include <assets_icons.h>
|
||||
#include <dolphin/helpers/dolphin_state.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#include "desktop_settings_view_pin_setup_howto.h"
|
||||
|
||||
struct DesktopSettingsViewPinSetupHowto {
|
||||
View* view;
|
||||
DesktopSettingsViewPinSetupHowtoDoneCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
static void desktop_settings_view_pin_setup_howto_draw(Canvas* canvas, void* model) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(model);
|
||||
|
||||
canvas_draw_icon(canvas, 16, 18, &I_Pin_attention_dpad_29x29);
|
||||
elements_button_right(canvas, "Next");
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Setting up PIN");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text(canvas, 58, 24, "Prepare to use\narrows as\nPIN symbols");
|
||||
}
|
||||
|
||||
static bool desktop_settings_view_pin_setup_howto_input(InputEvent* event, void* context) {
|
||||
furi_assert(event);
|
||||
furi_assert(context);
|
||||
|
||||
DesktopSettingsViewPinSetupHowto* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if((event->key == InputKeyRight) && (event->type == InputTypeShort)) {
|
||||
instance->callback(instance->context);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_view_pin_setup_howto_set_callback(
|
||||
DesktopSettingsViewPinSetupHowto* instance,
|
||||
DesktopSettingsViewPinSetupHowtoDoneCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
DesktopSettingsViewPinSetupHowto* desktop_settings_view_pin_setup_howto_alloc() {
|
||||
DesktopSettingsViewPinSetupHowto* view = furi_alloc(sizeof(DesktopSettingsViewPinSetupHowto));
|
||||
view->view = view_alloc();
|
||||
view_allocate_model(view->view, ViewModelTypeLockFree, 1);
|
||||
view_set_context(view->view, view);
|
||||
view_set_draw_callback(view->view, desktop_settings_view_pin_setup_howto_draw);
|
||||
view_set_input_callback(view->view, desktop_settings_view_pin_setup_howto_input);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
void desktop_settings_view_pin_setup_howto_free(DesktopSettingsViewPinSetupHowto* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
view_free(instance->view);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
View* desktop_settings_view_pin_setup_howto_get_view(DesktopSettingsViewPinSetupHowto* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->view;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct DesktopSettingsViewPinSetupHowto DesktopSettingsViewPinSetupHowto;
|
||||
|
||||
typedef void (*DesktopSettingsViewPinSetupHowtoDoneCallback)(void*);
|
||||
|
||||
void desktop_settings_view_pin_setup_howto_set_callback(
|
||||
DesktopSettingsViewPinSetupHowto* instance,
|
||||
DesktopSettingsViewPinSetupHowtoDoneCallback callback,
|
||||
void* context);
|
||||
DesktopSettingsViewPinSetupHowto* desktop_settings_view_pin_setup_howto_alloc();
|
||||
void desktop_settings_view_pin_setup_howto_free(DesktopSettingsViewPinSetupHowto* instance);
|
||||
View* desktop_settings_view_pin_setup_howto_get_view(DesktopSettingsViewPinSetupHowto* instance);
|
||||
@@ -0,0 +1,101 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/canvas.h>
|
||||
#include <toolbox/version.h>
|
||||
#include <assets_icons.h>
|
||||
#include <dolphin/helpers/dolphin_state.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#include "desktop_settings_view_pin_setup_howto2.h"
|
||||
|
||||
struct DesktopSettingsViewPinSetupHowto2 {
|
||||
View* view;
|
||||
DesktopSettingsViewPinSetupHowto2Callback cancel_callback;
|
||||
DesktopSettingsViewPinSetupHowto2Callback ok_callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
static void desktop_settings_view_pin_setup_howto2_draw(Canvas* canvas, void* model) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(model);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text_aligned(
|
||||
canvas,
|
||||
64,
|
||||
24,
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
"Forgotten PIN can only be\n"
|
||||
"reset with entire device.\n"
|
||||
"Read docs How to reset PIN.");
|
||||
|
||||
elements_button_right(canvas, "OK");
|
||||
elements_button_left(canvas, "Cancel");
|
||||
}
|
||||
|
||||
static bool desktop_settings_view_pin_setup_howto2_input(InputEvent* event, void* context) {
|
||||
furi_assert(event);
|
||||
furi_assert(context);
|
||||
|
||||
DesktopSettingsViewPinSetupHowto2* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyRight) {
|
||||
instance->ok_callback(instance->context);
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
instance->cancel_callback(instance->context);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_view_pin_setup_howto2_set_context(
|
||||
DesktopSettingsViewPinSetupHowto2* instance,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
void desktop_settings_view_pin_setup_howto2_set_cancel_callback(
|
||||
DesktopSettingsViewPinSetupHowto2* instance,
|
||||
DesktopSettingsViewPinSetupHowto2Callback callback) {
|
||||
furi_assert(instance);
|
||||
instance->cancel_callback = callback;
|
||||
}
|
||||
|
||||
void desktop_settings_view_pin_setup_howto2_set_ok_callback(
|
||||
DesktopSettingsViewPinSetupHowto2* instance,
|
||||
DesktopSettingsViewPinSetupHowto2Callback callback) {
|
||||
furi_assert(instance);
|
||||
instance->ok_callback = callback;
|
||||
}
|
||||
|
||||
DesktopSettingsViewPinSetupHowto2* desktop_settings_view_pin_setup_howto2_alloc() {
|
||||
DesktopSettingsViewPinSetupHowto2* view =
|
||||
furi_alloc(sizeof(DesktopSettingsViewPinSetupHowto2));
|
||||
view->view = view_alloc();
|
||||
view_allocate_model(view->view, ViewModelTypeLockFree, 1);
|
||||
view_set_context(view->view, view);
|
||||
view_set_draw_callback(view->view, desktop_settings_view_pin_setup_howto2_draw);
|
||||
view_set_input_callback(view->view, desktop_settings_view_pin_setup_howto2_input);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
void desktop_settings_view_pin_setup_howto2_free(DesktopSettingsViewPinSetupHowto2* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
view_free(instance->view);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
View* desktop_settings_view_pin_setup_howto2_get_view(DesktopSettingsViewPinSetupHowto2* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->view;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct DesktopSettingsViewPinSetupHowto2 DesktopSettingsViewPinSetupHowto2;
|
||||
|
||||
typedef void (*DesktopSettingsViewPinSetupHowto2Callback)(void*);
|
||||
|
||||
DesktopSettingsViewPinSetupHowto2* desktop_settings_view_pin_setup_howto2_alloc();
|
||||
void desktop_settings_view_pin_setup_howto2_free(DesktopSettingsViewPinSetupHowto2* instance);
|
||||
View* desktop_settings_view_pin_setup_howto2_get_view(DesktopSettingsViewPinSetupHowto2* instance);
|
||||
void desktop_settings_view_pin_setup_howto2_set_context(
|
||||
DesktopSettingsViewPinSetupHowto2* instance,
|
||||
void* context);
|
||||
void desktop_settings_view_pin_setup_howto2_set_cancel_callback(
|
||||
DesktopSettingsViewPinSetupHowto2* instance,
|
||||
DesktopSettingsViewPinSetupHowto2Callback callback);
|
||||
void desktop_settings_view_pin_setup_howto2_set_ok_callback(
|
||||
DesktopSettingsViewPinSetupHowto2* instance,
|
||||
DesktopSettingsViewPinSetupHowto2Callback callback);
|
||||
@@ -3,5 +3,7 @@ ADD_SCENE(desktop, lock_menu, LockMenu)
|
||||
ADD_SCENE(desktop, debug, Debug)
|
||||
ADD_SCENE(desktop, first_start, FirstStart)
|
||||
ADD_SCENE(desktop, hw_mismatch, HwMismatch)
|
||||
ADD_SCENE(desktop, pinsetup, PinSetup)
|
||||
ADD_SCENE(desktop, fault, Fault)
|
||||
ADD_SCENE(desktop, locked, Locked)
|
||||
ADD_SCENE(desktop, pin_input, PinInput)
|
||||
ADD_SCENE(desktop, pin_timeout, PinTimeout)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <dolphin/helpers/dolphin_deed.h>
|
||||
|
||||
#include "../desktop_i.h"
|
||||
#include "../views/desktop_debug.h"
|
||||
#include "../views/desktop_view_debug.h"
|
||||
#include "desktop_scene.h"
|
||||
|
||||
void desktop_scene_debug_callback(DesktopEvent event, void* context) {
|
||||
@@ -17,7 +17,7 @@ void desktop_scene_debug_on_enter(void* context) {
|
||||
desktop_debug_get_dolphin_data(desktop->debug_view);
|
||||
|
||||
desktop_debug_set_callback(desktop->debug_view, desktop_scene_debug_callback, desktop);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewDebug);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdDebug);
|
||||
}
|
||||
|
||||
bool desktop_scene_debug_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
@@ -25,7 +25,7 @@ void desktop_scene_fault_on_enter(void* context) {
|
||||
char* message = (char*)furi_hal_rtc_get_fault_data();
|
||||
popup_set_text(popup, message, 60, 37 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter);
|
||||
popup_set_callback(popup, desktop_scene_fault_callback);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewHwMismatch);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdHwMismatch);
|
||||
}
|
||||
|
||||
bool desktop_scene_fault_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <storage/storage.h>
|
||||
|
||||
#include "../desktop_i.h"
|
||||
#include "../views/desktop_first_start.h"
|
||||
#include "../views/desktop_view_first_start.h"
|
||||
#include "../views/desktop_events.h"
|
||||
|
||||
void desktop_scene_first_start_callback(DesktopEvent event, void* context) {
|
||||
@@ -17,7 +17,7 @@ void desktop_scene_first_start_on_enter(void* context) {
|
||||
desktop_first_start_set_callback(
|
||||
first_start_view, desktop_scene_first_start_callback, desktop);
|
||||
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewFirstStart);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdFirstStart);
|
||||
}
|
||||
|
||||
bool desktop_scene_first_start_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <gui/scene_manager.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include "desktop_scene.h"
|
||||
#include "../desktop_i.h"
|
||||
@@ -31,7 +31,7 @@ void desktop_scene_hw_mismatch_on_enter(void* context) {
|
||||
popup, "!!!! HW Mismatch !!!!", 60, 14 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter);
|
||||
popup_set_text(popup, text_buffer, 60, 37 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter);
|
||||
popup_set_callback(popup, desktop_scene_hw_mismatch_callback);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewHwMismatch);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdHwMismatch);
|
||||
}
|
||||
|
||||
bool desktop_scene_hw_mismatch_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
DesktopMainSceneStateUnlocked,
|
||||
DesktopMainSceneStateLockedWithPin,
|
||||
DesktopMainSceneStateLockedNoPin,
|
||||
} DesktopMainSceneState;
|
||||
#define SCENE_LOCKED_FIRST_ENTER 0
|
||||
#define SCENE_LOCKED_REPEAT_ENTER 1
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
#include <gui/scene_manager.h>
|
||||
#include <applications.h>
|
||||
#include <furi_hal.h>
|
||||
#include <toolbox/saved_struct.h>
|
||||
#include <stdbool.h>
|
||||
#include <loader/loader.h>
|
||||
|
||||
#include "../desktop_i.h"
|
||||
#include "../views/desktop_lock_menu.h"
|
||||
#include "../desktop_settings/desktop_settings.h"
|
||||
#include "../views/desktop_view_lock_menu.h"
|
||||
#include "desktop_scene_i.h"
|
||||
#include "desktop_scene.h"
|
||||
|
||||
@@ -15,36 +20,50 @@ void desktop_scene_lock_menu_on_enter(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
|
||||
LOAD_DESKTOP_SETTINGS(&desktop->settings);
|
||||
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
|
||||
desktop_lock_menu_set_callback(desktop->lock_menu, desktop_scene_lock_menu_callback, desktop);
|
||||
desktop_lock_menu_pin_set(desktop->lock_menu, desktop->settings.pincode.length > 0);
|
||||
desktop_lock_menu_pin_set(desktop->lock_menu, desktop->settings.pin_code.length > 0);
|
||||
desktop_lock_menu_set_idx(desktop->lock_menu, 0);
|
||||
|
||||
uint8_t idx = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu);
|
||||
desktop_lock_menu_set_idx(desktop->lock_menu, idx);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewLockMenu);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdLockMenu);
|
||||
}
|
||||
|
||||
bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.type == SceneManagerEventTypeTick) {
|
||||
bool check_pin_changed =
|
||||
scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu);
|
||||
if(check_pin_changed) {
|
||||
LOAD_DESKTOP_SETTINGS(&desktop->settings);
|
||||
if(desktop->settings.pin_code.length > 0) {
|
||||
desktop_lock_menu_pin_set(desktop->lock_menu, 1);
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
|
||||
}
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case DesktopLockMenuEventLock:
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedNoPin);
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopLockMenuEventPinLock:
|
||||
if(desktop->settings.pincode.length > 0) {
|
||||
if(desktop->settings.pin_code.length > 0) {
|
||||
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedWithPin);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
||||
} else {
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopScenePinSetup);
|
||||
Loader* loader = furi_record_open("loader");
|
||||
LoaderStatus status =
|
||||
loader_start(loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG);
|
||||
furi_check(status == LoaderStatusOk);
|
||||
furi_record_close("loader");
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
|
||||
109
applications/desktop/scenes/desktop_scene_locked.c
Normal file
109
applications/desktop/scenes/desktop_scene_locked.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/view_stack.h>
|
||||
#include <stdint.h>
|
||||
#include <portmacro.h>
|
||||
|
||||
#include "../desktop.h"
|
||||
#include "../desktop_i.h"
|
||||
#include "../desktop_helpers.h"
|
||||
#include "../animations/animation_manager.h"
|
||||
#include "../views/desktop_events.h"
|
||||
#include "../views/desktop_view_pin_input.h"
|
||||
#include "../views/desktop_view_locked.h"
|
||||
#include "desktop_scene.h"
|
||||
#include "desktop_scene_i.h"
|
||||
|
||||
#define WRONG_PIN_HEADER_TIMEOUT 3000
|
||||
#define INPUT_PIN_VIEW_TIMEOUT 15000
|
||||
|
||||
static void desktop_scene_locked_callback(DesktopEvent event, void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
view_dispatcher_send_custom_event(desktop->view_dispatcher, event);
|
||||
}
|
||||
|
||||
static void desktop_scene_locked_new_idle_animation_callback(void* context) {
|
||||
furi_assert(context);
|
||||
Desktop* desktop = context;
|
||||
view_dispatcher_send_custom_event(
|
||||
desktop->view_dispatcher, DesktopAnimationEventNewIdleAnimation);
|
||||
}
|
||||
|
||||
void desktop_scene_locked_on_enter(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
|
||||
// callbacks for 1-st layer
|
||||
animation_manager_set_new_idle_callback(
|
||||
desktop->animation_manager, desktop_scene_locked_new_idle_animation_callback);
|
||||
animation_manager_set_check_callback(desktop->animation_manager, NULL);
|
||||
animation_manager_set_interact_callback(desktop->animation_manager, NULL);
|
||||
|
||||
// callbacks for 2-nd layer
|
||||
desktop_view_locked_set_callback(desktop->locked_view, desktop_scene_locked_callback, desktop);
|
||||
|
||||
bool switch_to_timeout_scene = false;
|
||||
uint32_t state = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLocked);
|
||||
if(state == SCENE_LOCKED_FIRST_ENTER) {
|
||||
bool pin_locked = furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock);
|
||||
desktop_helpers_lock_system(desktop, pin_locked);
|
||||
if(pin_locked) {
|
||||
LOAD_DESKTOP_SETTINGS(&desktop->settings);
|
||||
desktop_view_locked_lock(desktop->locked_view, true);
|
||||
uint32_t pin_fails = furi_hal_rtc_get_pin_fails();
|
||||
uint32_t pin_timeout = desktop_helpers_get_pin_fail_timeout(pin_fails);
|
||||
if(pin_timeout) {
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopScenePinTimeout, pin_timeout);
|
||||
switch_to_timeout_scene = true;
|
||||
} else {
|
||||
desktop_view_locked_close_doors(desktop->locked_view);
|
||||
}
|
||||
} else {
|
||||
desktop_view_locked_lock(desktop->locked_view, false);
|
||||
desktop_view_locked_close_doors(desktop->locked_view);
|
||||
}
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_REPEAT_ENTER);
|
||||
}
|
||||
|
||||
if(switch_to_timeout_scene) {
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopScenePinTimeout);
|
||||
} else {
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdLocked);
|
||||
}
|
||||
}
|
||||
|
||||
bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case DesktopLockedEventUnlocked:
|
||||
furi_hal_rtc_set_pin_fails(0);
|
||||
desktop_helpers_unlock_system(desktop);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
desktop->scene_manager, DesktopSceneMain);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopLockedEventUpdate:
|
||||
desktop_view_locked_update(desktop->locked_view);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopLockedEventShowPinInput:
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopScenePinInput);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopAnimationEventNewIdleAnimation:
|
||||
animation_manager_new_idle_process(desktop->animation_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_scene_locked_on_exit(void* context) {
|
||||
}
|
||||
@@ -4,15 +4,14 @@
|
||||
#include <assets_icons.h>
|
||||
#include <loader/loader.h>
|
||||
|
||||
#include "desktop/desktop_i.h"
|
||||
#include "desktop/views/desktop_main.h"
|
||||
#include "../desktop_i.h"
|
||||
#include "../views/desktop_events.h"
|
||||
#include "../views/desktop_view_main.h"
|
||||
#include "desktop_scene.h"
|
||||
#include "desktop_scene_i.h"
|
||||
|
||||
#define TAG "DesktopSrv"
|
||||
|
||||
#define MAIN_VIEW_DEFAULT (0UL)
|
||||
|
||||
static void desktop_scene_main_app_started_callback(const void* message, void* context) {
|
||||
furi_assert(context);
|
||||
Desktop* desktop = context;
|
||||
@@ -31,19 +30,22 @@ static void desktop_scene_main_app_started_callback(const void* message, void* c
|
||||
static void desktop_scene_main_new_idle_animation_callback(void* context) {
|
||||
furi_assert(context);
|
||||
Desktop* desktop = context;
|
||||
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventNewIdleAnimation);
|
||||
view_dispatcher_send_custom_event(
|
||||
desktop->view_dispatcher, DesktopAnimationEventNewIdleAnimation);
|
||||
}
|
||||
|
||||
static void desktop_scene_main_check_animation_callback(void* context) {
|
||||
furi_assert(context);
|
||||
Desktop* desktop = context;
|
||||
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventCheckAnimation);
|
||||
view_dispatcher_send_custom_event(
|
||||
desktop->view_dispatcher, DesktopAnimationEventCheckAnimation);
|
||||
}
|
||||
|
||||
static void desktop_scene_main_interact_animation_callback(void* context) {
|
||||
furi_assert(context);
|
||||
Desktop* desktop = context;
|
||||
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopMainEventInteractAnimation);
|
||||
view_dispatcher_send_custom_event(
|
||||
desktop->view_dispatcher, DesktopAnimationEventInteractAnimation);
|
||||
}
|
||||
|
||||
static void desktop_switch_to_app(Desktop* desktop, const FlipperApplication* flipper_app) {
|
||||
@@ -80,7 +82,6 @@ void desktop_scene_main_on_enter(void* context) {
|
||||
desktop->animation_manager, desktop_scene_main_check_animation_callback);
|
||||
animation_manager_set_interact_callback(
|
||||
desktop->animation_manager, desktop_scene_main_interact_animation_callback);
|
||||
desktop_locked_set_callback(desktop->locked_view, desktop_scene_main_callback, desktop);
|
||||
|
||||
furi_assert(osSemaphoreGetCount(desktop->unload_animation_semaphore) == 0);
|
||||
Loader* loader = furi_record_open("loader");
|
||||
@@ -90,24 +91,7 @@ void desktop_scene_main_on_enter(void* context) {
|
||||
|
||||
desktop_main_set_callback(main_view, desktop_scene_main_callback, desktop);
|
||||
|
||||
DesktopMainSceneState state =
|
||||
scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneMain);
|
||||
if(state == DesktopMainSceneStateLockedNoPin) {
|
||||
desktop_locked_lock(desktop->locked_view);
|
||||
view_port_enabled_set(desktop->lock_viewport, true);
|
||||
} else if(state == DesktopMainSceneStateLockedWithPin) {
|
||||
LOAD_DESKTOP_SETTINGS(&desktop->settings);
|
||||
furi_assert(desktop->settings.pincode.length > 0);
|
||||
desktop_locked_lock_pincode(desktop->locked_view, desktop->settings.pincode);
|
||||
view_port_enabled_set(desktop->lock_viewport, true);
|
||||
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
|
||||
furi_hal_usb_disable();
|
||||
} else {
|
||||
furi_assert(state == DesktopMainSceneStateUnlocked);
|
||||
view_port_enabled_set(desktop->lock_viewport, false);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewMain);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdMain);
|
||||
}
|
||||
|
||||
bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
@@ -154,15 +138,15 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case DesktopMainEventCheckAnimation:
|
||||
case DesktopAnimationEventCheckAnimation:
|
||||
animation_manager_check_blocking_process(desktop->animation_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopMainEventNewIdleAnimation:
|
||||
case DesktopAnimationEventNewIdleAnimation:
|
||||
animation_manager_new_idle_process(desktop->animation_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopMainEventInteractAnimation:
|
||||
case DesktopAnimationEventInteractAnimation:
|
||||
animation_manager_interact_process(desktop->animation_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
@@ -175,16 +159,8 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
animation_manager_load_and_continue_animation(desktop->animation_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopMainEventUnlocked:
|
||||
consumed = true;
|
||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
||||
furi_hal_usb_enable();
|
||||
view_port_enabled_set(desktop->lock_viewport, false);
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateUnlocked);
|
||||
break;
|
||||
case DesktopMainEventUpdate:
|
||||
desktop_locked_update(desktop->locked_view);
|
||||
case DesktopLockedEventUpdate:
|
||||
desktop_view_locked_update(desktop->locked_view);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
@@ -213,5 +189,4 @@ void desktop_scene_main_on_exit(void* context) {
|
||||
animation_manager_set_check_callback(desktop->animation_manager, NULL);
|
||||
animation_manager_set_interact_callback(desktop->animation_manager, NULL);
|
||||
animation_manager_set_context(desktop->animation_manager, desktop);
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneMain, MAIN_VIEW_DEFAULT);
|
||||
}
|
||||
|
||||
162
applications/desktop/scenes/desktop_scene_pin_input.c
Normal file
162
applications/desktop/scenes/desktop_scene_pin_input.c
Normal file
@@ -0,0 +1,162 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/view_stack.h>
|
||||
#include <stdint.h>
|
||||
#include <portmacro.h>
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include "../desktop.h"
|
||||
#include "../desktop_i.h"
|
||||
#include "../animations/animation_manager.h"
|
||||
#include "../views/desktop_events.h"
|
||||
#include "../views/desktop_view_pin_input.h"
|
||||
#include "../desktop_helpers.h"
|
||||
#include "desktop_scene.h"
|
||||
#include "desktop_scene_i.h"
|
||||
|
||||
#define WRONG_PIN_HEADER_TIMEOUT 3000
|
||||
#define INPUT_PIN_VIEW_TIMEOUT 15000
|
||||
|
||||
typedef struct {
|
||||
TimerHandle_t timer;
|
||||
} DesktopScenePinInputState;
|
||||
|
||||
static void desktop_scene_locked_light_red(bool value) {
|
||||
NotificationApp* app = furi_record_open("notification");
|
||||
if(value) {
|
||||
notification_message(app, &sequence_set_only_red_255);
|
||||
} else {
|
||||
notification_message(app, &sequence_reset_red);
|
||||
}
|
||||
furi_record_close("notification");
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_scene_pin_input_set_timer(Desktop* desktop, bool enable, TickType_t new_period) {
|
||||
furi_assert(desktop);
|
||||
|
||||
DesktopScenePinInputState* state = (DesktopScenePinInputState*)scene_manager_get_scene_state(
|
||||
desktop->scene_manager, DesktopScenePinInput);
|
||||
furi_assert(state);
|
||||
if(enable) {
|
||||
xTimerChangePeriod(state->timer, new_period, portMAX_DELAY);
|
||||
} else {
|
||||
xTimerStop(state->timer, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
static void desktop_scene_pin_input_back_callback(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinInputEventBack);
|
||||
}
|
||||
|
||||
static void desktop_scene_pin_input_done_callback(const PinCode* pin_code, void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
if(pins_are_equal(&desktop->settings.pin_code, pin_code)) {
|
||||
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinInputEventUnlocked);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(
|
||||
desktop->view_dispatcher, DesktopPinInputEventUnlockFailed);
|
||||
}
|
||||
}
|
||||
|
||||
static void desktop_scene_pin_input_timer_callback(TimerHandle_t timer) {
|
||||
Desktop* desktop = pvTimerGetTimerID(timer);
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
desktop->view_dispatcher, DesktopPinInputEventResetWrongPinLabel);
|
||||
}
|
||||
|
||||
void desktop_scene_pin_input_on_enter(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
|
||||
desktop_view_pin_input_set_context(desktop->pin_input_view, desktop);
|
||||
desktop_view_pin_input_set_back_callback(
|
||||
desktop->pin_input_view, desktop_scene_pin_input_back_callback);
|
||||
desktop_view_pin_input_set_timeout_callback(
|
||||
desktop->pin_input_view, desktop_scene_pin_input_back_callback);
|
||||
desktop_view_pin_input_set_done_callback(
|
||||
desktop->pin_input_view, desktop_scene_pin_input_done_callback);
|
||||
|
||||
DesktopScenePinInputState* state = furi_alloc(sizeof(DesktopScenePinInputState));
|
||||
state->timer =
|
||||
xTimerCreate(NULL, 10000, pdFALSE, desktop, desktop_scene_pin_input_timer_callback);
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopScenePinInput, (uint32_t)state);
|
||||
|
||||
desktop_view_pin_input_hide_pin(desktop->pin_input_view, true);
|
||||
desktop_view_pin_input_set_label_button(desktop->pin_input_view, "OK");
|
||||
desktop_view_pin_input_set_label_secondary(desktop->pin_input_view, 44, 25, "Enter PIN:");
|
||||
desktop_view_pin_input_set_pin_position(desktop->pin_input_view, 64, 37);
|
||||
desktop_view_pin_input_reset_pin(desktop->pin_input_view);
|
||||
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdPinInput);
|
||||
}
|
||||
|
||||
bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
bool consumed = false;
|
||||
uint32_t pin_fails = 0;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case DesktopPinInputEventUnlockFailed:
|
||||
pin_fails = furi_hal_rtc_get_pin_fails();
|
||||
pin_fails++;
|
||||
furi_hal_rtc_set_pin_fails(pin_fails);
|
||||
uint32_t pin_timeout = desktop_helpers_get_pin_fail_timeout(pin_fails);
|
||||
if(pin_timeout > 0) {
|
||||
desktop_helpers_emit_error_notification();
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopScenePinTimeout, pin_timeout);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopScenePinTimeout);
|
||||
} else {
|
||||
desktop_scene_locked_light_red(true);
|
||||
desktop_view_pin_input_set_label_primary(desktop->pin_input_view, 0, 0, NULL);
|
||||
desktop_view_pin_input_set_label_secondary(
|
||||
desktop->pin_input_view, 25, 25, "Wrong PIN try again:");
|
||||
desktop_scene_pin_input_set_timer(desktop, true, WRONG_PIN_HEADER_TIMEOUT);
|
||||
desktop_view_pin_input_reset_pin(desktop->pin_input_view);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopPinInputEventResetWrongPinLabel:
|
||||
desktop_scene_locked_light_red(false);
|
||||
desktop_view_pin_input_set_label_primary(desktop->pin_input_view, 0, 0, NULL);
|
||||
desktop_view_pin_input_set_label_secondary(
|
||||
desktop->pin_input_view, 44, 25, "Enter PIN:");
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopPinInputEventUnlocked:
|
||||
desktop_view_locked_unlock(desktop->locked_view);
|
||||
furi_hal_rtc_set_pin_fails(0);
|
||||
desktop_helpers_unlock_system(desktop);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
desktop->scene_manager, DesktopSceneMain);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopPinInputEventBack:
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
desktop->scene_manager, DesktopSceneLocked);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_scene_pin_input_on_exit(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
desktop_scene_locked_light_red(false);
|
||||
|
||||
DesktopScenePinInputState* state = (DesktopScenePinInputState*)scene_manager_get_scene_state(
|
||||
desktop->scene_manager, DesktopScenePinInput);
|
||||
xTimerStop(state->timer, portMAX_DELAY);
|
||||
while(xTimerIsTimerActive(state->timer)) {
|
||||
delay(1);
|
||||
}
|
||||
xTimerDelete(state->timer, portMAX_DELAY);
|
||||
free(state);
|
||||
}
|
||||
46
applications/desktop/scenes/desktop_scene_pin_timeout.c
Normal file
46
applications/desktop/scenes/desktop_scene_pin_timeout.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <furi.h>
|
||||
#include <FreeRTOS.h>
|
||||
#include <portmacro.h>
|
||||
#include <timer.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#include "../desktop_i.h"
|
||||
#include "../views/desktop_view_pin_timeout.h"
|
||||
#include "desktop_scene.h"
|
||||
#include "desktop_scene_i.h"
|
||||
|
||||
static void desktop_scene_pin_timeout_callback(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinTimeoutExit);
|
||||
}
|
||||
|
||||
void desktop_scene_pin_timeout_on_enter(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
|
||||
uint32_t timeout =
|
||||
scene_manager_get_scene_state(desktop->scene_manager, DesktopScenePinTimeout);
|
||||
desktop_view_pin_timeout_start(desktop->pin_timeout_view, timeout);
|
||||
desktop_view_pin_timeout_set_callback(
|
||||
desktop->pin_timeout_view, desktop_scene_pin_timeout_callback, desktop);
|
||||
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdPinTimeout);
|
||||
}
|
||||
|
||||
bool desktop_scene_pin_timeout_on_event(void* context, SceneManagerEvent event) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case DesktopPinTimeoutExit:
|
||||
scene_manager_previous_scene(desktop->scene_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_scene_pin_timeout_on_exit(void* context) {
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#include "../desktop_i.h"
|
||||
|
||||
#define SCENE_EXIT_EVENT (0U)
|
||||
|
||||
void desktop_scene_ok_callback(void* context) {
|
||||
Desktop* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EXIT_EVENT);
|
||||
}
|
||||
|
||||
void desktop_scene_pinsetup_on_enter(void* context) {
|
||||
Desktop* app = context;
|
||||
CodeInput* code_input = app->code_input;
|
||||
|
||||
code_input_set_result_callback(
|
||||
code_input,
|
||||
desktop_scene_ok_callback,
|
||||
NULL,
|
||||
app,
|
||||
app->settings.pincode.data,
|
||||
&app->settings.pincode.length,
|
||||
true);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopViewPinSetup);
|
||||
}
|
||||
|
||||
bool desktop_scene_pinsetup_on_event(void* context, SceneManagerEvent event) {
|
||||
Desktop* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SCENE_EXIT_EVENT:
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_scene_pinsetup_on_exit(void* context) {
|
||||
Desktop* app = context;
|
||||
SAVE_DESKTOP_SETTINGS(&app->settings);
|
||||
code_input_set_result_callback(app->code_input, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
code_input_set_header_text(app->code_input, "");
|
||||
}
|
||||
@@ -6,24 +6,35 @@ typedef enum {
|
||||
DesktopMainEventOpenFavorite,
|
||||
DesktopMainEventOpenMenu,
|
||||
DesktopMainEventOpenDebug,
|
||||
DesktopMainEventUpdate,
|
||||
DesktopMainEventUnlocked,
|
||||
DesktopMainEventRightShort,
|
||||
DesktopMainEventCheckAnimation,
|
||||
DesktopMainEventNewIdleAnimation,
|
||||
DesktopMainEventInteractAnimation,
|
||||
DesktopMainEventBeforeAppStarted,
|
||||
DesktopMainEventAfterAppFinished,
|
||||
DesktopLockedEventUnlock,
|
||||
DesktopLockedEventCheckAnimation,
|
||||
DesktopLockedEventMax,
|
||||
|
||||
DesktopLockedEventUnlocked,
|
||||
DesktopLockedEventUpdate,
|
||||
DesktopLockedEventShowPinInput,
|
||||
|
||||
DesktopPinInputEventResetWrongPinLabel,
|
||||
DesktopPinInputEventUnlocked,
|
||||
DesktopPinInputEventUnlockFailed,
|
||||
DesktopPinInputEventBack,
|
||||
|
||||
DesktopPinTimeoutExit,
|
||||
|
||||
DesktopDebugEventDeed,
|
||||
DesktopDebugEventWrongDeed,
|
||||
DesktopDebugEventSaveState,
|
||||
DesktopDebugEventExit,
|
||||
|
||||
DesktopFirstStartCompleted,
|
||||
DesktopFirstStartPoweroff,
|
||||
|
||||
DesktopLockMenuEventLock,
|
||||
DesktopLockMenuEventPinLock,
|
||||
DesktopLockMenuEventExit,
|
||||
|
||||
DesktopAnimationEventCheckAnimation,
|
||||
DesktopAnimationEventNewIdleAnimation,
|
||||
DesktopAnimationEventInteractAnimation,
|
||||
|
||||
} DesktopEvent;
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
#include "desktop/desktop_settings/desktop_settings.h"
|
||||
#include "furi/check.h"
|
||||
#include "gui/view.h"
|
||||
#include "portmacro.h"
|
||||
#include <furi.h>
|
||||
#include <gui/gui_i.h>
|
||||
#include <gui/elements.h>
|
||||
#include "../desktop_i.h"
|
||||
#include "desktop_locked.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define DOOR_MOVING_INTERVAL_MS (1000 / 16)
|
||||
#define UNLOCKED_HINT_TIMEOUT_MS (2000)
|
||||
|
||||
struct DesktopLockedView {
|
||||
View* view;
|
||||
DesktopLockedViewCallback callback;
|
||||
void* context;
|
||||
|
||||
TimerHandle_t timer;
|
||||
uint8_t lock_count;
|
||||
uint32_t lock_lastpress;
|
||||
|
||||
PinCode pincode;
|
||||
PinCode pincode_input;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t hint_icon_expire_at;
|
||||
bool unlocked_hint;
|
||||
bool locked;
|
||||
bool pin_locked;
|
||||
|
||||
int8_t door_left_x;
|
||||
int8_t door_right_x;
|
||||
bool animation_seq_end;
|
||||
} DesktopLockedViewModel;
|
||||
|
||||
static void desktop_locked_unlock(DesktopLockedView* locked_view);
|
||||
|
||||
void desktop_locked_set_callback(
|
||||
DesktopLockedView* locked_view,
|
||||
DesktopLockedViewCallback callback,
|
||||
void* context) {
|
||||
furi_assert(locked_view);
|
||||
furi_assert(callback);
|
||||
locked_view->callback = callback;
|
||||
locked_view->context = context;
|
||||
}
|
||||
|
||||
void locked_view_timer_callback(TimerHandle_t timer) {
|
||||
DesktopLockedView* locked_view = pvTimerGetTimerID(timer);
|
||||
locked_view->callback(DesktopMainEventUpdate, locked_view->context);
|
||||
}
|
||||
|
||||
static void desktop_locked_update_hint_icon_timeout(DesktopLockedView* locked_view) {
|
||||
DesktopLockedViewModel* model = view_get_model(locked_view->view);
|
||||
model->hint_icon_expire_at = osKernelGetTickCount() + osKernelGetTickFreq();
|
||||
view_commit_model(locked_view->view, true);
|
||||
}
|
||||
|
||||
static void desktop_locked_reset_door_pos(DesktopLockedView* locked_view) {
|
||||
DesktopLockedViewModel* model = view_get_model(locked_view->view);
|
||||
model->animation_seq_end = false;
|
||||
model->door_left_x = DOOR_L_POS;
|
||||
model->door_right_x = DOOR_R_POS;
|
||||
view_commit_model(locked_view->view, true);
|
||||
}
|
||||
|
||||
void desktop_locked_update(DesktopLockedView* locked_view) {
|
||||
bool stop_timer = false;
|
||||
|
||||
DesktopLockedViewModel* model = view_get_model(locked_view->view);
|
||||
if(model->locked) {
|
||||
if(model->door_left_x != DOOR_L_POS_MAX) {
|
||||
model->door_left_x = CLAMP(model->door_left_x + 5, DOOR_L_POS_MAX, DOOR_L_POS);
|
||||
model->door_right_x = CLAMP(model->door_right_x - 5, DOOR_R_POS, DOOR_R_POS_MIN);
|
||||
} else {
|
||||
model->animation_seq_end = true;
|
||||
}
|
||||
stop_timer = model->animation_seq_end;
|
||||
} else {
|
||||
model->unlocked_hint = false;
|
||||
stop_timer = true;
|
||||
}
|
||||
view_commit_model(locked_view->view, true);
|
||||
|
||||
if(stop_timer) {
|
||||
xTimerStop(locked_view->timer, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void desktop_locked_draw(Canvas* canvas, void* model) {
|
||||
DesktopLockedViewModel* m = model;
|
||||
uint32_t now = osKernelGetTickCount();
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
if(m->locked) {
|
||||
if(!m->animation_seq_end) {
|
||||
canvas_draw_icon(canvas, m->door_left_x, 0 + STATUS_BAR_Y_SHIFT, &I_DoorLeft_70x55);
|
||||
canvas_draw_icon(canvas, m->door_right_x, 0 + STATUS_BAR_Y_SHIFT, &I_DoorRight_70x55);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Locked");
|
||||
} else if((now < m->hint_icon_expire_at) && !m->pin_locked) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_icon(canvas, 13, 2 + STATUS_BAR_Y_SHIFT, &I_LockPopup_100x49);
|
||||
elements_multiline_text(canvas, 65, 20 + STATUS_BAR_Y_SHIFT, "To unlock\npress:");
|
||||
}
|
||||
} else {
|
||||
if(m->unlocked_hint) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Unlocked");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
View* desktop_locked_get_view(DesktopLockedView* locked_view) {
|
||||
furi_assert(locked_view);
|
||||
return locked_view->view;
|
||||
}
|
||||
|
||||
bool desktop_locked_input(InputEvent* event, void* context) {
|
||||
furi_assert(event);
|
||||
furi_assert(context);
|
||||
DesktopLockedView* locked_view = context;
|
||||
bool locked = false;
|
||||
bool locked_with_pin = false;
|
||||
uint32_t press_time = xTaskGetTickCount();
|
||||
|
||||
{
|
||||
DesktopLockedViewModel* model = view_get_model(locked_view->view);
|
||||
bool changed = false;
|
||||
locked = model->locked;
|
||||
locked_with_pin = model->pin_locked;
|
||||
if(!locked && model->unlocked_hint && event->type == InputTypePress) {
|
||||
model->unlocked_hint = false;
|
||||
changed = true;
|
||||
}
|
||||
view_commit_model(locked_view->view, changed);
|
||||
}
|
||||
|
||||
if(!locked || (event->type != InputTypeShort)) {
|
||||
return locked;
|
||||
}
|
||||
|
||||
if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) {
|
||||
locked_view->lock_lastpress = press_time;
|
||||
locked_view->lock_count = 0;
|
||||
locked_view->pincode_input.length = 0;
|
||||
}
|
||||
|
||||
if(locked_with_pin) {
|
||||
locked_view->pincode_input.length = code_input_push(
|
||||
locked_view->pincode_input.data, locked_view->pincode_input.length, event->key);
|
||||
bool match = code_input_compare(
|
||||
locked_view->pincode_input.data,
|
||||
locked_view->pincode_input.length,
|
||||
locked_view->pincode.data,
|
||||
locked_view->pincode.length);
|
||||
|
||||
if(match) {
|
||||
desktop_locked_unlock(locked_view);
|
||||
}
|
||||
} else {
|
||||
if(event->key == InputKeyBack) {
|
||||
locked_view->lock_lastpress = press_time;
|
||||
locked_view->lock_count++;
|
||||
if(locked_view->lock_count == UNLOCK_CNT) {
|
||||
desktop_locked_unlock(locked_view);
|
||||
}
|
||||
} else {
|
||||
desktop_locked_update_hint_icon_timeout(locked_view);
|
||||
locked_view->lock_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
locked_view->lock_lastpress = press_time;
|
||||
|
||||
return locked;
|
||||
}
|
||||
|
||||
DesktopLockedView* desktop_locked_alloc() {
|
||||
DesktopLockedView* locked_view = furi_alloc(sizeof(DesktopLockedView));
|
||||
locked_view->view = view_alloc();
|
||||
locked_view->timer =
|
||||
xTimerCreate("Locked view", 1000 / 16, pdTRUE, locked_view, locked_view_timer_callback);
|
||||
|
||||
view_allocate_model(locked_view->view, ViewModelTypeLocking, sizeof(DesktopLockedViewModel));
|
||||
view_set_context(locked_view->view, locked_view);
|
||||
view_set_draw_callback(locked_view->view, (ViewDrawCallback)desktop_locked_draw);
|
||||
view_set_input_callback(locked_view->view, desktop_locked_input);
|
||||
|
||||
return locked_view;
|
||||
}
|
||||
|
||||
void desktop_locked_free(DesktopLockedView* locked_view) {
|
||||
furi_assert(locked_view);
|
||||
osTimerDelete(locked_view->timer);
|
||||
view_free(locked_view->view);
|
||||
free(locked_view);
|
||||
}
|
||||
|
||||
void desktop_locked_lock(DesktopLockedView* locked_view) {
|
||||
locked_view->pincode.length = 0;
|
||||
DesktopLockedViewModel* model = view_get_model(locked_view->view);
|
||||
model->locked = true;
|
||||
model->pin_locked = false;
|
||||
view_commit_model(locked_view->view, true);
|
||||
desktop_locked_reset_door_pos(locked_view);
|
||||
xTimerChangePeriod(locked_view->timer, DOOR_MOVING_INTERVAL_MS, portMAX_DELAY);
|
||||
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_set_lockdown(gui, true);
|
||||
furi_record_close("gui");
|
||||
}
|
||||
|
||||
void desktop_locked_lock_pincode(DesktopLockedView* locked_view, PinCode pincode) {
|
||||
locked_view->pincode = pincode;
|
||||
locked_view->pincode_input.length = 0;
|
||||
DesktopLockedViewModel* model = view_get_model(locked_view->view);
|
||||
model->locked = true;
|
||||
model->pin_locked = true;
|
||||
view_commit_model(locked_view->view, true);
|
||||
desktop_locked_reset_door_pos(locked_view);
|
||||
xTimerChangePeriod(locked_view->timer, DOOR_MOVING_INTERVAL_MS, portMAX_DELAY);
|
||||
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_set_lockdown(gui, true);
|
||||
furi_record_close("gui");
|
||||
}
|
||||
|
||||
static void desktop_locked_unlock(DesktopLockedView* locked_view) {
|
||||
furi_assert(locked_view);
|
||||
|
||||
locked_view->lock_count = 0;
|
||||
DesktopLockedViewModel* model = view_get_model(locked_view->view);
|
||||
model->locked = false;
|
||||
model->pin_locked = false;
|
||||
model->unlocked_hint = true;
|
||||
view_commit_model(locked_view->view, true);
|
||||
locked_view->callback(DesktopMainEventUnlocked, locked_view->context);
|
||||
xTimerChangePeriod(locked_view->timer, UNLOCKED_HINT_TIMEOUT_MS, portMAX_DELAY);
|
||||
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_set_lockdown(gui, false);
|
||||
furi_record_close("gui");
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <desktop/desktop_settings/desktop_settings.h>
|
||||
#include <gui/view.h>
|
||||
#include "desktop_events.h"
|
||||
|
||||
#define UNLOCK_RST_TIMEOUT 300
|
||||
#define UNLOCK_CNT 3
|
||||
|
||||
#define DOOR_L_POS -57
|
||||
#define DOOR_L_POS_MAX 0
|
||||
#define DOOR_R_POS 115
|
||||
#define DOOR_R_POS_MIN 60
|
||||
|
||||
typedef enum {
|
||||
DesktopLockedWithPin,
|
||||
DesktopLockedNoPin,
|
||||
} DesktopLockedSceneState;
|
||||
|
||||
typedef struct DesktopLockedView DesktopLockedView;
|
||||
|
||||
typedef void (*DesktopLockedViewCallback)(DesktopEvent event, void* context);
|
||||
|
||||
void desktop_locked_set_callback(
|
||||
DesktopLockedView* locked_view,
|
||||
DesktopLockedViewCallback callback,
|
||||
void* context);
|
||||
|
||||
void desktop_locked_update(DesktopLockedView* locked_view);
|
||||
|
||||
View* desktop_locked_get_view(DesktopLockedView* locked_view);
|
||||
DesktopLockedView* desktop_locked_alloc();
|
||||
void desktop_locked_free(DesktopLockedView* locked_view);
|
||||
|
||||
void desktop_locked_lock_pincode(DesktopLockedView* locked_view, PinCode pincode);
|
||||
void desktop_locked_lock(DesktopLockedView* locked_view);
|
||||
@@ -1,11 +1,11 @@
|
||||
#include <toolbox/version.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <dolphin/helpers/dolphin_state.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#include "../desktop_i.h"
|
||||
#include "desktop_debug.h"
|
||||
#include "dolphin/helpers/dolphin_state.h"
|
||||
#include "dolphin/dolphin.h"
|
||||
#include "desktop_view_debug.h"
|
||||
|
||||
void desktop_debug_set_callback(
|
||||
DesktopDebugView* debug_view,
|
||||
@@ -1,8 +1,9 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
#include "../desktop_i.h"
|
||||
#include "desktop_first_start.h"
|
||||
#include "desktop_view_first_start.h"
|
||||
|
||||
#define DESKTOP_FIRST_START_POWEROFF_SHORT 5000
|
||||
#define DESKTOP_FIRST_START_POWEROFF_LONG (60 * 60 * 1000)
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <gui/elements.h>
|
||||
|
||||
#include "../desktop_i.h"
|
||||
#include "desktop_lock_menu.h"
|
||||
#include "desktop_view_lock_menu.h"
|
||||
|
||||
#define LOCK_MENU_ITEMS_NB 3
|
||||
|
||||
233
applications/desktop/views/desktop_view_locked.c
Normal file
233
applications/desktop/views/desktop_view_locked.c
Normal file
@@ -0,0 +1,233 @@
|
||||
#include <projdefs.h>
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/icon.h>
|
||||
#include <gui/view.h>
|
||||
#include <portmacro.h>
|
||||
|
||||
#include "../desktop_settings/desktop_settings.h"
|
||||
#include "../desktop_i.h"
|
||||
#include "desktop_view_locked.h"
|
||||
|
||||
#define DOOR_MOVING_INTERVAL_MS (1000 / 16)
|
||||
#define UNLOCKED_HINT_TIMEOUT_MS (2000)
|
||||
|
||||
#define DOOR_OFFSET_START -55
|
||||
#define DOOR_OFFSET_END 0
|
||||
|
||||
#define DOOR_L_FINAL_POS 0
|
||||
#define DOOR_R_FINAL_POS 60
|
||||
|
||||
#define UNLOCK_CNT 3
|
||||
#define UNLOCK_RST_TIMEOUT 600
|
||||
|
||||
struct DesktopViewLocked {
|
||||
View* view;
|
||||
DesktopViewLockedCallback callback;
|
||||
void* context;
|
||||
|
||||
TimerHandle_t timer;
|
||||
uint8_t lock_count;
|
||||
uint32_t lock_lastpress;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t hint_icon_expire_at;
|
||||
bool unlocked_hint;
|
||||
bool locked;
|
||||
bool pin_locked;
|
||||
|
||||
int8_t door_offset;
|
||||
bool doors_closing;
|
||||
} DesktopViewLockedModel;
|
||||
|
||||
void desktop_view_locked_set_callback(
|
||||
DesktopViewLocked* locked_view,
|
||||
DesktopViewLockedCallback callback,
|
||||
void* context) {
|
||||
furi_assert(locked_view);
|
||||
furi_assert(callback);
|
||||
locked_view->callback = callback;
|
||||
locked_view->context = context;
|
||||
}
|
||||
|
||||
static void locked_view_timer_callback(TimerHandle_t timer) {
|
||||
DesktopViewLocked* locked_view = pvTimerGetTimerID(timer);
|
||||
locked_view->callback(DesktopLockedEventUpdate, locked_view->context);
|
||||
}
|
||||
|
||||
static void desktop_view_locked_doors_draw(Canvas* canvas, DesktopViewLockedModel* model) {
|
||||
int8_t offset = model->door_offset;
|
||||
uint8_t door_left_x = DOOR_L_FINAL_POS + offset;
|
||||
uint8_t door_right_x = DOOR_R_FINAL_POS - offset;
|
||||
uint8_t height = icon_get_height(&I_DoorLeft_70x55);
|
||||
canvas_draw_icon(canvas, door_left_x, canvas_height(canvas) - height, &I_DoorLeft_70x55);
|
||||
canvas_draw_icon(canvas, door_right_x, canvas_height(canvas) - height, &I_DoorRight_70x55);
|
||||
}
|
||||
|
||||
static bool desktop_view_locked_doors_move(DesktopViewLockedModel* model) {
|
||||
bool stop = false;
|
||||
if(model->door_offset < DOOR_OFFSET_END) {
|
||||
model->door_offset = CLAMP(model->door_offset + 5, DOOR_OFFSET_END, DOOR_OFFSET_START);
|
||||
stop = true;
|
||||
}
|
||||
|
||||
return stop;
|
||||
}
|
||||
|
||||
static void desktop_view_locked_update_hint_icon_timeout(DesktopViewLocked* locked_view) {
|
||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||
model->hint_icon_expire_at = osKernelGetTickCount() + osKernelGetTickFreq();
|
||||
view_commit_model(locked_view->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_locked_update(DesktopViewLocked* locked_view) {
|
||||
bool stop_timer = false;
|
||||
|
||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||
if(model->locked) {
|
||||
model->doors_closing = desktop_view_locked_doors_move(model);
|
||||
stop_timer = !model->doors_closing;
|
||||
} else {
|
||||
model->unlocked_hint = false;
|
||||
stop_timer = true;
|
||||
}
|
||||
view_commit_model(locked_view->view, true);
|
||||
|
||||
if(stop_timer) {
|
||||
xTimerStop(locked_view->timer, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
static void desktop_view_locked_draw(Canvas* canvas, void* model) {
|
||||
DesktopViewLockedModel* m = model;
|
||||
uint32_t now = osKernelGetTickCount();
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
if(m->locked) {
|
||||
if(m->doors_closing) {
|
||||
desktop_view_locked_doors_draw(canvas, m);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Locked");
|
||||
} else if((now < m->hint_icon_expire_at) && !m->pin_locked) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_bold_rounded_frame(canvas, 14, 2 + STATUS_BAR_Y_SHIFT, 99, 48);
|
||||
elements_multiline_text(canvas, 65, 20 + STATUS_BAR_Y_SHIFT, "To unlock\npress:");
|
||||
canvas_draw_icon(canvas, 65, 36 + STATUS_BAR_Y_SHIFT, &I_Back3_45x8);
|
||||
canvas_draw_icon(canvas, 16, 7 + STATUS_BAR_Y_SHIFT, &I_WarningDolphin_45x42);
|
||||
canvas_draw_dot(canvas, 17, 61);
|
||||
}
|
||||
} else {
|
||||
if(m->unlocked_hint) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_framed(canvas, 42, 30 + STATUS_BAR_Y_SHIFT, "Unlocked");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
View* desktop_view_locked_get_view(DesktopViewLocked* locked_view) {
|
||||
furi_assert(locked_view);
|
||||
return locked_view->view;
|
||||
}
|
||||
|
||||
static bool desktop_view_locked_input(InputEvent* event, void* context) {
|
||||
furi_assert(event);
|
||||
furi_assert(context);
|
||||
DesktopViewLocked* locked_view = context;
|
||||
bool locked = false;
|
||||
bool locked_with_pin = false;
|
||||
bool doors_closing = false;
|
||||
uint32_t press_time = xTaskGetTickCount();
|
||||
|
||||
{
|
||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||
bool changed = false;
|
||||
locked = model->locked;
|
||||
locked_with_pin = model->pin_locked;
|
||||
doors_closing = model->doors_closing;
|
||||
if(!locked && model->unlocked_hint && event->type == InputTypePress) {
|
||||
model->unlocked_hint = false;
|
||||
changed = true;
|
||||
}
|
||||
view_commit_model(locked_view->view, changed);
|
||||
}
|
||||
|
||||
if(!locked || doors_closing || (event->type != InputTypeShort)) {
|
||||
return locked;
|
||||
}
|
||||
|
||||
if(locked_with_pin) {
|
||||
locked_view->callback(DesktopLockedEventShowPinInput, locked_view->context);
|
||||
} else {
|
||||
if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) {
|
||||
locked_view->lock_lastpress = press_time;
|
||||
locked_view->lock_count = 0;
|
||||
}
|
||||
|
||||
desktop_view_locked_update_hint_icon_timeout(locked_view);
|
||||
if(event->key == InputKeyBack) {
|
||||
locked_view->lock_lastpress = press_time;
|
||||
locked_view->lock_count++;
|
||||
if(locked_view->lock_count == UNLOCK_CNT) {
|
||||
desktop_view_locked_unlock(locked_view);
|
||||
locked_view->callback(DesktopLockedEventUnlocked, locked_view->context);
|
||||
}
|
||||
} else {
|
||||
locked_view->lock_count = 0;
|
||||
}
|
||||
|
||||
locked_view->lock_lastpress = press_time;
|
||||
}
|
||||
|
||||
return locked;
|
||||
}
|
||||
|
||||
DesktopViewLocked* desktop_view_locked_alloc() {
|
||||
DesktopViewLocked* locked_view = furi_alloc(sizeof(DesktopViewLocked));
|
||||
locked_view->view = view_alloc();
|
||||
locked_view->timer =
|
||||
xTimerCreate(NULL, 1000 / 16, pdTRUE, locked_view, locked_view_timer_callback);
|
||||
|
||||
locked_view->view = view_alloc();
|
||||
view_allocate_model(locked_view->view, ViewModelTypeLocking, sizeof(DesktopViewLockedModel));
|
||||
view_set_context(locked_view->view, locked_view);
|
||||
view_set_draw_callback(locked_view->view, desktop_view_locked_draw);
|
||||
view_set_input_callback(locked_view->view, desktop_view_locked_input);
|
||||
|
||||
return locked_view;
|
||||
}
|
||||
|
||||
void desktop_view_locked_free(DesktopViewLocked* locked_view) {
|
||||
furi_assert(locked_view);
|
||||
osTimerDelete(locked_view->timer);
|
||||
view_free(locked_view->view);
|
||||
free(locked_view);
|
||||
}
|
||||
|
||||
void desktop_view_locked_close_doors(DesktopViewLocked* locked_view) {
|
||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||
model->doors_closing = true;
|
||||
model->door_offset = DOOR_OFFSET_START;
|
||||
view_commit_model(locked_view->view, true);
|
||||
xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(DOOR_MOVING_INTERVAL_MS), portMAX_DELAY);
|
||||
}
|
||||
|
||||
void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked) {
|
||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||
model->locked = true;
|
||||
model->pin_locked = pin_locked;
|
||||
view_commit_model(locked_view->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_locked_unlock(DesktopViewLocked* locked_view) {
|
||||
furi_assert(locked_view);
|
||||
|
||||
locked_view->lock_count = 0;
|
||||
DesktopViewLockedModel* model = view_get_model(locked_view->view);
|
||||
model->locked = false;
|
||||
model->pin_locked = false;
|
||||
model->unlocked_hint = true;
|
||||
view_commit_model(locked_view->view, true);
|
||||
xTimerChangePeriod(locked_view->timer, pdMS_TO_TICKS(UNLOCKED_HINT_TIMEOUT_MS), portMAX_DELAY);
|
||||
}
|
||||
21
applications/desktop/views/desktop_view_locked.h
Normal file
21
applications/desktop/views/desktop_view_locked.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "../desktop_settings/desktop_settings.h"
|
||||
#include "../views/desktop_events.h"
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct DesktopViewLocked DesktopViewLocked;
|
||||
|
||||
typedef void (*DesktopViewLockedCallback)(DesktopEvent event, void* context);
|
||||
|
||||
void desktop_view_locked_set_callback(
|
||||
DesktopViewLocked* locked_view,
|
||||
DesktopViewLockedCallback callback,
|
||||
void* context);
|
||||
void desktop_view_locked_update(DesktopViewLocked* locked_view);
|
||||
View* desktop_view_locked_get_view(DesktopViewLocked* locked_view);
|
||||
DesktopViewLocked* desktop_view_locked_alloc();
|
||||
void desktop_view_locked_free(DesktopViewLocked* locked_view);
|
||||
void desktop_view_locked_lock(DesktopViewLocked* locked_view, bool pin_locked);
|
||||
void desktop_view_locked_unlock(DesktopViewLocked* locked_view);
|
||||
void desktop_view_locked_close_doors(DesktopViewLocked* locked_view);
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#include "../desktop_i.h"
|
||||
#include "desktop_main.h"
|
||||
#include "desktop_view_main.h"
|
||||
|
||||
struct DesktopMainView {
|
||||
View* view;
|
||||
340
applications/desktop/views/desktop_view_pin_input.c
Normal file
340
applications/desktop/views/desktop_view_pin_input.c
Normal file
@@ -0,0 +1,340 @@
|
||||
#include <gui/canvas.h>
|
||||
#include <furi.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/elements.h>
|
||||
#include <stdint.h>
|
||||
#include <portmacro.h>
|
||||
|
||||
#include "desktop_view_pin_input.h"
|
||||
#include "../desktop_settings/desktop_settings.h"
|
||||
|
||||
#define NO_ACTIVITY_TIMEOUT 15000
|
||||
|
||||
#define PIN_CELL_WIDTH 13
|
||||
#define DEFAULT_PIN_X 64
|
||||
#define DEFAULT_PIN_Y 32
|
||||
|
||||
struct DesktopViewPinInput {
|
||||
View* view;
|
||||
DesktopViewPinInputCallback back_callback;
|
||||
DesktopViewPinInputCallback timeout_callback;
|
||||
DesktopViewPinInputDoneCallback done_callback;
|
||||
void* context;
|
||||
TimerHandle_t timer;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
PinCode pin;
|
||||
bool pin_hidden;
|
||||
bool locked_input;
|
||||
uint8_t pin_x;
|
||||
uint8_t pin_y;
|
||||
const char* primary_str;
|
||||
uint8_t primary_str_x;
|
||||
uint8_t primary_str_y;
|
||||
const char* secondary_str;
|
||||
uint8_t secondary_str_x;
|
||||
uint8_t secondary_str_y;
|
||||
const char* button_label;
|
||||
} DesktopViewPinInputModel;
|
||||
|
||||
static bool desktop_view_pin_input_input(InputEvent* event, void* context) {
|
||||
furi_assert(event);
|
||||
furi_assert(context);
|
||||
|
||||
DesktopViewPinInput* pin_input = context;
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
|
||||
bool call_back_callback = false;
|
||||
bool call_done_callback = false;
|
||||
PinCode pin_code = {0};
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
switch(event->key) {
|
||||
case InputKeyRight:
|
||||
case InputKeyLeft:
|
||||
case InputKeyDown:
|
||||
case InputKeyUp:
|
||||
if(!model->locked_input) {
|
||||
if(model->pin.length < MAX_PIN_SIZE) {
|
||||
model->pin.data[model->pin.length++] = event->key;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
if(model->pin.length >= MIN_PIN_SIZE) {
|
||||
call_done_callback = true;
|
||||
pin_code = model->pin;
|
||||
}
|
||||
break;
|
||||
case InputKeyBack:
|
||||
if(!model->locked_input) {
|
||||
if(model->pin.length > 0) {
|
||||
model->pin.length = 0;
|
||||
} else {
|
||||
call_back_callback = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
furi_assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
view_commit_model(pin_input->view, true);
|
||||
|
||||
if(call_done_callback && pin_input->done_callback) {
|
||||
pin_input->done_callback(&pin_code, pin_input->context);
|
||||
} else if(call_back_callback && pin_input->back_callback) {
|
||||
pin_input->back_callback(pin_input->context);
|
||||
}
|
||||
|
||||
xTimerStart(pin_input->timer, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInputModel* model) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(model);
|
||||
|
||||
uint8_t draw_pin_size = MAX(4, model->pin.length + 1);
|
||||
if(model->locked_input || (model->pin.length == MAX_PIN_SIZE)) {
|
||||
draw_pin_size = model->pin.length;
|
||||
}
|
||||
|
||||
uint8_t x = model->pin_x - (draw_pin_size * (PIN_CELL_WIDTH - 1)) / 2;
|
||||
uint8_t y = model->pin_y - (PIN_CELL_WIDTH / 2);
|
||||
|
||||
for(int i = 0; i < draw_pin_size; ++i) {
|
||||
canvas_draw_frame(canvas, x, y, PIN_CELL_WIDTH, PIN_CELL_WIDTH);
|
||||
if(i < model->pin.length) {
|
||||
if(model->pin_hidden) {
|
||||
canvas_draw_icon(canvas, x + 3, y + 3, &I_Pin_star_7x7);
|
||||
} else {
|
||||
switch(model->pin.data[i]) {
|
||||
case InputKeyDown:
|
||||
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_down_7x9);
|
||||
break;
|
||||
case InputKeyUp:
|
||||
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up7x9);
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_left_9x7);
|
||||
break;
|
||||
case InputKeyRight:
|
||||
canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_right_9x7);
|
||||
break;
|
||||
default:
|
||||
furi_assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(i == model->pin.length) {
|
||||
canvas_draw_icon(canvas, x + 4, y + PIN_CELL_WIDTH + 1, &I_Pin_pointer_5x3);
|
||||
}
|
||||
x += PIN_CELL_WIDTH - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void desktop_view_pin_input_draw(Canvas* canvas, void* context) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(context);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
DesktopViewPinInputModel* model = context;
|
||||
desktop_view_pin_input_draw_cells(canvas, model);
|
||||
|
||||
if((model->pin.length > 0) && !model->locked_input) {
|
||||
canvas_draw_icon(canvas, 4, 53, &I_Pin_back_full_40x8);
|
||||
}
|
||||
|
||||
if(model->button_label && ((model->pin.length >= MIN_PIN_SIZE) || model->locked_input)) {
|
||||
elements_button_center(canvas, model->button_label);
|
||||
}
|
||||
|
||||
if(model->primary_str) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, model->primary_str_x, model->primary_str_y, model->primary_str);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
}
|
||||
|
||||
if(model->secondary_str) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(
|
||||
canvas, model->secondary_str_x, model->secondary_str_y, model->secondary_str);
|
||||
}
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_timer_callback(TimerHandle_t timer) {
|
||||
DesktopViewPinInput* pin_input = pvTimerGetTimerID(timer);
|
||||
|
||||
if(pin_input->timeout_callback) {
|
||||
pin_input->timeout_callback(pin_input->context);
|
||||
}
|
||||
}
|
||||
|
||||
static void desktop_view_pin_input_enter(void* context) {
|
||||
DesktopViewPinInput* pin_input = context;
|
||||
xTimerStart(pin_input->timer, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static void desktop_view_pin_input_exit(void* context) {
|
||||
DesktopViewPinInput* pin_input = context;
|
||||
xTimerStop(pin_input->timer, portMAX_DELAY);
|
||||
}
|
||||
|
||||
DesktopViewPinInput* desktop_view_pin_input_alloc(void) {
|
||||
DesktopViewPinInput* pin_input = furi_alloc(sizeof(DesktopViewPinInput));
|
||||
pin_input->view = view_alloc();
|
||||
view_allocate_model(pin_input->view, ViewModelTypeLocking, sizeof(DesktopViewPinInputModel));
|
||||
view_set_context(pin_input->view, pin_input);
|
||||
view_set_draw_callback(pin_input->view, desktop_view_pin_input_draw);
|
||||
view_set_input_callback(pin_input->view, desktop_view_pin_input_input);
|
||||
pin_input->timer = xTimerCreate(
|
||||
NULL,
|
||||
pdMS_TO_TICKS(NO_ACTIVITY_TIMEOUT),
|
||||
pdFALSE,
|
||||
pin_input,
|
||||
desktop_view_pin_input_timer_callback);
|
||||
view_set_enter_callback(pin_input->view, desktop_view_pin_input_enter);
|
||||
view_set_exit_callback(pin_input->view, desktop_view_pin_input_exit);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->pin_x = DEFAULT_PIN_X;
|
||||
model->pin_y = DEFAULT_PIN_Y;
|
||||
model->pin.length = 0;
|
||||
view_commit_model(pin_input->view, false);
|
||||
|
||||
return pin_input;
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_free(DesktopViewPinInput* pin_input) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
xTimerStop(pin_input->timer, portMAX_DELAY);
|
||||
while(xTimerIsTimerActive(pin_input->timer)) {
|
||||
delay(1);
|
||||
}
|
||||
xTimerDelete(pin_input->timer, portMAX_DELAY);
|
||||
|
||||
view_free(pin_input->view);
|
||||
free(pin_input);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_lock_input(DesktopViewPinInput* pin_input) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->locked_input = true;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_unlock_input(DesktopViewPinInput* pin_input) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->locked_input = false;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const PinCode* pin) {
|
||||
furi_assert(pin_input);
|
||||
furi_assert(pin);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->pin = *pin;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_reset_pin(DesktopViewPinInput* pin_input) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->pin.length = 0;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_hide_pin(DesktopViewPinInput* pin_input, bool pin_hidden) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->pin_hidden = pin_hidden;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_label_button(DesktopViewPinInput* pin_input, const char* label) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->button_label = label;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_label_primary(
|
||||
DesktopViewPinInput* pin_input,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
const char* label) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->primary_str = label;
|
||||
model->primary_str_x = x;
|
||||
model->primary_str_y = y;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_label_secondary(
|
||||
DesktopViewPinInput* pin_input,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
const char* label) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->secondary_str = label;
|
||||
model->secondary_str_x = x;
|
||||
model->secondary_str_y = y;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_pin_position(DesktopViewPinInput* pin_input, uint8_t x, uint8_t y) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->pin_x = x;
|
||||
model->pin_y = y;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_context(DesktopViewPinInput* pin_input, void* context) {
|
||||
furi_assert(pin_input);
|
||||
pin_input->context = context;
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_timeout_callback(
|
||||
DesktopViewPinInput* pin_input,
|
||||
DesktopViewPinInputCallback callback) {
|
||||
furi_assert(pin_input);
|
||||
pin_input->timeout_callback = callback;
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_back_callback(
|
||||
DesktopViewPinInput* pin_input,
|
||||
DesktopViewPinInputCallback callback) {
|
||||
furi_assert(pin_input);
|
||||
pin_input->back_callback = callback;
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_done_callback(
|
||||
DesktopViewPinInput* pin_input,
|
||||
DesktopViewPinInputDoneCallback callback) {
|
||||
furi_assert(pin_input);
|
||||
pin_input->done_callback = callback;
|
||||
}
|
||||
|
||||
View* desktop_view_pin_input_get_view(DesktopViewPinInput* pin_input) {
|
||||
furi_assert(pin_input);
|
||||
return pin_input->view;
|
||||
}
|
||||
40
applications/desktop/views/desktop_view_pin_input.h
Normal file
40
applications/desktop/views/desktop_view_pin_input.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "desktop/desktop_settings/desktop_settings.h"
|
||||
|
||||
typedef void (*DesktopViewPinInputCallback)(void*);
|
||||
typedef void (*DesktopViewPinInputDoneCallback)(const PinCode* pin_code, void*);
|
||||
typedef struct DesktopViewPinInput DesktopViewPinInput;
|
||||
|
||||
DesktopViewPinInput* desktop_view_pin_input_alloc(void);
|
||||
void desktop_view_pin_input_free(DesktopViewPinInput*);
|
||||
|
||||
void desktop_view_pin_input_set_pin(DesktopViewPinInput* pin_input, const PinCode* pin);
|
||||
void desktop_view_pin_input_reset_pin(DesktopViewPinInput* pin_input);
|
||||
void desktop_view_pin_input_hide_pin(DesktopViewPinInput* pin_input, bool pin_hidden);
|
||||
void desktop_view_pin_input_set_label_button(DesktopViewPinInput* pin_input, const char* label);
|
||||
void desktop_view_pin_input_set_label_primary(
|
||||
DesktopViewPinInput* pin_input,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
const char* label);
|
||||
void desktop_view_pin_input_set_label_secondary(
|
||||
DesktopViewPinInput* pin_input,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
const char* label);
|
||||
void desktop_view_pin_input_set_pin_position(DesktopViewPinInput* pin_input, uint8_t x, uint8_t y);
|
||||
View* desktop_view_pin_input_get_view(DesktopViewPinInput*);
|
||||
void desktop_view_pin_input_set_done_callback(
|
||||
DesktopViewPinInput* pin_input,
|
||||
DesktopViewPinInputDoneCallback callback);
|
||||
void desktop_view_pin_input_set_back_callback(
|
||||
DesktopViewPinInput* pin_input,
|
||||
DesktopViewPinInputCallback callback);
|
||||
void desktop_view_pin_input_set_timeout_callback(
|
||||
DesktopViewPinInput* pin_input,
|
||||
DesktopViewPinInputCallback callback);
|
||||
void desktop_view_pin_input_set_context(DesktopViewPinInput* pin_input, void* context);
|
||||
void desktop_view_pin_input_lock_input(DesktopViewPinInput* pin_input);
|
||||
void desktop_view_pin_input_unlock_input(DesktopViewPinInput* pin_input);
|
||||
80
applications/desktop/views/desktop_view_pin_setup_done.c
Normal file
80
applications/desktop/views/desktop_view_pin_setup_done.c
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/canvas.h>
|
||||
#include <toolbox/version.h>
|
||||
#include <assets_icons.h>
|
||||
#include <dolphin/helpers/dolphin_state.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#include "../desktop_i.h"
|
||||
#include "desktop_view_pin_setup_done.h"
|
||||
|
||||
struct DesktopViewPinSetupDone {
|
||||
View* view;
|
||||
DesktopViewPinSetupDoneDoneCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
static void desktop_view_pin_done_draw(Canvas* canvas, void* model) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(model);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 64, 0, AlignCenter, AlignTop, "Prepare to use\narrows as\nPIN symbols");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text(canvas, 58, 24, "Prepare to use\narrows as\nPIN symbols");
|
||||
|
||||
canvas_draw_icon(canvas, 16, 18, &I_Pin_attention_dpad_29x29);
|
||||
elements_button_right(canvas, "Next");
|
||||
}
|
||||
|
||||
static bool desktop_view_pin_done_input(InputEvent* event, void* context) {
|
||||
furi_assert(event);
|
||||
furi_assert(context);
|
||||
|
||||
DesktopViewPinSetupDone* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if((event->key == InputKeyRight) && (event->type == InputTypeShort)) {
|
||||
instance->callback(instance->context);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_view_pin_done_set_callback(
|
||||
DesktopViewPinSetupDone* instance,
|
||||
DesktopViewPinSetupDoneDoneCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
DesktopViewPinSetupDone* desktop_view_pin_done_alloc() {
|
||||
DesktopViewPinSetupDone* view = furi_alloc(sizeof(DesktopViewPinSetupDone));
|
||||
view->view = view_alloc();
|
||||
view_allocate_model(view->view, ViewModelTypeLockFree, 1);
|
||||
view_set_context(view->view, view);
|
||||
view_set_draw_callback(view->view, desktop_view_pin_done_draw);
|
||||
view_set_input_callback(view->view, desktop_view_pin_done_input);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
void desktop_view_pin_done_free(DesktopViewPinSetupDone* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
view_free(instance->view);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
View* desktop_view_pin_done_get_view(DesktopViewPinSetupDone* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->view;
|
||||
}
|
||||
15
applications/desktop/views/desktop_view_pin_setup_done.h
Normal file
15
applications/desktop/views/desktop_view_pin_setup_done.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct DesktopViewPinSetupDone DesktopViewPinSetupDone;
|
||||
|
||||
typedef void (*DesktopViewPinSetupDoneDoneCallback)(void*);
|
||||
|
||||
void desktop_view_pin_done_set_callback(
|
||||
DesktopViewPinSetupDone* instance,
|
||||
DesktopViewPinSetupDoneDoneCallback callback,
|
||||
void* context);
|
||||
DesktopViewPinSetupDone* desktop_view_pin_done_alloc();
|
||||
void desktop_view_pin_done_free(DesktopViewPinSetupDone* instance);
|
||||
View* desktop_view_pin_done_get_view(DesktopViewPinSetupDone* instance);
|
||||
109
applications/desktop/views/desktop_view_pin_timeout.c
Normal file
109
applications/desktop/views/desktop_view_pin_timeout.c
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
#include <furi.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <FreeRTOS.h>
|
||||
#include <portmacro.h>
|
||||
#include <projdefs.h>
|
||||
#include <input/input.h>
|
||||
#include <gui/canvas.h>
|
||||
#include <gui/view.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
16
applications/desktop/views/desktop_view_pin_timeout.h
Normal file
16
applications/desktop/views/desktop_view_pin_timeout.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef void (*DesktopViewPinTimeoutDoneCallback)(void*);
|
||||
typedef struct DesktopViewPinTimeout DesktopViewPinTimeout;
|
||||
|
||||
void desktop_view_pin_timeout_set_callback(
|
||||
DesktopViewPinTimeout* instance,
|
||||
DesktopViewPinTimeoutDoneCallback callback,
|
||||
void* context);
|
||||
DesktopViewPinTimeout* desktop_view_pin_timeout_alloc(void);
|
||||
void desktop_view_pin_timeout_free(DesktopViewPinTimeout*);
|
||||
void desktop_view_pin_timeout_start(DesktopViewPinTimeout* instance, uint32_t time_left);
|
||||
View* desktop_view_pin_timeout_get_view(DesktopViewPinTimeout* instance);
|
||||
@@ -80,15 +80,11 @@ Dolphin* dolphin_alloc() {
|
||||
dolphin->event_queue = osMessageQueueNew(8, sizeof(DolphinEvent), NULL);
|
||||
dolphin->pubsub = furi_pubsub_alloc();
|
||||
dolphin->butthurt_timer = xTimerCreate(
|
||||
"Butthurt timer", HOURS_IN_TICKS(2 * 24), pdTRUE, dolphin, dolphin_butthurt_timer_callback);
|
||||
NULL, HOURS_IN_TICKS(2 * 24), pdTRUE, dolphin, dolphin_butthurt_timer_callback);
|
||||
dolphin->flush_timer =
|
||||
xTimerCreate("Flush timer", 30 * 1000, pdFALSE, dolphin, dolphin_flush_timer_callback);
|
||||
xTimerCreate(NULL, 30 * 1000, pdFALSE, dolphin, dolphin_flush_timer_callback);
|
||||
dolphin->clear_limits_timer = xTimerCreate(
|
||||
"Clear limits timer",
|
||||
HOURS_IN_TICKS(24),
|
||||
pdTRUE,
|
||||
dolphin,
|
||||
dolphin_clear_limits_timer_callback);
|
||||
NULL, HOURS_IN_TICKS(24), pdTRUE, dolphin, dolphin_clear_limits_timer_callback);
|
||||
|
||||
return dolphin;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#include "elements.h"
|
||||
#include <assets_icons.h>
|
||||
#include "furi_hal_resources.h"
|
||||
#include <furi_hal.h>
|
||||
#include "gui/canvas.h"
|
||||
|
||||
#include <gui/icon_i.h>
|
||||
@@ -337,6 +340,47 @@ void elements_slightly_rounded_box(
|
||||
canvas_draw_rbox(canvas, x, y, width, height, 1);
|
||||
}
|
||||
|
||||
void elements_bold_rounded_frame(
|
||||
Canvas* canvas,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height) {
|
||||
furi_assert(canvas);
|
||||
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_box(canvas, x + 2, y + 2, width - 3, height - 3);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
canvas_draw_line(canvas, x + 3, y, x + width - 3, y);
|
||||
canvas_draw_line(canvas, x + 2, y + 1, x + width - 2, y + 1);
|
||||
|
||||
canvas_draw_line(canvas, x, y + 3, x, y + height - 3);
|
||||
canvas_draw_line(canvas, x + 1, y + 2, x + 1, y + height - 2);
|
||||
|
||||
canvas_draw_line(canvas, x + width, y + 3, x + width, y + height - 3);
|
||||
canvas_draw_line(canvas, x + width - 1, y + 2, x + width - 1, y + height - 2);
|
||||
|
||||
canvas_draw_line(canvas, x + 3, y + height, x + width - 3, y + height);
|
||||
canvas_draw_line(canvas, x + 2, y + height - 1, x + width - 2, y + height - 1);
|
||||
|
||||
canvas_draw_dot(canvas, x + 2, y + 2);
|
||||
canvas_draw_dot(canvas, x + 3, y + 2);
|
||||
canvas_draw_dot(canvas, x + 2, y + 3);
|
||||
|
||||
canvas_draw_dot(canvas, x + width - 2, y + 2);
|
||||
canvas_draw_dot(canvas, x + width - 3, y + 2);
|
||||
canvas_draw_dot(canvas, x + width - 2, y + 3);
|
||||
|
||||
canvas_draw_dot(canvas, x + 2, y + height - 2);
|
||||
canvas_draw_dot(canvas, x + 3, y + height - 2);
|
||||
canvas_draw_dot(canvas, x + 2, y + height - 3);
|
||||
|
||||
canvas_draw_dot(canvas, x + width - 2, y + height - 2);
|
||||
canvas_draw_dot(canvas, x + width - 3, y + height - 2);
|
||||
canvas_draw_dot(canvas, x + width - 2, y + height - 3);
|
||||
}
|
||||
|
||||
void elements_bubble(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
|
||||
furi_assert(canvas);
|
||||
canvas_draw_rframe(canvas, x + 4, y, width, height, 3);
|
||||
|
||||
@@ -150,6 +150,19 @@ void elements_slightly_rounded_box(
|
||||
uint8_t width,
|
||||
uint8_t height);
|
||||
|
||||
/** Draw bold rounded frame
|
||||
*
|
||||
* @param canvas Canvas instance
|
||||
* @param x, y top left corner coordinates
|
||||
* @param width, height size of frame
|
||||
*/
|
||||
void elements_bold_rounded_frame(
|
||||
Canvas* canvas,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height);
|
||||
|
||||
/** Draw bubble frame for text
|
||||
*
|
||||
* @param canvas Canvas instance
|
||||
|
||||
@@ -1,478 +0,0 @@
|
||||
#include "code_input.h"
|
||||
#include <gui/elements.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define MAX_CODE_LEN 10
|
||||
|
||||
struct CodeInput {
|
||||
View* view;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CodeInputStateVerify,
|
||||
CodeInputStateUpdate,
|
||||
CodeInputStateTotal,
|
||||
} CodeInputStateEnum;
|
||||
|
||||
typedef enum {
|
||||
CodeInputFirst,
|
||||
CodeInputSecond,
|
||||
CodeInputTotal,
|
||||
} CodeInputsEnum;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t current;
|
||||
bool ext_update;
|
||||
|
||||
uint8_t input_length[CodeInputTotal];
|
||||
uint8_t local_buffer[CodeInputTotal][MAX_CODE_LEN];
|
||||
|
||||
CodeInputOkCallback ok_callback;
|
||||
CodeInputFailCallback fail_callback;
|
||||
void* callback_context;
|
||||
|
||||
const char* header;
|
||||
|
||||
uint8_t* ext_buffer;
|
||||
uint8_t* ext_buffer_length;
|
||||
} CodeInputModel;
|
||||
|
||||
static const Icon* keys_assets[] = {
|
||||
[InputKeyUp] = &I_ButtonUp_7x4,
|
||||
[InputKeyDown] = &I_ButtonDown_7x4,
|
||||
[InputKeyRight] = &I_ButtonRight_4x7,
|
||||
[InputKeyLeft] = &I_ButtonLeft_4x7,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Compare buffers
|
||||
*
|
||||
* @param in Input buffer pointer
|
||||
* @param len_in Input array length
|
||||
* @param src Source buffer pointer
|
||||
* @param len_src Source array length
|
||||
*/
|
||||
|
||||
bool code_input_compare(uint8_t* in, size_t len_in, uint8_t* src, size_t len_src) {
|
||||
bool result = false;
|
||||
do {
|
||||
result = (len_in && len_src);
|
||||
if(!result) {
|
||||
break;
|
||||
}
|
||||
result = (len_in == len_src);
|
||||
if(!result) {
|
||||
break;
|
||||
}
|
||||
for(size_t i = 0; i < len_in; i++) {
|
||||
result = (in[i] == src[i]);
|
||||
if(!result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare local buffers
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
static bool code_input_compare_local(CodeInputModel* model) {
|
||||
uint8_t* source = model->local_buffer[CodeInputFirst];
|
||||
size_t source_length = model->input_length[CodeInputFirst];
|
||||
|
||||
uint8_t* input = model->local_buffer[CodeInputSecond];
|
||||
size_t input_length = model->input_length[CodeInputSecond];
|
||||
|
||||
return code_input_compare(input, input_length, source, source_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare ext with local
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
static bool code_input_compare_ext(CodeInputModel* model) {
|
||||
uint8_t* input = model->local_buffer[CodeInputFirst];
|
||||
size_t input_length = model->input_length[CodeInputFirst];
|
||||
|
||||
uint8_t* source = model->ext_buffer;
|
||||
size_t source_length = *model->ext_buffer_length;
|
||||
|
||||
return code_input_compare(input, input_length, source, source_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set ext buffer
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
static void code_input_set_ext(CodeInputModel* model) {
|
||||
*model->ext_buffer_length = model->input_length[CodeInputFirst];
|
||||
for(size_t i = 0; i <= model->input_length[CodeInputFirst]; i++) {
|
||||
model->ext_buffer[i] = model->local_buffer[CodeInputFirst][i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draw input sequence
|
||||
*
|
||||
* @param canvas
|
||||
* @param buffer
|
||||
* @param length
|
||||
* @param x
|
||||
* @param y
|
||||
* @param active
|
||||
*/
|
||||
static void code_input_draw_sequence(
|
||||
Canvas* canvas,
|
||||
uint8_t* buffer,
|
||||
uint8_t length,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
bool active) {
|
||||
uint8_t pos_x = x + 6;
|
||||
uint8_t pos_y = y + 3;
|
||||
|
||||
if(active) canvas_draw_icon(canvas, x - 4, y + 5, &I_ButtonRightSmall_3x5);
|
||||
|
||||
elements_slightly_rounded_frame(canvas, x, y, 116, 15);
|
||||
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
// maybe symmetrical assets? :-/
|
||||
uint8_t offset_y = buffer[i] < 2 ? 2 + (buffer[i] * 2) : 1;
|
||||
canvas_draw_icon(canvas, pos_x, pos_y + offset_y, keys_assets[buffer[i]]);
|
||||
pos_x += buffer[i] > 1 ? 9 : 11;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset input count
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
static void code_input_reset_count(CodeInputModel* model) {
|
||||
model->input_length[model->current] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call input callback
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
static void code_input_call_ok_callback(CodeInputModel* model) {
|
||||
if(model->ok_callback != NULL) {
|
||||
model->ok_callback(model->callback_context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call changed callback
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
static void code_input_call_fail_callback(CodeInputModel* model) {
|
||||
if(model->fail_callback != NULL) {
|
||||
model->fail_callback(model->callback_context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle Back button
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
static bool code_input_handle_back(CodeInputModel* model) {
|
||||
if(model->current && !model->input_length[model->current]) {
|
||||
--model->current;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(model->input_length[model->current]) {
|
||||
code_input_reset_count(model);
|
||||
return true;
|
||||
}
|
||||
|
||||
code_input_call_fail_callback(model);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle OK button
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
static void code_input_handle_ok(CodeInputModel* model) {
|
||||
switch(model->state) {
|
||||
case CodeInputStateVerify:
|
||||
|
||||
if(code_input_compare_ext(model)) {
|
||||
if(model->ext_update) {
|
||||
model->state = CodeInputStateUpdate;
|
||||
} else {
|
||||
code_input_call_ok_callback(model);
|
||||
}
|
||||
}
|
||||
code_input_reset_count(model);
|
||||
break;
|
||||
|
||||
case CodeInputStateUpdate:
|
||||
|
||||
if(!model->current && model->input_length[model->current]) {
|
||||
model->current++;
|
||||
} else {
|
||||
if(code_input_compare_local(model)) {
|
||||
if(model->ext_update) {
|
||||
code_input_set_ext(model);
|
||||
}
|
||||
code_input_call_ok_callback(model);
|
||||
} else {
|
||||
code_input_reset_count(model);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle input
|
||||
*
|
||||
* @param model
|
||||
* @param key
|
||||
*/
|
||||
|
||||
size_t code_input_push(uint8_t* buffer, size_t length, InputKey key) {
|
||||
buffer[length] = key;
|
||||
length = CLAMP(length + 1, MAX_CODE_LEN, 0);
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle D-pad keys
|
||||
*
|
||||
* @param model
|
||||
* @param key
|
||||
*/
|
||||
static void code_input_handle_dpad(CodeInputModel* model, InputKey key) {
|
||||
uint8_t at = model->current;
|
||||
size_t new_length = code_input_push(model->local_buffer[at], model->input_length[at], key);
|
||||
model->input_length[at] = new_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draw callback
|
||||
*
|
||||
* @param canvas
|
||||
* @param _model
|
||||
*/
|
||||
static void code_input_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
CodeInputModel* model = _model;
|
||||
uint8_t y_offset = 0;
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
if(model->header && strlen(model->header)) {
|
||||
canvas_draw_str(canvas, 2, 9, model->header);
|
||||
} else {
|
||||
y_offset = 4;
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
switch(model->state) {
|
||||
case CodeInputStateVerify:
|
||||
code_input_draw_sequence(
|
||||
canvas,
|
||||
model->local_buffer[CodeInputFirst],
|
||||
model->input_length[CodeInputFirst],
|
||||
6,
|
||||
30 + y_offset,
|
||||
true);
|
||||
break;
|
||||
case CodeInputStateUpdate:
|
||||
code_input_draw_sequence(
|
||||
canvas,
|
||||
model->local_buffer[CodeInputFirst],
|
||||
model->input_length[CodeInputFirst],
|
||||
6,
|
||||
14 + y_offset,
|
||||
!model->current);
|
||||
code_input_draw_sequence(
|
||||
canvas,
|
||||
model->local_buffer[CodeInputSecond],
|
||||
model->input_length[CodeInputSecond],
|
||||
6,
|
||||
44 + y_offset,
|
||||
model->current);
|
||||
|
||||
if(model->current) canvas_draw_str(canvas, 2, 39 + y_offset, "Repeat code");
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Input callback
|
||||
*
|
||||
* @param event
|
||||
* @param context
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
static bool code_input_view_input_callback(InputEvent* event, void* context) {
|
||||
CodeInput* code_input = context;
|
||||
furi_assert(code_input);
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
|
||||
switch(event->key) {
|
||||
case InputKeyBack:
|
||||
with_view_model(
|
||||
code_input->view, (CodeInputModel * model) {
|
||||
consumed = code_input_handle_back(model);
|
||||
return true;
|
||||
});
|
||||
break;
|
||||
|
||||
case InputKeyOk:
|
||||
with_view_model(
|
||||
code_input->view, (CodeInputModel * model) {
|
||||
code_input_handle_ok(model);
|
||||
return true;
|
||||
});
|
||||
consumed = true;
|
||||
break;
|
||||
default:
|
||||
|
||||
with_view_model(
|
||||
code_input->view, (CodeInputModel * model) {
|
||||
code_input_handle_dpad(model, event->key);
|
||||
return true;
|
||||
});
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all input-related data in model
|
||||
*
|
||||
* @param model CodeInputModel
|
||||
*/
|
||||
static void code_input_reset_model_input_data(CodeInputModel* model) {
|
||||
model->current = 0;
|
||||
model->input_length[CodeInputFirst] = 0;
|
||||
model->input_length[CodeInputSecond] = 0;
|
||||
model->ext_buffer = NULL;
|
||||
model->ext_update = false;
|
||||
model->state = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate and initialize code input. This code input is used to enter codes.
|
||||
*
|
||||
* @return CodeInput instance pointer
|
||||
*/
|
||||
CodeInput* code_input_alloc() {
|
||||
CodeInput* code_input = furi_alloc(sizeof(CodeInput));
|
||||
code_input->view = view_alloc();
|
||||
view_set_context(code_input->view, code_input);
|
||||
view_allocate_model(code_input->view, ViewModelTypeLocking, sizeof(CodeInputModel));
|
||||
view_set_draw_callback(code_input->view, code_input_view_draw_callback);
|
||||
view_set_input_callback(code_input->view, code_input_view_input_callback);
|
||||
|
||||
with_view_model(
|
||||
code_input->view, (CodeInputModel * model) {
|
||||
model->header = "";
|
||||
model->ok_callback = NULL;
|
||||
model->fail_callback = NULL;
|
||||
model->callback_context = NULL;
|
||||
code_input_reset_model_input_data(model);
|
||||
return true;
|
||||
});
|
||||
|
||||
return code_input;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize and free code input
|
||||
*
|
||||
* @param code_input Code input instance
|
||||
*/
|
||||
void code_input_free(CodeInput* code_input) {
|
||||
furi_assert(code_input);
|
||||
view_free(code_input->view);
|
||||
free(code_input);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get code input view
|
||||
*
|
||||
* @param code_input code input instance
|
||||
* @return View instance that can be used for embedding
|
||||
*/
|
||||
View* code_input_get_view(CodeInput* code_input) {
|
||||
furi_assert(code_input);
|
||||
return code_input->view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set code input callbacks
|
||||
*
|
||||
* @param code_input code input instance
|
||||
* @param ok_callback input callback fn
|
||||
* @param fail_callback code match callback fn
|
||||
* @param callback_context callback context
|
||||
* @param buffer buffer
|
||||
* @param buffer_length ptr to buffer length uint
|
||||
* @param ext_update true to update buffer
|
||||
*/
|
||||
void code_input_set_result_callback(
|
||||
CodeInput* code_input,
|
||||
CodeInputOkCallback ok_callback,
|
||||
CodeInputFailCallback fail_callback,
|
||||
void* callback_context,
|
||||
uint8_t* buffer,
|
||||
uint8_t* buffer_length,
|
||||
bool ext_update) {
|
||||
with_view_model(
|
||||
code_input->view, (CodeInputModel * model) {
|
||||
code_input_reset_model_input_data(model);
|
||||
model->ok_callback = ok_callback;
|
||||
model->fail_callback = fail_callback;
|
||||
model->callback_context = callback_context;
|
||||
|
||||
model->ext_buffer = buffer;
|
||||
model->ext_buffer_length = buffer_length;
|
||||
model->state = (*buffer_length == 0) ? 1 : 0;
|
||||
model->ext_update = ext_update;
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set code input header text
|
||||
*
|
||||
* @param code_input code input instance
|
||||
* @param text text to be shown
|
||||
*/
|
||||
void code_input_set_header_text(CodeInput* code_input, const char* text) {
|
||||
with_view_model(
|
||||
code_input->view, (CodeInputModel * model) {
|
||||
model->header = text;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/**
|
||||
* @file code_input.h
|
||||
* GUI: CodeInput keyboard view module API
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Code input anonymous structure */
|
||||
typedef struct CodeInput CodeInput;
|
||||
|
||||
/** callback that is executed when entered code matches ext buffer */
|
||||
typedef void (*CodeInputOkCallback)(void* context);
|
||||
|
||||
/** callback that is executed when entered code does not matches ext buffer */
|
||||
typedef void (*CodeInputFailCallback)(void* context);
|
||||
|
||||
/** Allocate and initialize code input. This code input is used to enter codes.
|
||||
*
|
||||
* @return CodeInput instance pointer
|
||||
*/
|
||||
CodeInput* code_input_alloc();
|
||||
|
||||
/** Deinitialize and free code input
|
||||
*
|
||||
* @param code_input Code input instance
|
||||
*/
|
||||
void code_input_free(CodeInput* code_input);
|
||||
|
||||
/** Get code input view
|
||||
*
|
||||
* @param code_input code input instance
|
||||
*
|
||||
* @return View instance that can be used for embedding
|
||||
*/
|
||||
View* code_input_get_view(CodeInput* code_input);
|
||||
|
||||
/** Set code input result callback
|
||||
*
|
||||
* @param code_input code input instance
|
||||
* @param ok_callback ok callback fn
|
||||
* @param fail_callback fail callback fn
|
||||
* @param callback_context callback context
|
||||
* @param buffer buffer to use
|
||||
* @param buffer_length buffer length
|
||||
* @param update set true to update buffer
|
||||
*/
|
||||
void code_input_set_result_callback(
|
||||
CodeInput* code_input,
|
||||
CodeInputOkCallback ok_callback,
|
||||
CodeInputFailCallback fail_callback,
|
||||
void* callback_context,
|
||||
uint8_t* buffer,
|
||||
uint8_t* buffer_length,
|
||||
bool update);
|
||||
|
||||
/** Set code input header text
|
||||
*
|
||||
* @param code_input code input instance
|
||||
* @param text text to be shown
|
||||
*/
|
||||
void code_input_set_header_text(CodeInput* code_input, const char* text);
|
||||
|
||||
/** Compare two buffers
|
||||
*
|
||||
* @param in buffer to compare to source
|
||||
* @param len_in length of input buffer
|
||||
* @param src source buffer
|
||||
* @param len_src length of insourceput buffer
|
||||
* @return true if buffers match
|
||||
*/
|
||||
|
||||
bool code_input_compare(uint8_t* in, size_t len_in, uint8_t* src, size_t len_src);
|
||||
|
||||
/** Push input into the end of array
|
||||
*
|
||||
* @param buffer buffer
|
||||
* @param length length of buffer
|
||||
* @param key input key
|
||||
* @return new length of input buffer
|
||||
*/
|
||||
size_t code_input_push(uint8_t* buffer, size_t length, InputKey key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "applications.h"
|
||||
#include <furi.h>
|
||||
#include "loader/loader.h"
|
||||
#include "loader_i.h"
|
||||
@@ -79,6 +80,12 @@ const FlipperApplication* loader_find_application_by_name(const char* name) {
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) {
|
||||
if(strcmp(name, FLIPPER_SETTINGS_APPS[i].name) == 0) {
|
||||
application = &FLIPPER_SETTINGS_APPS[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
for(size_t i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) {
|
||||
if(strcmp(name, FLIPPER_DEBUG_APPS[i].name) == 0) {
|
||||
|
||||
Reference in New Issue
Block a user