Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FL-3934] Alarm improvements: Snooze, timeouts, and dismissing from the locked state #4017

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions applications/services/gui/gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ static void gui_redraw(Gui* gui) {

canvas_reset(gui->canvas);

if(gui->lockdown) {
if(gui_is_lockdown(gui)) {
gui_redraw_desktop(gui);
bool need_attention =
(gui_view_port_find_enabled(gui->layers[GuiLayerWindow]) != 0 ||
Expand Down Expand Up @@ -299,7 +299,7 @@ static void gui_input(Gui* gui, InputEvent* input_event) {

ViewPort* view_port = NULL;

if(gui->lockdown) {
if(gui_is_lockdown(gui)) {
view_port = gui_view_port_find_enabled(gui->layers[GuiLayerDesktop]);
} else {
view_port = gui_view_port_find_enabled(gui->layers[GuiLayerFullscreen]);
Expand Down Expand Up @@ -495,6 +495,23 @@ void gui_set_lockdown(Gui* gui, bool lockdown) {
gui_update(gui);
}

void gui_set_lockdown_inhibit(Gui* gui, bool inhibit) {
furi_check(gui);

gui_lock(gui);
gui->lockdown_inhibit = inhibit;
gui_unlock(gui);

// Request redraw
gui_update(gui);
}

bool gui_is_lockdown(const Gui* gui) {
furi_check(gui);

return gui->lockdown && !gui->lockdown_inhibit;
}

Canvas* gui_direct_draw_acquire(Gui* gui) {
furi_check(gui);

Expand Down
17 changes: 17 additions & 0 deletions applications/services/gui/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,23 @@ size_t gui_get_framebuffer_size(const Gui* gui);
*/
void gui_set_lockdown(Gui* gui, bool lockdown);

/** Inhibit lockdown mode
*
* Lockdown mode can be inhibited by calling this function with inhibit set to true.
* This is used to show information even when flipper is locked.
*
* @param gui Gui instance
* @param inhibit true to inhibit lockdown mode
*/
void gui_set_lockdown_inhibit(Gui* gui, bool inhibit);

/** Check if Gui is in lockdown mode
*
* @param gui Gui instance
* @return bool true if Gui is in lockdown mode
*/
bool gui_is_lockdown(const Gui* gui);

/** Acquire Direct Draw lock and get Canvas instance
*
* This method return Canvas instance for use in monopoly mode. Direct draw lock
Expand Down
1 change: 1 addition & 0 deletions applications/services/gui/gui_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct Gui {

// Layers and Canvas
bool lockdown;
bool lockdown_inhibit;
bool direct_draw;
ViewPortArray_t layers[GuiLayerMAX];
Canvas* canvas;
Expand Down
52 changes: 51 additions & 1 deletion applications/settings/clock_settings/clock_settings_alarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@

#define TAG "ClockSettingsAlarm"

#define SNOOZE_MINUTES 9
#define TIMEOUT_MINUTES 10

typedef struct {
DateTime now;
DateTime snooze_until;
DateTime alarm_start;
IconAnimation* icon;

bool is_snooze;
} ClockSettingsAlramModel;

const NotificationSequence sequence_alarm = {
Expand Down Expand Up @@ -47,12 +54,15 @@ static void clock_settings_alarm_draw_callback(Canvas* canvas, void* ctx) {
ClockSettingsAlramModel* model = ctx;
char buffer[64] = {};

// Clock icon
canvas_draw_icon_animation(canvas, 5, 6, model->icon);

// Time
canvas_set_font(canvas, FontBigNumbers);
snprintf(buffer, sizeof(buffer), "%02u:%02u", model->now.hour, model->now.minute);
canvas_draw_str(canvas, 58, 32, buffer);

// Date
canvas_set_font(canvas, FontPrimary);
snprintf(
buffer,
Expand All @@ -62,6 +72,11 @@ static void clock_settings_alarm_draw_callback(Canvas* canvas, void* ctx) {
model->now.month,
model->now.year);
canvas_draw_str(canvas, 60, 44, buffer);

// Press Back to snooze
canvas_set_font(canvas, FontPrimary);
canvas_draw_icon_ex(canvas, 5, 50, &I_back_btn_10x8, 0);
canvas_draw_str_aligned(canvas, 20, 50, AlignLeft, AlignTop, "Snooze");
}

static void clock_settings_alarm_input_callback(InputEvent* input_event, void* ctx) {
Expand All @@ -81,8 +96,10 @@ int32_t clock_settings_alarm(void* p) {

// View Model
ClockSettingsAlramModel model;
model.is_snooze = false;

furi_hal_rtc_get_datetime(&model.now);
furi_hal_rtc_get_alarm(&model.alarm_start);
model.icon = icon_animation_alloc(&A_Alarm_47x39);

// Alloc message queue
Expand All @@ -95,6 +112,7 @@ int32_t clock_settings_alarm(void* p) {

// Register view port in GUI
Gui* gui = furi_record_open(RECORD_GUI);
gui_set_lockdown_inhibit(gui, true);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);

NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
Expand All @@ -110,12 +128,43 @@ int32_t clock_settings_alarm(void* p) {
while(running) {
if(furi_message_queue_get(event_queue, &event, 2000) == FuriStatusOk) {
if(event.type == InputTypePress) {
running = false;
// Snooze
if(event.key == InputKeyBack) {
furi_hal_rtc_get_datetime(&model.snooze_until);
model.snooze_until.minute += SNOOZE_MINUTES;
model.snooze_until.hour += model.snooze_until.minute / 60;
model.snooze_until.minute %= 60;
model.snooze_until.hour %= 24;

model.is_snooze = true;
model.alarm_start = model.snooze_until; // For correct timeout behavior
view_port_enabled_set(view_port, false);
gui_set_lockdown_inhibit(gui, false);
} else {
running = false;
}
}
} else if(model.is_snooze) {
furi_hal_rtc_get_datetime(&model.now);
if(datetime_datetime_to_timestamp(&model.now) >=
datetime_datetime_to_timestamp(&model.snooze_until)) {
view_port_enabled_set(view_port, true);
gui_set_lockdown_inhibit(gui, true);

model.is_snooze = false;
}
} else {
notification_message(notification, &sequence_alarm);
furi_hal_rtc_get_datetime(&model.now);
view_port_update(view_port);

// Stop the alarm if it has been ringing for more than TIMEOUT_MINUTES
if((model.now.hour == model.alarm_start.hour &&
model.now.minute >= model.alarm_start.minute + TIMEOUT_MINUTES) ||
(model.now.hour == (model.alarm_start.hour + 1) % 24 &&
model.now.minute < (model.alarm_start.minute + TIMEOUT_MINUTES) % 60)) {
running = false;
}
}
}

Expand All @@ -125,6 +174,7 @@ int32_t clock_settings_alarm(void* p) {
furi_record_close(RECORD_NOTIFICATION);

view_port_enabled_set(view_port, false);
gui_set_lockdown_inhibit(gui, false);
gui_remove_view_port(gui, view_port);
view_port_free(view_port);
furi_message_queue_free(event_queue);
Expand Down
6 changes: 4 additions & 2 deletions targets/f18/api_symbols.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,79.2,,
Version,+,80.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
Header,+,applications/services/cli/cli.h,,
Expand Down Expand Up @@ -1736,9 +1736,11 @@ Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer"
Function,+,gui_direct_draw_acquire,Canvas*,Gui*
Function,+,gui_direct_draw_release,void,Gui*
Function,+,gui_get_framebuffer_size,size_t,const Gui*
Function,+,gui_is_lockdown,_Bool,const Gui*
Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*"
Function,+,gui_remove_view_port,void,"Gui*, ViewPort*"
Function,+,gui_set_lockdown,void,"Gui*, _Bool"
Function,+,gui_set_lockdown_inhibit,void,"Gui*, _Bool"
Function,-,gui_view_port_send_to_back,void,"Gui*, ViewPort*"
Function,+,gui_view_port_send_to_front,void,"Gui*, ViewPort*"
Function,-,hci_send_req,int,"hci_request*, uint8_t"
Expand Down Expand Up @@ -2302,9 +2304,9 @@ Function,+,pipe_install_as_stdio,void,PipeSide*
Function,+,pipe_receive,size_t,"PipeSide*, void*, size_t, FuriWait"
Function,+,pipe_role,PipeRole,PipeSide*
Function,+,pipe_send,size_t,"PipeSide*, const void*, size_t, FuriWait"
Function,+,pipe_set_broken_callback,void,"PipeSide*, PipeSideBrokenCallback, FuriEventLoopEvent"
Function,+,pipe_set_callback_context,void,"PipeSide*, void*"
Function,+,pipe_set_data_arrived_callback,void,"PipeSide*, PipeSideDataArrivedCallback, FuriEventLoopEvent"
Function,+,pipe_set_broken_callback,void,"PipeSide*, PipeSideBrokenCallback, FuriEventLoopEvent"
Function,+,pipe_set_space_freed_callback,void,"PipeSide*, PipeSideSpaceFreedCallback, FuriEventLoopEvent"
Function,+,pipe_spaces_available,size_t,PipeSide*
Function,+,pipe_state,PipeState,PipeSide*
Expand Down
6 changes: 4 additions & 2 deletions targets/f7/api_symbols.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,79.2,,
Version,+,80.0,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
Expand Down Expand Up @@ -1955,9 +1955,11 @@ Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer"
Function,+,gui_direct_draw_acquire,Canvas*,Gui*
Function,+,gui_direct_draw_release,void,Gui*
Function,+,gui_get_framebuffer_size,size_t,const Gui*
Function,+,gui_is_lockdown,_Bool,const Gui*
Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*"
Function,+,gui_remove_view_port,void,"Gui*, ViewPort*"
Function,+,gui_set_lockdown,void,"Gui*, _Bool"
Function,+,gui_set_lockdown_inhibit,void,"Gui*, _Bool"
Function,-,gui_view_port_send_to_back,void,"Gui*, ViewPort*"
Function,+,gui_view_port_send_to_front,void,"Gui*, ViewPort*"
Function,-,hci_send_req,int,"hci_request*, uint8_t"
Expand Down Expand Up @@ -2938,9 +2940,9 @@ Function,+,pipe_install_as_stdio,void,PipeSide*
Function,+,pipe_receive,size_t,"PipeSide*, void*, size_t, FuriWait"
Function,+,pipe_role,PipeRole,PipeSide*
Function,+,pipe_send,size_t,"PipeSide*, const void*, size_t, FuriWait"
Function,+,pipe_set_broken_callback,void,"PipeSide*, PipeSideBrokenCallback, FuriEventLoopEvent"
Function,+,pipe_set_callback_context,void,"PipeSide*, void*"
Function,+,pipe_set_data_arrived_callback,void,"PipeSide*, PipeSideDataArrivedCallback, FuriEventLoopEvent"
Function,+,pipe_set_broken_callback,void,"PipeSide*, PipeSideBrokenCallback, FuriEventLoopEvent"
Function,+,pipe_set_space_freed_callback,void,"PipeSide*, PipeSideSpaceFreedCallback, FuriEventLoopEvent"
Function,+,pipe_spaces_available,size_t,PipeSide*
Function,+,pipe_state,PipeState,PipeSide*
Expand Down
Loading