diff --git a/src/components/ble/NotificationManager.cpp b/src/components/ble/NotificationManager.cpp index 223f6221af..c2490b512d 100644 --- a/src/components/ble/NotificationManager.cpp +++ b/src/components/ble/NotificationManager.cpp @@ -10,6 +10,7 @@ constexpr uint8_t NotificationManager::MessageSize; void NotificationManager::Push(NotificationManager::Notification&& notif) { notif.id = GetNextId(); notif.valid = true; + notif.timeArrived = std::chrono::system_clock::to_time_t(dateTimeController.CurrentDateTime()); newNotification = true; if (beginIdx > 0) { --beginIdx; diff --git a/src/components/ble/NotificationManager.h b/src/components/ble/NotificationManager.h index 189a7e1355..a5c9621966 100644 --- a/src/components/ble/NotificationManager.h +++ b/src/components/ble/NotificationManager.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include "components/datetime/DateTimeController.h" namespace Pinetime { namespace Controllers { @@ -28,6 +30,7 @@ namespace Pinetime { using Id = uint8_t; using Idx = uint8_t; + std::time_t timeArrived; std::array message; uint8_t size; Categories category = Categories::Unknown; @@ -38,6 +41,9 @@ namespace Pinetime { const char* Title() const; }; + NotificationManager(Controllers::DateTime& dateTimeController) : dateTimeController {dateTimeController} { + } + void Push(Notification&& notif); Notification GetLastNotification() const; Notification Get(Notification::Id id) const; @@ -61,6 +67,7 @@ namespace Pinetime { private: Notification::Id nextId {0}; + Controllers::DateTime& dateTimeController; Notification::Id GetNextId(); const Notification& At(Notification::Idx idx) const; Notification& At(Notification::Idx idx); diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index b1594f197c..d04e91e14b 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -562,6 +562,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio notificationManager, systemTask->nimble().alertService(), motorController, + dateTimeController, *systemTask, Screens::Notifications::Modes::Normal); break; @@ -570,6 +571,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio notificationManager, systemTask->nimble().alertService(), motorController, + dateTimeController, *systemTask, Screens::Notifications::Modes::Preview); break; diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 45f72f2e20..16b8ed55e5 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -14,12 +14,14 @@ Notifications::Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::MotorController& motorController, + Pinetime::Controllers::DateTime& dateTimeController, System::SystemTask& systemTask, Modes mode) : app {app}, notificationManager {notificationManager}, alertNotificationService {alertNotificationService}, motorController {motorController}, + dateTimeController {dateTimeController}, wakeLock(systemTask), mode {mode} { @@ -31,6 +33,8 @@ Notifications::Notifications(DisplayApp* app, notification.Message(), 1, notification.category, + notification.timeArrived, + std::chrono::system_clock::to_time_t(this->dateTimeController.CurrentDateTime()), notificationManager.NbNotifications(), alertNotificationService, motorController); @@ -107,6 +111,8 @@ void Notifications::Refresh() { notification.Message(), currentIdx + 1, notification.category, + notification.timeArrived, + std::chrono::system_clock::to_time_t(this->dateTimeController.CurrentDateTime()), notificationManager.NbNotifications(), alertNotificationService, motorController); @@ -200,6 +206,8 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { previousNotification.Message(), currentIdx + 1, previousNotification.category, + previousNotification.timeArrived, + std::chrono::system_clock::to_time_t(dateTimeController.CurrentDateTime()), notificationManager.NbNotifications(), alertNotificationService, motorController); @@ -227,6 +235,8 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { nextNotification.Message(), currentIdx + 1, nextNotification.category, + nextNotification.timeArrived, + std::chrono::system_clock::to_time_t(dateTimeController.CurrentDateTime()), notificationManager.NbNotifications(), alertNotificationService, motorController); @@ -251,6 +261,8 @@ Notifications::NotificationItem::NotificationItem(Pinetime::Controllers::AlertNo 0, Controllers::NotificationManager::Categories::Unknown, 0, + 0, + 0, alertNotificationService, motorController) { } @@ -259,6 +271,8 @@ Notifications::NotificationItem::NotificationItem(const char* title, const char* msg, uint8_t notifNr, Controllers::NotificationManager::Categories category, + std::time_t timeArrived, + std::time_t timeNow, uint8_t notifNb, Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::MotorController& motorController) @@ -324,8 +338,8 @@ Notifications::NotificationItem::NotificationItem(const char* title, bt_accept = lv_btn_create(container, nullptr); bt_accept->user_data = this; lv_obj_set_event_cb(bt_accept, CallEventHandler); - lv_obj_set_size(bt_accept, 76, 76); - lv_obj_align(bt_accept, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_obj_set_size(bt_accept, 76, 38); + lv_obj_align(bt_accept, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, -34); label_accept = lv_label_create(bt_accept, nullptr); lv_label_set_text_static(label_accept, Symbols::phone); lv_obj_set_style_local_bg_color(bt_accept, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight); @@ -333,8 +347,8 @@ Notifications::NotificationItem::NotificationItem(const char* title, bt_reject = lv_btn_create(container, nullptr); bt_reject->user_data = this; lv_obj_set_event_cb(bt_reject, CallEventHandler); - lv_obj_set_size(bt_reject, 76, 76); - lv_obj_align(bt_reject, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + lv_obj_set_size(bt_reject, 76, 38); + lv_obj_align(bt_reject, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, -34); label_reject = lv_label_create(bt_reject, nullptr); lv_label_set_text_static(label_reject, Symbols::phoneSlash); lv_obj_set_style_local_bg_color(bt_reject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); @@ -342,13 +356,37 @@ Notifications::NotificationItem::NotificationItem(const char* title, bt_mute = lv_btn_create(container, nullptr); bt_mute->user_data = this; lv_obj_set_event_cb(bt_mute, CallEventHandler); - lv_obj_set_size(bt_mute, 76, 76); - lv_obj_align(bt_mute, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + lv_obj_set_size(bt_mute, 76, 38); + lv_obj_align(bt_mute, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, -34); label_mute = lv_label_create(bt_mute, nullptr); lv_label_set_text_static(label_mute, Symbols::volumMute); lv_obj_set_style_local_bg_color(bt_mute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); } break; } + AddAlertAgeLabel(timeArrived, timeNow); +} + +void Notifications::NotificationItem::AddAlertAgeLabel(std::time_t timeArrived, std::time_t timeNow) { + // almost impossible to receive a real notification at time 0, so skip because it is the "no notifications" notification + if (timeNow != 0) { + auto diff = std::chrono::system_clock::from_time_t(timeNow) - std::chrono::system_clock::from_time_t(timeArrived); + std::chrono::minutes age = std::chrono::duration_cast(diff); + uint32_t ageInt = static_cast(age.count()); + char timeUnit; + if (ageInt / (60 * 24) >= 1) { + ageInt /= (60 * 24); + timeUnit = 'd'; + } else if (ageInt >= 60) { + ageInt /= 60; + timeUnit = 'h'; + } else { + timeUnit = 'm'; + } + lv_obj_t* alertAge = lv_label_create(container, nullptr); + lv_label_set_text_fmt(alertAge, "%d%c ago", ageInt, timeUnit); + // same format as alert_count + lv_obj_align(alertAge, container, LV_ALIGN_IN_BOTTOM_RIGHT, -10, -10); + } } void Notifications::NotificationItem::OnCallButtonEvent(lv_obj_t* obj, lv_event_t event) { diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index 8488dc5bb2..07b586d460 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -2,10 +2,12 @@ #include #include +#include #include #include #include "displayapp/screens/Screen.h" #include "components/ble/NotificationManager.h" +#include "components/datetime/DateTimeController.h" #include "components/motor/MotorController.h" #include "systemtask/SystemTask.h" #include "systemtask/WakeLock.h" @@ -25,6 +27,7 @@ namespace Pinetime { Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::MotorController& motorController, + Pinetime::Controllers::DateTime& dateTimeController, System::SystemTask& systemTask, Modes mode); ~Notifications() override; @@ -43,6 +46,8 @@ namespace Pinetime { const char* msg, uint8_t notifNr, Controllers::NotificationManager::Categories, + std::time_t timeArrived, + std::time_t timeNow, uint8_t notifNb, Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::MotorController& motorController); @@ -55,6 +60,8 @@ namespace Pinetime { void OnCallButtonEvent(lv_obj_t*, lv_event_t event); private: + void AddAlertAgeLabel(std::time_t timeArrived, std::time_t timeNow); + lv_obj_t* container; lv_obj_t* subject_container; lv_obj_t* bt_accept; @@ -74,6 +81,7 @@ namespace Pinetime { Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Controllers::AlertNotificationService& alertNotificationService; Pinetime::Controllers::MotorController& motorController; + Pinetime::Controllers::DateTime& dateTimeController; System::WakeLock wakeLock; Modes mode = Modes::Normal; std::unique_ptr currentItem; diff --git a/src/main.cpp b/src/main.cpp index 24f13caddd..10e01e7c47 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -102,7 +102,7 @@ Pinetime::Controllers::MotorController motorController {}; Pinetime::Controllers::DateTime dateTimeController {settingsController}; Pinetime::Drivers::Watchdog watchdog; -Pinetime::Controllers::NotificationManager notificationManager; +Pinetime::Controllers::NotificationManager notificationManager {dateTimeController}; Pinetime::Controllers::MotionController motionController; Pinetime::Controllers::AlarmController alarmController {dateTimeController, fs}; Pinetime::Controllers::TouchHandler touchHandler;