settings: Add sleep/wake notification times

Add configure screens for sleep and wake notification times, so the
watch can automatically set notifications to sleep or on as applicable.
This commit is contained in:
Justin Hibbits 2024-01-20 16:53:35 -05:00
parent 2135e12b33
commit 3ab84601a3
12 changed files with 427 additions and 1 deletions

View file

@ -413,7 +413,10 @@ list(APPEND SOURCE_FILES
displayapp/screens/settings/SettingSteps.cpp
displayapp/screens/settings/SettingSetDateTime.cpp
displayapp/screens/settings/SettingSetDate.cpp
displayapp/screens/settings/SettingSetSleepTime.cpp
displayapp/screens/settings/SettingSetSleepWakeTime.cpp
displayapp/screens/settings/SettingSetTime.cpp
displayapp/screens/settings/SettingSetWakeTime.cpp
displayapp/screens/settings/SettingChimes.cpp
displayapp/screens/settings/SettingShakeThreshold.cpp
displayapp/screens/settings/SettingBluetooth.cpp

View file

@ -101,6 +101,9 @@ void DateTime::UpdateTime(uint32_t systickCounter) {
} else if (hour != 0) {
isMidnightAlreadyNotified = false;
}
// Finally change notification status if necessary
settingsController.SetNotificationStatusByTime(hour, minute);
}
const char* DateTime::MonthShortToString() const {

View file

@ -203,6 +203,47 @@ namespace Pinetime {
return settings.notificationStatus;
};
void SetNotificationStatusByTime(uint8_t h, uint8_t m) {
if (settings.notificationStatus == Notification::Off) {
return;
}
if (settings.sleepHour == settings.wakeHour &&
settings.sleepMinute == settings.wakeMinute) {
return;
}
if (h == settings.sleepHour && m == settings.sleepMinute) {
SetNotificationStatus(Notification::Sleep);
} else if (h == settings.wakeHour && m == settings.wakeMinute) {
SetNotificationStatus(Notification::On);
}
};
void SetSleepTime(uint8_t h, uint8_t m) {
if (h != settings.sleepHour || m != settings.sleepMinute) {
settingsChanged = true;
}
settings.sleepHour = h;
settings.sleepMinute = m;
};
void SetWakeTime(uint8_t h, uint8_t m) {
if (h != settings.wakeHour || m != settings.wakeMinute) {
settingsChanged = true;
}
settings.wakeHour = h;
settings.wakeMinute = m;
};
void GetSleepTime(uint8_t &h, uint8_t &m) {
h = settings.sleepHour;
m = settings.sleepMinute;
};
void GetWakeTime(uint8_t &h, uint8_t &m) {
h = settings.wakeHour;
m = settings.wakeMinute;
};
void SetScreenTimeOut(uint32_t timeout) {
if (timeout != settings.screenTimeOut) {
settingsChanged = true;
@ -286,7 +327,7 @@ namespace Pinetime {
private:
Pinetime::Controllers::FS& fs;
static constexpr uint32_t settingsVersion = 0x0007;
static constexpr uint32_t settingsVersion = 0x0008;
struct SettingsData {
uint32_t version = settingsVersion;
@ -308,6 +349,10 @@ namespace Pinetime {
uint16_t shakeWakeThreshold = 150;
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
uint8_t sleepHour;
uint8_t sleepMinute;
uint8_t wakeHour;
uint8_t wakeMinute;
};
SettingsData settings;

View file

@ -47,6 +47,7 @@
#include "displayapp/screens/settings/SettingSetDateTime.h"
#include "displayapp/screens/settings/SettingChimes.h"
#include "displayapp/screens/settings/SettingShakeThreshold.h"
#include "displayapp/screens/settings/SettingSetSleepWakeTime.h"
#include "displayapp/screens/settings/SettingBluetooth.h"
#include "libs/lv_conf.h"
@ -519,6 +520,9 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
case Apps::SettingChimes:
currentScreen = std::make_unique<Screens::SettingChimes>(settingsController);
break;
case Apps::SettingSetSleepWakeTime:
currentScreen = std::make_unique<Screens::SettingSetSleepWakeTime>(this, dateTimeController, settingsController);
break;
case Apps::SettingShakeThreshold:
currentScreen = std::make_unique<Screens::SettingShakeThreshold>(settingsController, motionController, *systemTask);
break;

View file

@ -38,6 +38,7 @@ namespace Pinetime {
SettingWakeUp,
SettingSteps,
SettingSetDateTime,
SettingSetSleepWakeTime,
SettingChimes,
SettingShakeThreshold,
SettingBluetooth,

View file

@ -0,0 +1,103 @@
#include "displayapp/screens/settings/SettingSetSleepTime.h"
#include <lvgl/lvgl.h>
#include <nrf_log.h>
#include "displayapp/DisplayApp.h"
#include "displayapp/screens/Symbols.h"
#include "components/settings/Settings.h"
#include "displayapp/InfiniTimeTheme.h"
using namespace Pinetime::Applications::Screens;
namespace {
constexpr int16_t POS_Y_TEXT = -7;
void SetTimeEventHandler(lv_obj_t* obj, lv_event_t event) {
auto* screen = static_cast<SettingSetSleepTime*>(obj->user_data);
if (event == LV_EVENT_CLICKED) {
screen->SetTime();
}
}
void ValueChangedHandler(void* userData) {
auto* screen = static_cast<SettingSetSleepTime*>(userData);
screen->UpdateScreen();
}
}
SettingSetSleepTime::SettingSetSleepTime(Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Settings& settingsController,
Pinetime::Applications::Screens::SettingSetSleepWakeTime& settingSetSleepWakeTime)
: dateTimeController {dateTimeController}, settingsController {settingsController}, settingSetSleepWakeTime {settingSetSleepWakeTime} {
uint8_t h, m;
lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(title, "Set sleep time");
lv_label_set_align(title, LV_LABEL_ALIGN_CENTER);
lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15);
lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE);
lv_label_set_text_static(icon, Symbols::clock);
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);
lv_obj_t* staticLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(staticLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
lv_label_set_text_static(staticLabel, "00:00:00");
lv_obj_align(staticLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, POS_Y_TEXT);
hourCounter.Create();
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
hourCounter.EnableTwelveHourMode();
}
settingsController.GetSleepTime(h, m);
hourCounter.SetValue(h);
lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_CENTER, -75, POS_Y_TEXT);
hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler);
minuteCounter.Create();
minuteCounter.SetValue(m);
lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_CENTER, 0, POS_Y_TEXT);
minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler);
lblampm = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(lblampm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20);
lv_label_set_text_static(lblampm, " ");
lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 75, -50);
btnSetTime = lv_btn_create(lv_scr_act(), nullptr);
btnSetTime->user_data = this;
lv_obj_set_size(btnSetTime, 120, 50);
lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0);
lblSetTime = lv_label_create(btnSetTime, nullptr);
lv_label_set_text_static(lblSetTime, "Set");
lv_obj_set_style_local_bg_color(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt);
lv_obj_set_style_local_text_color(lblSetTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, LV_COLOR_GRAY);
lv_obj_set_event_cb(btnSetTime, SetTimeEventHandler);
UpdateScreen();
}
SettingSetSleepTime::~SettingSetSleepTime() {
lv_obj_clean(lv_scr_act());
}
void SettingSetSleepTime::UpdateScreen() {
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
if (hourCounter.GetValue() >= 12) {
lv_label_set_text_static(lblampm, "PM");
} else {
lv_label_set_text_static(lblampm, "AM");
}
}
}
void SettingSetSleepTime::SetTime() {
const int hoursValue = hourCounter.GetValue();
const int minutesValue = minuteCounter.GetValue();
NRF_LOG_INFO("Setting sleep time to %02d:%02d:00", hoursValue, minutesValue);
settingsController.SetSleepTime(static_cast<uint8_t>(hoursValue),
static_cast<uint8_t>(minutesValue));
settingSetSleepWakeTime.Quit();
}

View file

@ -0,0 +1,38 @@
#pragma once
#include <cstdint>
#include <lvgl/lvgl.h>
#include "components/datetime/DateTimeController.h"
#include "components/settings/Settings.h"
#include "displayapp/widgets/Counter.h"
#include "displayapp/screens/Screen.h"
#include "displayapp/widgets/DotIndicator.h"
#include "displayapp/screens/settings/SettingSetSleepWakeTime.h"
namespace Pinetime {
namespace Applications {
namespace Screens {
class SettingSetSleepTime : public Screen {
public:
SettingSetSleepTime(Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Settings& settingsController,
Pinetime::Applications::Screens::SettingSetSleepWakeTime& settingSetSleepWakeTime);
~SettingSetSleepTime() override;
void SetTime();
void UpdateScreen();
private:
Controllers::DateTime& dateTimeController;
Controllers::Settings& settingsController;
Pinetime::Applications::Screens::SettingSetSleepWakeTime& settingSetSleepWakeTime;
lv_obj_t* lblampm;
lv_obj_t* btnSetTime;
lv_obj_t* lblSetTime;
Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_42);
Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_42);
};
}
}
}

View file

@ -0,0 +1,54 @@
#include "displayapp/screens/settings/SettingSetSleepWakeTime.h"
#include "displayapp/screens/settings/SettingSetSleepTime.h"
#include "displayapp/screens/settings/SettingSetWakeTime.h"
#include "displayapp/DisplayApp.h"
#include "displayapp/screens/ScreenList.h"
#include "components/settings/Settings.h"
#include "displayapp/widgets/DotIndicator.h"
using namespace Pinetime::Applications::Screens;
bool SettingSetSleepWakeTime::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
return screens.OnTouchEvent(event);
}
SettingSetSleepWakeTime::SettingSetSleepWakeTime(Pinetime::Applications::DisplayApp* app,
Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Settings& settingsController)
: app {app},
dateTimeController {dateTimeController},
settingsController {settingsController},
screens {app,
0,
{[this]() -> std::unique_ptr<Screen> {
return screenSetSleepTime();
},
[this]() -> std::unique_ptr<Screen> {
return screenSetWakeTime();
}},
Screens::ScreenListModes::UpDown} {
}
std::unique_ptr<Screen> SettingSetSleepWakeTime::screenSetSleepTime() {
Widgets::DotIndicator dotIndicator(0, 2);
dotIndicator.Create();
return std::make_unique<Screens::SettingSetSleepTime>(dateTimeController, settingsController, *this);
}
std::unique_ptr<Screen> SettingSetSleepWakeTime::screenSetWakeTime() {
Widgets::DotIndicator dotIndicator(1, 2);
dotIndicator.Create();
return std::make_unique<Screens::SettingSetWakeTime>(dateTimeController, settingsController, *this);
}
SettingSetSleepWakeTime::~SettingSetSleepWakeTime() {
lv_obj_clean(lv_scr_act());
}
void SettingSetSleepWakeTime::Advance() {
screens.OnTouchEvent(Pinetime::Applications::TouchEvents::SwipeUp);
}
void SettingSetSleepWakeTime::Quit() {
running = false;
}

View file

@ -0,0 +1,33 @@
#pragma once
#include <cstdint>
#include <lvgl/lvgl.h>
#include "displayapp/screens/Screen.h"
#include "displayapp/screens/ScreenList.h"
namespace Pinetime {
namespace Applications {
namespace Screens {
class SettingSetSleepWakeTime : public Screen {
public:
SettingSetSleepWakeTime(DisplayApp* app,
Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Settings& settingsController);
~SettingSetSleepWakeTime() override;
bool OnTouchEvent(TouchEvents event) override;
void Advance();
void Quit();
private:
DisplayApp* app;
Controllers::DateTime& dateTimeController;
Controllers::Settings& settingsController;
ScreenList<2> screens;
std::unique_ptr<Screen> screenSetSleepTime();
std::unique_ptr<Screen> screenSetWakeTime();
};
}
}
}

View file

@ -0,0 +1,103 @@
#include "displayapp/screens/settings/SettingSetWakeTime.h"
#include <lvgl/lvgl.h>
#include <nrf_log.h>
#include "displayapp/DisplayApp.h"
#include "displayapp/screens/Symbols.h"
#include "components/settings/Settings.h"
#include "displayapp/InfiniTimeTheme.h"
using namespace Pinetime::Applications::Screens;
namespace {
constexpr int16_t POS_Y_TEXT = -7;
void SetTimeEventHandler(lv_obj_t* obj, lv_event_t event) {
auto* screen = static_cast<SettingSetWakeTime*>(obj->user_data);
if (event == LV_EVENT_CLICKED) {
screen->SetTime();
}
}
void ValueChangedHandler(void* userData) {
auto* screen = static_cast<SettingSetWakeTime*>(userData);
screen->UpdateScreen();
}
}
SettingSetWakeTime::SettingSetWakeTime(Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Settings& settingsController,
Pinetime::Applications::Screens::SettingSetSleepWakeTime& settingSetSleepWakeTime)
: dateTimeController {dateTimeController}, settingsController {settingsController}, settingSetSleepWakeTime {settingSetSleepWakeTime} {
uint8_t h, m;
lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(title, "Set current time");
lv_label_set_align(title, LV_LABEL_ALIGN_CENTER);
lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15);
lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE);
lv_label_set_text_static(icon, Symbols::clock);
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);
lv_obj_t* staticLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(staticLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
lv_label_set_text_static(staticLabel, "00:00:00");
lv_obj_align(staticLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, POS_Y_TEXT);
settingsController.GetWakeTime(h, m);
hourCounter.Create();
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
hourCounter.EnableTwelveHourMode();
}
hourCounter.SetValue(h);
lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_CENTER, -75, POS_Y_TEXT);
hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler);
minuteCounter.Create();
minuteCounter.SetValue(m);
lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_CENTER, 0, POS_Y_TEXT);
minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler);
lblampm = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(lblampm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20);
lv_label_set_text_static(lblampm, " ");
lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 75, -50);
btnSetTime = lv_btn_create(lv_scr_act(), nullptr);
btnSetTime->user_data = this;
lv_obj_set_size(btnSetTime, 120, 50);
lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0);
lblSetTime = lv_label_create(btnSetTime, nullptr);
lv_label_set_text_static(lblSetTime, "Set");
lv_obj_set_style_local_bg_color(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt);
lv_obj_set_style_local_text_color(lblSetTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, LV_COLOR_GRAY);
lv_obj_set_event_cb(btnSetTime, SetTimeEventHandler);
UpdateScreen();
}
SettingSetWakeTime::~SettingSetWakeTime() {
lv_obj_clean(lv_scr_act());
}
void SettingSetWakeTime::UpdateScreen() {
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
if (hourCounter.GetValue() >= 12) {
lv_label_set_text_static(lblampm, "PM");
} else {
lv_label_set_text_static(lblampm, "AM");
}
}
}
void SettingSetWakeTime::SetTime() {
const int hoursValue = hourCounter.GetValue();
const int minutesValue = minuteCounter.GetValue();
NRF_LOG_INFO("Setting wakeup time to %02d:%02d:00", hoursValue, minutesValue);
settingsController.SetSleepTime(static_cast<uint8_t>(hoursValue),
static_cast<uint8_t>(minutesValue));
settingSetSleepWakeTime.Quit();
}

View file

@ -0,0 +1,38 @@
#pragma once
#include <cstdint>
#include <lvgl/lvgl.h>
#include "components/datetime/DateTimeController.h"
#include "components/settings/Settings.h"
#include "displayapp/widgets/Counter.h"
#include "displayapp/screens/Screen.h"
#include "displayapp/widgets/DotIndicator.h"
#include "displayapp/screens/settings/SettingSetSleepWakeTime.h"
namespace Pinetime {
namespace Applications {
namespace Screens {
class SettingSetWakeTime : public Screen {
public:
SettingSetWakeTime(Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Settings& settingsController,
Pinetime::Applications::Screens::SettingSetSleepWakeTime& settingSetSleepWakeTime);
~SettingSetWakeTime() override;
void SetTime();
void UpdateScreen();
private:
Controllers::DateTime& dateTimeController;
Controllers::Settings& settingsController;
Pinetime::Applications::Screens::SettingSetSleepWakeTime& settingSetSleepWakeTime;
lv_obj_t* lblampm;
lv_obj_t* btnSetTime;
lv_obj_t* lblSetTime;
Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_42);
Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_42);
};
}
}
}

View file

@ -43,6 +43,7 @@ namespace Pinetime {
{Symbols::batteryHalf, "Battery", Apps::BatteryInfo},
{Symbols::clock, "Chimes", Apps::SettingChimes},
{Symbols::clock, "Sleep/Wake", Apps::SettingSetSleepWakeTime},
{Symbols::tachometer, "Shake Calib.", Apps::SettingShakeThreshold},
{Symbols::check, "Firmware", Apps::FirmwareValidation},
{Symbols::bluetooth, "Bluetooth", Apps::SettingBluetooth},