diff --git a/applications/services/desktop/scenes/desktop_scene_lock_menu.c b/applications/services/desktop/scenes/desktop_scene_lock_menu.c index 5ca95c4c590..d30365bf3ec 100644 --- a/applications/services/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/services/desktop/scenes/desktop_scene_lock_menu.c @@ -26,6 +26,8 @@ void desktop_scene_lock_menu_on_enter(void* context) { desktop_lock_menu_set_stealth_mode_state( desktop->lock_menu, furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode)); desktop_lock_menu_set_idx(desktop->lock_menu, 0); + desktop_lock_menu_set_notification_record(desktop->lock_menu, desktop->notification); + desktop_lock_menu_refresh_notification_values(desktop->lock_menu); view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdLockMenu); } @@ -77,5 +79,9 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { } void desktop_scene_lock_menu_on_exit(void* context) { - UNUSED(context); + Desktop* desktop = (Desktop*)context; + + if(desktop_lock_menu_did_notification_settings_change(desktop->lock_menu)) { + notification_message_save_settings(desktop->notification); + } } diff --git a/applications/services/desktop/views/desktop_view_lock_menu.c b/applications/services/desktop/views/desktop_view_lock_menu.c index 1b6bdab9c58..adfb47a271d 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.c +++ b/applications/services/desktop/views/desktop_view_lock_menu.c @@ -4,14 +4,224 @@ #include "../desktop_i.h" #include "desktop_view_lock_menu.h" +#include -typedef enum { - DesktopLockMenuIndexLock, - DesktopLockMenuIndexStealth, - DesktopLockMenuIndexDummy, +#define DESKTOP_LOCK_MENU_VISIBLE_ITEM_COUNT 3 - DesktopLockMenuIndexTotalCount -} DesktopLockMenuIndex; +typedef struct DesktopLockMenuItem DesktopLockMenuItem; + +typedef FuriString* (*DesktopLockMenuItemGetTextCallback)( + const DesktopLockMenuItem* item, + DesktopLockMenuViewModel* model, + bool is_selected); + +typedef bool (*DesktopLockMenuItemOnInputCallback)( + const DesktopLockMenuItem* item, + const InputEvent* event, + DesktopLockMenuView* view); + +struct DesktopLockMenuItem { + DesktopLockMenuItemGetTextCallback get_text; + DesktopLockMenuItemOnInputCallback on_input; +}; + +FuriString* desktop_lock_menu_lock_get_text( + const DesktopLockMenuItem* item, + DesktopLockMenuViewModel* model, + bool is_selected) { + furi_assert(item); + furi_assert(model); + UNUSED(is_selected); + + return furi_string_alloc_set("Lock"); +} + +bool desktop_lock_menu_lock_on_input( + const DesktopLockMenuItem* item, + const InputEvent* event, + DesktopLockMenuView* view) { + furi_assert(item); + furi_assert(event); + furi_assert(view); + + if(event->key == InputKeyOk) { + view->callback(DesktopLockMenuEventLock, view->context); + return true; + } else + return false; +} + +FuriString* desktop_lock_menu_stealth_get_text( + const DesktopLockMenuItem* item, + DesktopLockMenuViewModel* model, + bool is_selected) { + furi_assert(item); + furi_assert(model); + UNUSED(is_selected); + + if(model->stealth_mode) + return furi_string_alloc_set("Unmute"); + else + return furi_string_alloc_set("Mute"); +} + +bool desktop_lock_menu_stealth_on_input( + const DesktopLockMenuItem* item, + const InputEvent* event, + DesktopLockMenuView* view) { + furi_assert(item); + furi_assert(event); + furi_assert(view); + + if(event->key == InputKeyOk) { + DesktopEvent event_type = DesktopLockMenuEventStealthModeOff; + with_view_model( + view->view, + DesktopLockMenuViewModel * model, + { + if(!model->stealth_mode) event_type = DesktopLockMenuEventStealthModeOn; + }, + false) + + view->callback(event_type, view->context); + + return true; + } else + return false; +} + +FuriString* desktop_lock_menu_dummy_mode_get_text( + const DesktopLockMenuItem* item, + DesktopLockMenuViewModel* model, + bool is_selected) { + furi_assert(item); + furi_assert(model); + UNUSED(is_selected); + + if(model->dummy_mode) + return furi_string_alloc_set("Default Mode"); + else + return furi_string_alloc_set("Dummy Mode"); +} + +bool desktop_lock_menu_dummy_mode_on_input( + const DesktopLockMenuItem* item, + const InputEvent* event, + DesktopLockMenuView* view) { + furi_assert(item); + furi_assert(event); + furi_assert(view); + + if(event->key == InputKeyOk) { + DesktopEvent event_type = DesktopLockMenuEventDummyModeOff; + with_view_model( + view->view, + DesktopLockMenuViewModel * model, + { + if(!model->dummy_mode) event_type = DesktopLockMenuEventDummyModeOn; + }, + false) + + view->callback(event_type, view->context); + + return true; + } else + return false; +} + +FuriString* desktop_lock_menu_display_brightness_get_text( + const DesktopLockMenuItem* item, + DesktopLockMenuViewModel* model, + bool is_selected) { + furi_assert(item); + furi_assert(model); + UNUSED(is_selected); + + const char* value_string = backlight_text[model->display_brightness_index]; + FuriString* str = furi_string_alloc_set("Display "); + + if(model->display_brightness_index > 0) + furi_string_cat(str, "< "); + else + furi_string_cat(str, " "); + + furi_string_cat(str, value_string); + + if(model->display_brightness_index < BACKLIGHT_COUNT - 1) + furi_string_cat(str, " >"); + else + furi_string_cat(str, " "); + + return str; +} + +bool desktop_lock_menu_display_brightness_on_input( + const DesktopLockMenuItem* item, + const InputEvent* event, + DesktopLockMenuView* view) { + furi_assert(item); + furi_assert(event); + furi_assert(view); + + if(event->key == InputKeyLeft || event->key == InputKeyRight) { + bool update = false; + uint8_t index = 0; + with_view_model( + view->view, + DesktopLockMenuViewModel * model, + { + if(event->key == InputKeyLeft && + (int8_t)model->display_brightness_index - 1 >= 0) { + model->display_brightness_index--; + index = model->display_brightness_index; + update = true; + } else if( + event->key == InputKeyRight && + model->display_brightness_index + 1 < BACKLIGHT_COUNT) { + model->display_brightness_index++; + index = model->display_brightness_index; + update = true; + } + + if(update) { + model->notification_settings_changed = true; + } + }, + update); + + if(update) { + view->notification_record->settings.display_brightness = backlight_value[index]; + notification_message(view->notification_record, &sequence_display_backlight_on); + } + + return true; + } + + return false; +} + +const DesktopLockMenuItem menu_items[] = { + { + .get_text = desktop_lock_menu_lock_get_text, + .on_input = desktop_lock_menu_lock_on_input, + }, + { + .get_text = desktop_lock_menu_stealth_get_text, + .on_input = desktop_lock_menu_stealth_on_input, + }, + { + .get_text = desktop_lock_menu_dummy_mode_get_text, + .on_input = desktop_lock_menu_dummy_mode_on_input, + }, + { + .get_text = desktop_lock_menu_display_brightness_get_text, + .on_input = desktop_lock_menu_display_brightness_on_input, + }, +}; +#define DESKTOP_LOCK_MENU_ITEM_COUNT COUNT_OF(menu_items) + +#define DESKTOP_LOCK_MENU_NEEDS_SCROLL_BAR \ + DESKTOP_LOCK_MENU_ITEM_COUNT > DESKTOP_LOCK_MENU_VISIBLE_ITEM_COUNT void desktop_lock_menu_set_callback( DesktopLockMenuView* lock_menu, @@ -40,11 +250,62 @@ void desktop_lock_menu_set_stealth_mode_state(DesktopLockMenuView* lock_menu, bo } void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) { - furi_assert(idx < DesktopLockMenuIndexTotalCount); + furi_assert(idx < DESKTOP_LOCK_MENU_ITEM_COUNT); with_view_model( lock_menu->view, DesktopLockMenuViewModel * model, { model->idx = idx; }, true); } +void desktop_lock_menu_set_notification_record( + DesktopLockMenuView* lock_menu, + NotificationApp* notification) { + furi_assert(lock_menu); + furi_assert(notification); + + lock_menu->notification_record = notification; + + desktop_lock_menu_refresh_notification_values(lock_menu); +} + +void desktop_lock_menu_refresh_notification_values(DesktopLockMenuView* lock_menu) { + furi_assert(lock_menu); + + uint8_t index = value_index_float( + lock_menu->notification_record->settings.display_brightness, + backlight_value, + BACKLIGHT_COUNT); + with_view_model( + lock_menu->view, + DesktopLockMenuViewModel * model, + { model->display_brightness_index = index; }, + true); +} + +bool desktop_lock_menu_did_notification_settings_change(DesktopLockMenuView* lock_menu) { + furi_assert(lock_menu); + + bool ret = false; + with_view_model(lock_menu->view, + DesktopLockMenuViewModel * model, + ret = model->notification_settings_changed; + , false); + return ret; +} + +uint8_t desktop_lock_menu_get_first_visible_item(uint8_t idx) { + if(DESKTOP_LOCK_MENU_NEEDS_SCROLL_BAR) { + if(idx < 1) //first item is selected + return 0; + else if( + idx > DESKTOP_LOCK_MENU_ITEM_COUNT - DESKTOP_LOCK_MENU_VISIBLE_ITEM_COUNT + + 1) //last item is selected + return DESKTOP_LOCK_MENU_ITEM_COUNT - DESKTOP_LOCK_MENU_VISIBLE_ITEM_COUNT; + else //item is not the first or last item + return idx - 1; + } else { + return 0; + } +} + void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { DesktopLockMenuViewModel* m = model; @@ -53,31 +314,39 @@ void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { canvas_draw_icon(canvas, 116, 0 + STATUS_BAR_Y_SHIFT, &I_DoorRight_70x55); canvas_set_font(canvas, FontSecondary); - for(size_t i = 0; i < DesktopLockMenuIndexTotalCount; ++i) { - const char* str = NULL; + const uint8_t first_visible_item = desktop_lock_menu_get_first_visible_item(m->idx); - if(i == DesktopLockMenuIndexLock) { - str = "Lock"; - } else if(i == DesktopLockMenuIndexStealth) { - if(m->stealth_mode) { - str = "Unmute"; - } else { - str = "Mute"; - } - } else if(i == DesktopLockMenuIndexDummy) { //-V547 - if(m->dummy_mode) { - str = "Default Mode"; - } else { - str = "Dummy Mode"; - } - } + for(size_t i = 0; i < DESKTOP_LOCK_MENU_VISIBLE_ITEM_COUNT; ++i) { + const uint32_t menu_item_index = first_visible_item + i; + const bool is_selected = m->idx == menu_item_index; + const DesktopLockMenuItem* menu_item = &menu_items[menu_item_index]; + + FuriString* text = menu_item->get_text(menu_item, model, is_selected); - if(str) //-V547 + if(text != NULL) { canvas_draw_str_aligned( - canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); + canvas, + 64, + 9 + (i * 17) + STATUS_BAR_Y_SHIFT, + AlignCenter, + AlignCenter, + furi_string_get_cstr(text)); - if(m->idx == i) elements_frame(canvas, 15, 1 + (i * 17) + STATUS_BAR_Y_SHIFT, 98, 15); + furi_string_free(text); + } + + if(is_selected) + elements_frame( + canvas, + 15, + 1 + (i * 17) + STATUS_BAR_Y_SHIFT, + DESKTOP_LOCK_MENU_NEEDS_SCROLL_BAR ? 95 : 98, + 15); } + + if(DESKTOP_LOCK_MENU_NEEDS_SCROLL_BAR) + elements_scrollbar_pos( + canvas, 115, 1 + STATUS_BAR_Y_SHIFT, 51, m->idx, DESKTOP_LOCK_MENU_ITEM_COUNT); } View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu) { @@ -92,8 +361,6 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { DesktopLockMenuView* lock_menu = context; uint8_t idx = 0; bool consumed = false; - bool dummy_mode = false; - bool stealth_mode = false; bool update = false; with_view_model( @@ -103,47 +370,35 @@ bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { if(event->key == InputKeyUp) { if(model->idx == 0) { - model->idx = DesktopLockMenuIndexTotalCount - 1; + model->idx = DESKTOP_LOCK_MENU_ITEM_COUNT - 1; } else { - model->idx = CLAMP(model->idx - 1, DesktopLockMenuIndexTotalCount - 1, 0); + model->idx = + CLAMP(model->idx - 1, (int8_t)DESKTOP_LOCK_MENU_ITEM_COUNT - 1, 0); } update = true; consumed = true; } else if(event->key == InputKeyDown) { - if(model->idx == DesktopLockMenuIndexTotalCount - 1) { + if(model->idx == DESKTOP_LOCK_MENU_ITEM_COUNT - 1) { model->idx = 0; } else { - model->idx = CLAMP(model->idx + 1, DesktopLockMenuIndexTotalCount - 1, 0); + model->idx = + CLAMP(model->idx + 1, (int8_t)DESKTOP_LOCK_MENU_ITEM_COUNT - 1, 0); } update = true; consumed = true; } } idx = model->idx; - dummy_mode = model->dummy_mode; - stealth_mode = model->stealth_mode; }, update); - if(event->key == InputKeyOk) { - if(idx == DesktopLockMenuIndexLock) { - if(event->type == InputTypeShort) { - lock_menu->callback(DesktopLockMenuEventLock, lock_menu->context); - } - } else if(idx == DesktopLockMenuIndexStealth) { - if((stealth_mode == false) && (event->type == InputTypeShort)) { - lock_menu->callback(DesktopLockMenuEventStealthModeOn, lock_menu->context); - } else if((stealth_mode == true) && (event->type == InputTypeShort)) { - lock_menu->callback(DesktopLockMenuEventStealthModeOff, lock_menu->context); - } - } else if(idx == DesktopLockMenuIndexDummy) { - if((dummy_mode == false) && (event->type == InputTypeShort)) { - lock_menu->callback(DesktopLockMenuEventDummyModeOn, lock_menu->context); - } else if((dummy_mode == true) && (event->type == InputTypeShort)) { - lock_menu->callback(DesktopLockMenuEventDummyModeOff, lock_menu->context); - } - } - consumed = true; + if((event->type == InputTypeShort || event->type == InputTypeRepeat) && + (event->key == InputKeyOk || event->key == InputKeyLeft || event->key == InputKeyRight)) { + const DesktopLockMenuItem* menu_item = &menu_items[idx]; + if(menu_item->on_input) + consumed = menu_item->on_input(menu_item, event, lock_menu); + else + consumed = true; } return consumed; diff --git a/applications/services/desktop/views/desktop_view_lock_menu.h b/applications/services/desktop/views/desktop_view_lock_menu.h index a44e6b13276..a97f6144f47 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.h +++ b/applications/services/desktop/views/desktop_view_lock_menu.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "desktop_events.h" #define HINT_TIMEOUT 2 @@ -13,12 +14,15 @@ struct DesktopLockMenuView { View* view; DesktopLockMenuViewCallback callback; void* context; + NotificationApp* notification_record; }; typedef struct { uint8_t idx; bool dummy_mode; bool stealth_mode; + uint8_t display_brightness_index; + bool notification_settings_changed; } DesktopLockMenuViewModel; void desktop_lock_menu_set_callback( @@ -30,5 +34,10 @@ View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu); void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool dummy_mode); void desktop_lock_menu_set_stealth_mode_state(DesktopLockMenuView* lock_menu, bool stealth_mode); void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx); +void desktop_lock_menu_set_notification_record( + DesktopLockMenuView* lock_menu, + NotificationApp* notification); +bool desktop_lock_menu_did_notification_settings_change(DesktopLockMenuView* lock_menu); +void desktop_lock_menu_refresh_notification_values(DesktopLockMenuView* lock_menu); DesktopLockMenuView* desktop_lock_menu_alloc(void); void desktop_lock_menu_free(DesktopLockMenuView* lock_menu); diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c index 35d2fe675aa..ccdd6761460 100644 --- a/applications/services/notification/notification_app.c +++ b/applications/services/notification/notification_app.c @@ -32,6 +32,21 @@ static uint8_t notification_settings_get_display_brightness(NotificationApp* app static uint8_t notification_settings_get_rgb_led_brightness(NotificationApp* app, uint8_t value); static uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app); +const char* backlight_text[BACKLIGHT_COUNT] = { + "0%", + "25%", + "50%", + "75%", + "100%", +}; +const float backlight_value[BACKLIGHT_COUNT] = { + 0.0f, + 0.25f, + 0.5f, + 0.75f, + 1.0f, +}; + void notification_message_save_settings(NotificationApp* app) { NotificationAppMessage m = { .type = SaveSettingsMessage, .back_event = furi_event_flag_alloc()}; diff --git a/applications/services/notification/notification_app.h b/applications/services/notification/notification_app.h index e1954657417..4fe3fea3a68 100644 --- a/applications/services/notification/notification_app.h +++ b/applications/services/notification/notification_app.h @@ -7,6 +7,10 @@ #define NOTIFICATION_LED_COUNT 3 #define NOTIFICATION_EVENT_COMPLETE 0x00000001U +#define BACKLIGHT_COUNT 5 +extern const char* backlight_text[BACKLIGHT_COUNT]; +extern const float backlight_value[BACKLIGHT_COUNT]; + typedef enum { NotificationLayerMessage, InternalLayerMessage, diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c index ada2bfdd42c..2d61770a775 100644 --- a/applications/settings/notification_settings/notification_settings_app.c +++ b/applications/settings/notification_settings/notification_settings_app.c @@ -48,22 +48,6 @@ const int32_t contrast_value[CONTRAST_COUNT] = { 5, }; -#define BACKLIGHT_COUNT 5 -const char* const backlight_text[BACKLIGHT_COUNT] = { - "0%", - "25%", - "50%", - "75%", - "100%", -}; -const float backlight_value[BACKLIGHT_COUNT] = { - 0.0f, - 0.25f, - 0.5f, - 0.75f, - 1.0f, -}; - #define VOLUME_COUNT 5 const char* const volume_text[VOLUME_COUNT] = { "0%",