Skip to content
Closed
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
81 changes: 81 additions & 0 deletions src/fw/apps/system_apps/settings/settings_system.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ typedef enum {
SystemMenuItemInformation,
SystemMenuItemCertification,
SystemMenuItemStationaryToggle,
SystemMenuItemPanicMode,
SystemMenuItemDebugging,
SystemMenuItemShutDown,
SystemMenuItemFactoryReset,
Expand All @@ -162,6 +163,7 @@ static const char *s_item_titles[SystemMenuItem_Count] = {
[SystemMenuItemInformation] = i18n_noop("Information"),
[SystemMenuItemCertification] = i18n_noop("Certification"),
[SystemMenuItemStationaryToggle] = i18n_noop("Stand-By Mode"),
[SystemMenuItemPanicMode] = i18n_noop("Panic Mode"),
[SystemMenuItemDebugging] = i18n_noop("Debugging"),
[SystemMenuItemShutDown] = i18n_noop("Shut Down"),
[SystemMenuItemFactoryReset] = i18n_noop("Factory Reset"),
Expand Down Expand Up @@ -384,6 +386,79 @@ static void prv_maybe_trigger_core_dump() {
app_confirmation_dialog_push(confirmation_dialog);
}

// Panic Mode confirmation
////////////////////////////

static void prv_panic_mode_dialog_load_cb(void *context) {
ExpandableDialog *expandable_dialog = (ExpandableDialog *)context;
Dialog *dialog = expandable_dialog_get_dialog(expandable_dialog);

// Center the main text after the dialog window loads
text_layer_set_text_alignment(&dialog->text_layer, GTextAlignmentCenter);

// Center the header text
text_layer_set_text_alignment(&expandable_dialog->header_layer, GTextAlignmentCenter);

// Center the icon by repositioning it, accounting for the action bar
KinoLayer *icon_layer = &dialog->icon_layer;
if (kino_layer_get_reel(icon_layer)) {
GRect icon_frame = icon_layer->layer.frame;
GRect window_frame = dialog->window.layer.frame;

// Check if action bar is shown and account for its width
bool show_action_bar = expandable_dialog->show_action_bar;
uint16_t action_bar_width = show_action_bar ? ACTION_BAR_WIDTH : 0;

// Center horizontally within the content area (excluding action bar)
uint16_t content_width = window_frame.size.w - action_bar_width;
icon_frame.origin.x = (content_width - icon_frame.size.w) / 2;
layer_set_frame(&icon_layer->layer, &icon_frame);
}
}

static void prv_panic_mode_confirm_cb(ClickRecognizerRef recognizer, void *context) {
ExpandableDialog *dialog = (ExpandableDialog *)context;

expandable_dialog_pop(dialog);

// Toggle panic mode setting
bool current_state = shell_prefs_get_panic_mode_enabled();
shell_prefs_set_panic_mode_enabled(!current_state);

// Reload the menu to reflect the change
settings_menu_reload_data(SettingsMenuItemSystem);
}

static void prv_panic_mode_interstitial_trigger(SettingsSystemData *context) {
const char *message;
const char *header;

// Show appropriate message based on current state
if (shell_prefs_get_panic_mode_enabled()) {
header = i18n_noop("Disable Panic Mode?");
message = i18n_noop("Notifications will no longer be cleared.");
} else {
header = i18n_noop("Enable Panic Mode?");
message = i18n_noop("Clears notifications on airplane, stand-by, and charging.");
}

// Set up callbacks to center text after window loads
static DialogCallbacks callbacks = {
.load = prv_panic_mode_dialog_load_cb,
.unload = NULL
};

// Create expandable dialog with scrolling support
ExpandableDialog *expandable_dialog = expandable_dialog_create_with_params(
"Panic Mode", RESOURCE_ID_RESULT_DELETED_SMALL, message, GColorWhite,
GColorRed, &callbacks, RESOURCE_ID_ACTION_BAR_ICON_CHECK,
prv_panic_mode_confirm_cb);
expandable_dialog_set_header(expandable_dialog, header);
expandable_dialog_show_action_bar(expandable_dialog, true);

app_expandable_dialog_push(expandable_dialog);
}

// ALS Threshold Settings
/////////////////////////////

Expand Down Expand Up @@ -1320,6 +1395,9 @@ static void prv_draw_row_cb(SettingsCallbacks *context, GContext *ctx,
case SystemMenuItemStationaryToggle:
subtitle = stationary_get_enabled() ? i18n_get("On", data) : i18n_get("Off", data);
break;
case SystemMenuItemPanicMode:
subtitle = shell_prefs_get_panic_mode_enabled() ? i18n_get("On", data) : i18n_get("Off", data);
break;
case SystemMenuItemShutDown:
if (!prv_shutdown_enabled()) {
// XXX: For now, gray out the Shut Down item if unusable.
Expand Down Expand Up @@ -1355,6 +1433,9 @@ static void prv_select_click_cb(SettingsCallbacks *context, uint16_t row) {
case SystemMenuItemStationaryToggle:
stationary_set_enabled(!stationary_get_enabled());
break;
case SystemMenuItemPanicMode:
prv_panic_mode_interstitial_trigger(data);
break;
case SystemMenuItemShutDown:
if (prv_shutdown_enabled()) {
launcher_task_add_callback(prv_shutdown_cb, 0);
Expand Down
12 changes: 11 additions & 1 deletion src/fw/apps/system_apps/toggle/airplane_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,23 @@
#include "process_management/app_manager.h"
#include "services/common/bluetooth/bluetooth_ctl.h"
#include "services/common/i18n/i18n.h"
#include "services/normal/notifications/notification_storage.h"
#include "shell/prefs.h"

static bool prv_get_state(void *context) {
return bt_ctl_is_airplane_mode_on();
}

static void prv_set_state(bool enabled, void *context) {
bt_ctl_set_airplane_mode_async(!bt_ctl_is_airplane_mode_on());
// Store the current state before toggling
bool will_be_enabled = !bt_ctl_is_airplane_mode_on();

bt_ctl_set_airplane_mode_async(will_be_enabled);

// If panic mode is enabled and we're turning on airplane mode, wipe notifications
if (will_be_enabled && shell_prefs_get_panic_mode_enabled()) {
notification_storage_reset_and_init();
}
}

static const ActionToggleImpl s_airplane_mode_action_toggle_impl = {
Expand Down
11 changes: 11 additions & 0 deletions src/fw/services/normal/stationary.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "services/common/i18n/i18n.h"
#include "services/common/regular_timer.h"
#include "services/common/system_task.h"
#include "services/normal/notifications/notification_storage.h"
#include "services/runlevel.h"
#include "shell/prefs.h"
#include "system/logging.h"
Expand Down Expand Up @@ -103,6 +104,11 @@ void stationary_handle_battery_connection_change_event(void) {
"Stationary mode battery state change event received");
if (battery_is_usb_connected()) {
analytics_event_stationary_state_change(rtc_get_time(), StationaryAnalyticsEnterCharging);

// If panic mode is enabled, wipe notifications when charger is connected
if (shell_prefs_get_panic_mode_enabled()) {
notification_storage_reset_and_init();
}
} else {
analytics_event_stationary_state_change(rtc_get_time(), StationaryAnalyticsExitCharging);
}
Expand Down Expand Up @@ -218,6 +224,11 @@ static void prv_enter_stationary_state(void) {
services_set_runlevel(RunLevel_Stationary);
accel_enable_high_sensitivity(true);
s_current_state = StationaryStateStationary;

// If panic mode is enabled, wipe notifications when entering stationary mode
if (shell_prefs_get_panic_mode_enabled()) {
notification_storage_reset_and_init();
}
}

static void prv_exit_stationary(void) {
Expand Down
16 changes: 16 additions & 0 deletions src/fw/shell/normal/prefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ static bool s_stationary_mode_enabled = false;
static bool s_stationary_mode_enabled = true;
#endif

#define PREF_KEY_PANIC_MODE "panicMode"
static bool s_panic_mode_enabled = false;

#define PREF_KEY_DEFAULT_WORKER "workerId"
static Uuid s_default_worker = UUID_INVALID_INIT;

Expand Down Expand Up @@ -377,6 +380,11 @@ static bool prv_set_s_stationary_mode_enabled(bool *enabled) {
return true;
}

static bool prv_set_s_panic_mode_enabled(bool *enabled) {
s_panic_mode_enabled = *enabled;
return true;
}

static bool prv_set_s_default_worker(Uuid *uuid) {
s_default_worker = *uuid;
return true;
Expand Down Expand Up @@ -1060,6 +1068,14 @@ void shell_prefs_set_stationary_enabled(bool enabled) {
prv_pref_set(PREF_KEY_STATIONARY, &enabled, sizeof(enabled));
}

bool shell_prefs_get_panic_mode_enabled(void) {
return s_panic_mode_enabled;
}

void shell_prefs_set_panic_mode_enabled(bool enabled) {
prv_pref_set(PREF_KEY_PANIC_MODE, &enabled, sizeof(enabled));
}

AppInstallId worker_preferences_get_default_worker(void) {
return app_install_get_id_for_uuid(&s_default_worker);
}
Expand Down
1 change: 1 addition & 0 deletions src/fw/shell/normal/prefs_values.h.inc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#endif
PREFS_MACRO(PREF_KEY_BACKLIGHT_AMBIENT_THRESHOLD, s_backlight_ambient_threshold)
PREFS_MACRO(PREF_KEY_STATIONARY, s_stationary_mode_enabled)
PREFS_MACRO(PREF_KEY_PANIC_MODE, s_panic_mode_enabled)
PREFS_MACRO(PREF_KEY_DEFAULT_WORKER, s_default_worker)
PREFS_MACRO(PREF_KEY_TEXT_STYLE, s_text_style)
PREFS_MACRO(PREF_KEY_LANG_ENGLISH, s_language_english)
Expand Down
4 changes: 4 additions & 0 deletions src/fw/shell/prefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ void backlight_set_ambient_threshold(uint32_t threshold);
bool shell_prefs_get_stationary_enabled(void);
void shell_prefs_set_stationary_enabled(bool enabled);

// Panic mode will wipe all notifications when entering airplane mode, stationary mode, or charging.
bool shell_prefs_get_panic_mode_enabled(void);
void shell_prefs_set_panic_mode_enabled(bool enabled);

// The default worker setting is used by process_management.
AppInstallId worker_preferences_get_default_worker(void);
void worker_preferences_set_default_worker(AppInstallId id);
Expand Down
Loading