[FL-1968] Pin code locking (#788)
* Gui: code input module * Gui: fix size to fit frame * Desktop: PIN config and lock option * Gui: code input: cleanup, offset input fields if no header present * Desktop: move code unlock to desktop_locked scene * Desktop: fix unlock with back key * Desktop: bump settings version * Desktop: correct scene usage. Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -41,6 +41,7 @@ Desktop* desktop_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();
|
||||
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher, DesktopViewMain, desktop_main_get_view(desktop->main_view));
|
||||
@@ -62,7 +63,8 @@ Desktop* desktop_alloc() {
|
||||
desktop->view_dispatcher,
|
||||
DesktopViewHwMismatch,
|
||||
popup_get_view(desktop->hw_mismatch_popup));
|
||||
|
||||
view_dispatcher_add_view(
|
||||
desktop->view_dispatcher, DesktopViewPinSetup, code_input_get_view(desktop->code_input));
|
||||
// Lock icon
|
||||
desktop->lock_viewport = view_port_alloc();
|
||||
view_port_set_width(desktop->lock_viewport, icon_get_width(&I_Lock_8x8));
|
||||
@@ -82,6 +84,7 @@ void desktop_free(Desktop* desktop) {
|
||||
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_free(desktop->view_dispatcher);
|
||||
scene_manager_free(desktop->scene_manager);
|
||||
@@ -92,6 +95,7 @@ void desktop_free(Desktop* desktop) {
|
||||
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);
|
||||
|
||||
furi_record_close("gui");
|
||||
desktop->gui = NULL;
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/modules/code_input.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <assets_icons.h>
|
||||
#include <storage/storage.h>
|
||||
@@ -29,6 +30,7 @@ typedef enum {
|
||||
DesktopViewDebug,
|
||||
DesktopViewFirstStart,
|
||||
DesktopViewHwMismatch,
|
||||
DesktopViewPinSetup,
|
||||
DesktopViewTotal,
|
||||
} DesktopViewEnum;
|
||||
|
||||
@@ -46,7 +48,10 @@ struct Desktop {
|
||||
DesktopLockMenuView* lock_menu;
|
||||
DesktopLockedView* locked_view;
|
||||
DesktopDebugView* debug_view;
|
||||
CodeInput* code_input;
|
||||
|
||||
DesktopSettings settings;
|
||||
PinCode pincode_buffer;
|
||||
|
||||
ViewPort* lock_viewport;
|
||||
};
|
||||
|
@@ -3,11 +3,20 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define DESKTOP_SETTINGS_VER (0)
|
||||
#define DESKTOP_SETTINGS_VER (1)
|
||||
#define PIN_MAX_LENGTH 12
|
||||
|
||||
typedef struct {
|
||||
uint8_t length;
|
||||
uint8_t data[PIN_MAX_LENGTH];
|
||||
} PinCode;
|
||||
|
||||
typedef struct {
|
||||
uint8_t version;
|
||||
uint16_t favorite;
|
||||
|
||||
PinCode pincode;
|
||||
bool locked;
|
||||
} DesktopSettings;
|
||||
|
||||
bool desktop_settings_load(DesktopSettings* desktop_settings);
|
||||
|
@@ -33,10 +33,13 @@ DesktopSettingsApp* desktop_settings_app_alloc() {
|
||||
|
||||
app->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, DesktopSettingsAppViewMain, submenu_get_view(app->submenu));
|
||||
app->view_dispatcher, DesktopSettingsAppViewMenu, submenu_get_view(app->submenu));
|
||||
|
||||
app->code_input = code_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, DesktopSettingsAppViewFavorite, submenu_get_view(app->submenu));
|
||||
app->view_dispatcher,
|
||||
DesktopSettingsAppViewPincodeInput,
|
||||
code_input_get_view(app->code_input));
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart);
|
||||
return app;
|
||||
@@ -45,9 +48,10 @@ DesktopSettingsApp* desktop_settings_app_alloc() {
|
||||
void desktop_settings_app_free(DesktopSettingsApp* app) {
|
||||
furi_assert(app);
|
||||
// Variable item list
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewMain);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewFavorite);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
|
||||
submenu_free(app->submenu);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewPincodeInput);
|
||||
code_input_free(app->code_input);
|
||||
// View dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
scene_manager_free(app->scene_manager);
|
||||
|
@@ -6,20 +6,32 @@
|
||||
#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"
|
||||
|
||||
#include "scenes/desktop_settings_scene.h"
|
||||
|
||||
typedef enum {
|
||||
DesktopSettingsAppViewMain,
|
||||
DesktopSettingsAppViewFavorite,
|
||||
CodeEventsSetPin,
|
||||
CodeEventsChangePin,
|
||||
CodeEventsDisablePin,
|
||||
} CodeEventsEnum;
|
||||
|
||||
typedef enum {
|
||||
DesktopSettingsAppViewMenu,
|
||||
DesktopSettingsAppViewPincodeInput,
|
||||
} DesktopSettingsAppView;
|
||||
|
||||
typedef struct {
|
||||
DesktopSettings settings;
|
||||
|
||||
Gui* gui;
|
||||
SceneManager* scene_manager;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Submenu* submenu;
|
||||
CodeInput* code_input;
|
||||
|
||||
uint8_t menu_idx;
|
||||
|
||||
} DesktopSettingsApp;
|
||||
|
@@ -1,2 +1,4 @@
|
||||
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)
|
||||
|
@@ -22,7 +22,7 @@ void desktop_settings_scene_favorite_on_enter(void* context) {
|
||||
|
||||
submenu_set_header(app->submenu, "Quick access app:");
|
||||
submenu_set_selected_item(app->submenu, app->settings.favorite);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewFavorite);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent event) {
|
||||
|
@@ -0,0 +1,62 @@
|
||||
#include "../desktop_settings_app.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;
|
||||
code_input_set_result_callback(app->code_input, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
code_input_set_header_text(app->code_input, "");
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
#include "../desktop_settings_app.h"
|
||||
#include "applications.h"
|
||||
|
||||
static void desktop_settings_scene_pincode_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) {
|
||||
DesktopSettingsApp* app = context;
|
||||
Submenu* submenu = app->submenu;
|
||||
submenu_clean(submenu);
|
||||
|
||||
if(!app->settings.pincode.length) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Set Pin",
|
||||
CodeEventsSetPin,
|
||||
desktop_settings_scene_pincode_menu_submenu_callback,
|
||||
app);
|
||||
|
||||
} else {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Change Pin",
|
||||
CodeEventsChangePin,
|
||||
desktop_settings_scene_pincode_menu_submenu_callback,
|
||||
app);
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Disable",
|
||||
CodeEventsDisablePin,
|
||||
desktop_settings_scene_pincode_menu_submenu_callback,
|
||||
app);
|
||||
}
|
||||
|
||||
submenu_set_header(app->submenu, "Pin code settings:");
|
||||
submenu_set_selected_item(app->submenu, app->menu_idx);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_pincode_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);
|
||||
consumed = true;
|
||||
break;
|
||||
case CodeEventsChangePin:
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, DesktopSettingsAppScenePinCodeInput, event.event);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeInput);
|
||||
consumed = true;
|
||||
break;
|
||||
case CodeEventsDisablePin:
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, DesktopSettingsAppScenePinCodeInput, event.event);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeInput);
|
||||
consumed = true;
|
||||
break;
|
||||
default:
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void desktop_settings_scene_pincode_menu_on_exit(void* context) {
|
||||
DesktopSettingsApp* app = context;
|
||||
submenu_clean(app->submenu);
|
||||
}
|
@@ -29,7 +29,7 @@ void desktop_settings_scene_start_on_enter(void* context) {
|
||||
desktop_settings_scene_start_submenu_callback,
|
||||
app);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMain);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
|
||||
}
|
||||
|
||||
bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
@@ -39,7 +39,11 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case DesktopSettingsStartSubmenuIndexFavorite:
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppViewFavorite);
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopSettingsStartSubmenuIndexPinSetup:
|
||||
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinCodeMenu);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
@@ -4,3 +4,4 @@ ADD_SCENE(desktop, locked, Locked)
|
||||
ADD_SCENE(desktop, debug, Debug)
|
||||
ADD_SCENE(desktop, first_start, FirstStart)
|
||||
ADD_SCENE(desktop, hw_mismatch, HwMismatch)
|
||||
ADD_SCENE(desktop, pinsetup, PinSetup)
|
||||
|
@@ -9,7 +9,10 @@ void desktop_scene_lock_menu_callback(DesktopLockMenuEvent event, void* context)
|
||||
void desktop_scene_lock_menu_on_enter(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
|
||||
desktop_settings_load(&desktop->settings);
|
||||
|
||||
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);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewLockMenu);
|
||||
}
|
||||
|
||||
@@ -20,10 +23,25 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case DesktopLockMenuEventLock:
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneLocked, DesktopLockedNoPin);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopLockMenuEventPinLock:
|
||||
|
||||
if(desktop->settings.pincode.length > 0) {
|
||||
desktop->settings.locked = true;
|
||||
desktop_settings_save(&desktop->settings);
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneLocked, DesktopLockedWithPin);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
||||
} else {
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopScenePinSetup);
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopLockMenuEventExit:
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
||||
consumed = true;
|
||||
|
@@ -15,12 +15,39 @@ void desktop_scene_locked_on_enter(void* context) {
|
||||
desktop_locked_update_hint_timeout(locked_view);
|
||||
desktop_locked_set_dolphin_animation(locked_view);
|
||||
|
||||
uint32_t state = scene_manager_get_scene_state(desktop->scene_manager, DesktopViewLocked);
|
||||
|
||||
desktop_locked_with_pin(desktop->locked_view, state == DesktopLockedWithPin);
|
||||
|
||||
view_port_enabled_set(desktop->lock_viewport, true);
|
||||
osTimerStart(locked_view->timer, 63);
|
||||
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewLocked);
|
||||
}
|
||||
|
||||
static bool desktop_scene_locked_check_pin(Desktop* desktop, DesktopMainEvent event) {
|
||||
bool match = false;
|
||||
|
||||
size_t length = desktop->pincode_buffer.length;
|
||||
length = code_input_push(desktop->pincode_buffer.data, length, event);
|
||||
desktop->pincode_buffer.length = length;
|
||||
|
||||
match = code_input_compare(
|
||||
desktop->pincode_buffer.data,
|
||||
length,
|
||||
desktop->settings.pincode.data,
|
||||
desktop->settings.pincode.length);
|
||||
|
||||
if(match) {
|
||||
desktop->pincode_buffer.length = 0;
|
||||
desktop->settings.locked = false;
|
||||
desktop_settings_save(&desktop->settings);
|
||||
desktop_main_unlocked(desktop->main_view);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
|
||||
@@ -36,7 +63,17 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
|
||||
case DesktopLockedEventUpdate:
|
||||
desktop_locked_manage_redraw(desktop->locked_view);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopLockedEventInputReset:
|
||||
desktop->pincode_buffer.length = 0;
|
||||
break;
|
||||
default:
|
||||
if(desktop_scene_locked_check_pin(desktop, event.event)) {
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneMain, DesktopMainEventUnlocked);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
||||
consumed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -34,6 +34,8 @@ void desktop_scene_main_on_enter(void* context) {
|
||||
desktop_main_set_callback(main_view, desktop_scene_main_callback, desktop);
|
||||
view_port_enabled_set(desktop->lock_viewport, false);
|
||||
|
||||
desktop_settings_load(&desktop->settings);
|
||||
|
||||
if(scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneMain) ==
|
||||
DesktopMainEventUnlocked) {
|
||||
desktop_main_unlocked(desktop->main_view);
|
||||
|
50
applications/desktop/scenes/desktop_scene_pinsetup.c
Normal file
50
applications/desktop/scenes/desktop_scene_pinsetup.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "../desktop_i.h"
|
||||
|
||||
#define SCENE_EXIT_EVENT (0U)
|
||||
|
||||
void desktop_scene_ok_callback(void* context) {
|
||||
Desktop* app = context;
|
||||
desktop_settings_save(&app->settings);
|
||||
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;
|
||||
code_input_set_result_callback(app->code_input, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
code_input_set_header_text(app->code_input, "");
|
||||
}
|
@@ -12,6 +12,14 @@ void desktop_lock_menu_set_callback(
|
||||
lock_menu->context = context;
|
||||
}
|
||||
|
||||
void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set) {
|
||||
with_view_model(
|
||||
lock_menu->view, (DesktopLockMenuViewModel * model) {
|
||||
model->pin_set = pin_is_set;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void desktop_lock_menu_reset_idx(DesktopLockMenuView* lock_menu) {
|
||||
with_view_model(
|
||||
lock_menu->view, (DesktopLockMenuViewModel * model) {
|
||||
@@ -26,6 +34,10 @@ static void lock_menu_callback(void* context, uint8_t index) {
|
||||
switch(index) {
|
||||
case 0: // lock
|
||||
lock_menu->callback(DesktopLockMenuEventLock, lock_menu->context);
|
||||
break;
|
||||
case 1: // lock
|
||||
lock_menu->callback(DesktopLockMenuEventPinLock, lock_menu->context);
|
||||
break;
|
||||
default: // wip message
|
||||
with_view_model(
|
||||
lock_menu->view, (DesktopLockMenuViewModel * model) {
|
||||
@@ -37,7 +49,7 @@ static void lock_menu_callback(void* context, uint8_t index) {
|
||||
}
|
||||
|
||||
void desktop_lock_menu_render(Canvas* canvas, void* model) {
|
||||
const char* Lockmenu_Items[3] = {"Lock", "Set PIN", "DUMB mode"};
|
||||
const char* Lockmenu_Items[3] = {"Lock", "Lock with PIN", "DUMB mode"};
|
||||
|
||||
DesktopLockMenuViewModel* m = model;
|
||||
canvas_clear(canvas);
|
||||
@@ -47,13 +59,13 @@ void desktop_lock_menu_render(Canvas* canvas, void* model) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
for(uint8_t i = 0; i < 3; ++i) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
13 + (i * 17),
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
(m->hint_timeout && m->idx == i && m->idx) ? "Not implemented" : Lockmenu_Items[i]);
|
||||
const char* str = Lockmenu_Items[i];
|
||||
|
||||
if(i == 1 && !m->pin_set) str = "Set PIN";
|
||||
if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not implemented";
|
||||
|
||||
canvas_draw_str_aligned(canvas, 64, 13 + (i * 17), AlignCenter, AlignCenter, str);
|
||||
|
||||
if(m->idx == i) elements_frame(canvas, 15, 5 + (i * 17), 98, 15);
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@
|
||||
typedef enum {
|
||||
DesktopLockMenuEventLock,
|
||||
DesktopLockMenuEventUnlock,
|
||||
DesktopLockMenuEventPinLock,
|
||||
DesktopLockMenuEventExit,
|
||||
} DesktopLockMenuEvent;
|
||||
|
||||
@@ -27,6 +28,7 @@ struct DesktopLockMenuView {
|
||||
typedef struct {
|
||||
uint8_t idx;
|
||||
uint8_t hint_timeout;
|
||||
bool pin_set;
|
||||
} DesktopLockMenuViewModel;
|
||||
|
||||
void desktop_lock_menu_set_callback(
|
||||
@@ -35,6 +37,7 @@ void desktop_lock_menu_set_callback(
|
||||
void* context);
|
||||
|
||||
View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu);
|
||||
void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set);
|
||||
void desktop_lock_menu_reset_idx(DesktopLockMenuView* lock_menu);
|
||||
DesktopLockMenuView* desktop_lock_menu_alloc();
|
||||
void desktop_lock_menu_free(DesktopLockMenuView* lock_menu);
|
||||
|
@@ -80,6 +80,14 @@ void desktop_locked_reset_counter(DesktopLockedView* locked_view) {
|
||||
});
|
||||
}
|
||||
|
||||
void desktop_locked_with_pin(DesktopLockedView* locked_view, bool locked) {
|
||||
with_view_model(
|
||||
locked_view->view, (DesktopLockedViewModel * model) {
|
||||
model->pin_lock = locked;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void desktop_locked_render(Canvas* canvas, void* model) {
|
||||
DesktopLockedViewModel* m = model;
|
||||
uint32_t now = osKernelGetTickCount();
|
||||
@@ -100,7 +108,7 @@ void desktop_locked_render(Canvas* canvas, void* model) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_framed(canvas, 42, 30, "Locked");
|
||||
|
||||
} else {
|
||||
} else if(!m->pin_lock) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_icon(canvas, 13, 5, &I_LockPopup_100x49);
|
||||
elements_multiline_text(canvas, 65, 20, "To unlock\npress:");
|
||||
@@ -116,27 +124,49 @@ View* desktop_locked_get_view(DesktopLockedView* locked_view) {
|
||||
bool desktop_locked_input(InputEvent* event, void* context) {
|
||||
furi_assert(event);
|
||||
furi_assert(context);
|
||||
|
||||
DesktopLockedView* locked_view = context;
|
||||
|
||||
uint32_t press_time = 0;
|
||||
bool locked_with_pin = false;
|
||||
|
||||
with_view_model(
|
||||
locked_view->view, (DesktopLockedViewModel * model) {
|
||||
locked_with_pin = model->pin_lock;
|
||||
return false;
|
||||
});
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
desktop_locked_update_hint_timeout(locked_view);
|
||||
if(locked_with_pin) {
|
||||
press_time = osKernelGetTickCount();
|
||||
|
||||
if(event->key == InputKeyBack) {
|
||||
uint32_t press_time = osKernelGetTickCount();
|
||||
// check if pressed sequentially
|
||||
if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) {
|
||||
if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT * 3) {
|
||||
locked_view->lock_lastpress = press_time;
|
||||
locked_view->lock_count = 0;
|
||||
} else if(press_time - locked_view->lock_lastpress < UNLOCK_RST_TIMEOUT) {
|
||||
locked_view->lock_lastpress = press_time;
|
||||
locked_view->lock_count++;
|
||||
locked_view->callback(DesktopLockedEventInputReset, locked_view->context);
|
||||
}
|
||||
|
||||
if(locked_view->lock_count == UNLOCK_CNT) {
|
||||
locked_view->lock_count = 0;
|
||||
locked_view->callback(DesktopLockedEventUnlock, locked_view->context);
|
||||
locked_view->callback(event->key, locked_view->context);
|
||||
} else {
|
||||
desktop_locked_update_hint_timeout(locked_view);
|
||||
|
||||
if(event->key == InputKeyBack) {
|
||||
press_time = osKernelGetTickCount();
|
||||
// check if pressed sequentially
|
||||
if(press_time - locked_view->lock_lastpress < UNLOCK_RST_TIMEOUT) {
|
||||
locked_view->lock_lastpress = press_time;
|
||||
locked_view->lock_count++;
|
||||
}
|
||||
|
||||
if(locked_view->lock_count == UNLOCK_CNT) {
|
||||
locked_view->lock_count = 0;
|
||||
locked_view->callback(DesktopLockedEventUnlock, locked_view->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(press_time - locked_view->lock_lastpress > UNLOCK_RST_TIMEOUT) {
|
||||
locked_view->lock_lastpress = press_time;
|
||||
locked_view->lock_count = 0;
|
||||
}
|
||||
}
|
||||
// All events consumed
|
||||
return true;
|
||||
|
@@ -15,10 +15,16 @@
|
||||
#define DOOR_R_POS_MIN 60
|
||||
|
||||
typedef enum {
|
||||
DesktopLockedEventUnlock,
|
||||
DesktopLockedEventUpdate,
|
||||
DesktopLockedEventUnlock = 10U,
|
||||
DesktopLockedEventUpdate = 11U,
|
||||
DesktopLockedEventInputReset = 12U,
|
||||
} DesktopLockedEvent;
|
||||
|
||||
typedef enum {
|
||||
DesktopLockedWithPin,
|
||||
DesktopLockedNoPin,
|
||||
} DesktopLockedSceneState;
|
||||
|
||||
typedef struct DesktopLockedView DesktopLockedView;
|
||||
|
||||
typedef void (*DesktopLockedViewCallback)(DesktopLockedEvent event, void* context);
|
||||
@@ -42,6 +48,7 @@ typedef struct {
|
||||
int8_t door_right_x;
|
||||
bool animation_seq_end;
|
||||
|
||||
bool pin_lock;
|
||||
} DesktopLockedViewModel;
|
||||
|
||||
void desktop_locked_set_callback(
|
||||
@@ -58,5 +65,4 @@ void desktop_locked_manage_redraw(DesktopLockedView* locked_view);
|
||||
View* desktop_locked_get_view(DesktopLockedView* locked_view);
|
||||
DesktopLockedView* desktop_locked_alloc();
|
||||
void desktop_locked_free(DesktopLockedView* locked_view);
|
||||
void desktop_main_unlocked(DesktopMainView* main_view);
|
||||
void desktop_main_reset_hint(DesktopMainView* main_view);
|
||||
void desktop_locked_with_pin(DesktopLockedView* lock_menu, bool locked);
|
@@ -67,6 +67,7 @@ bool desktop_main_input(InputEvent* event, void* context) {
|
||||
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
||||
main_view->callback(DesktopMainEventOpenFavorite, main_view->context);
|
||||
}
|
||||
|
||||
desktop_main_reset_hint(main_view);
|
||||
|
||||
return true;
|
||||
|
@@ -7,12 +7,12 @@
|
||||
#include <furi.h>
|
||||
|
||||
typedef enum {
|
||||
DesktopMainEventOpenMenu,
|
||||
DesktopMainEventOpenLockMenu,
|
||||
DesktopMainEventOpenDebug,
|
||||
DesktopMainEventUnlocked,
|
||||
DesktopMainEventOpenArchive,
|
||||
DesktopMainEventOpenFavorite,
|
||||
DesktopMainEventOpenMenu,
|
||||
DesktopMainEventOpenDebug,
|
||||
DesktopMainEventUnlocked,
|
||||
} DesktopMainEvent;
|
||||
|
||||
typedef struct DesktopMainView DesktopMainView;
|
||||
@@ -37,9 +37,8 @@ void desktop_main_set_callback(
|
||||
void* context);
|
||||
|
||||
View* desktop_main_get_view(DesktopMainView* main_view);
|
||||
|
||||
DesktopMainView* desktop_main_alloc();
|
||||
|
||||
void desktop_main_free(DesktopMainView* main_view);
|
||||
|
||||
void desktop_main_switch_dolphin_animation(DesktopMainView* main_view);
|
||||
void desktop_main_unlocked(DesktopMainView* main_view);
|
||||
void desktop_main_reset_hint(DesktopMainView* main_view);
|
||||
|
Reference in New Issue
Block a user