11#include " displayapp/screens/Notifications.h"
2+ #include " displayapp/screens/NotificationIcon.h"
23#include " displayapp/DisplayApp.h"
34#include " components/ble/MusicService.h"
45#include " components/ble/AlertNotificationService.h"
@@ -14,11 +15,13 @@ Notifications::Notifications(DisplayApp* app,
1415 Pinetime::Controllers::NotificationManager& notificationManager,
1516 Pinetime::Controllers::AlertNotificationService& alertNotificationService,
1617 Pinetime::Controllers::MotorController& motorController,
18+ Pinetime::Controllers::DateTime& dateTimeController,
1719 System::SystemTask& systemTask,
1820 Modes mode)
1921 : app {app},
2022 notificationManager {notificationManager},
2123 alertNotificationService {alertNotificationService},
24+ dateTimeController {dateTimeController},
2225 motorController {motorController},
2326 systemTask {systemTask},
2427 mode {mode} {
@@ -31,12 +34,15 @@ Notifications::Notifications(DisplayApp* app,
3134 notification.Message (),
3235 1 ,
3336 notification.category ,
37+ notification.timeArrived ,
38+ std::chrono::system_clock::to_time_t (this ->dateTimeController .CurrentDateTime ()),
3439 notificationManager.NbNotifications (),
3540 alertNotificationService,
36- motorController);
41+ motorController,
42+ notificationManager);
3743 validDisplay = true ;
3844 } else {
39- currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController);
45+ currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController, notificationManager );
4046 validDisplay = false ;
4147 }
4248 if (mode == Modes::Preview) {
@@ -82,7 +88,6 @@ void Notifications::Refresh() {
8288
8389 } else if (mode == Modes::Preview && dismissingNotification) {
8490 running = false ;
85- currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController);
8691
8792 } else if (dismissingNotification) {
8893 dismissingNotification = false ;
@@ -109,15 +114,18 @@ void Notifications::Refresh() {
109114 notification.Message (),
110115 currentIdx + 1 ,
111116 notification.category ,
117+ notification.timeArrived ,
118+ std::chrono::system_clock::to_time_t (this ->dateTimeController .CurrentDateTime ()),
112119 notificationManager.NbNotifications (),
113120 alertNotificationService,
114- motorController);
121+ motorController,
122+ notificationManager);
115123 } else {
116- currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController) ;
124+ running = false ;
117125 }
118126 }
119127
120- running = currentItem->IsRunning () && running ;
128+ running = running && currentItem->IsRunning ();
121129}
122130
123131void Notifications::OnPreviewInteraction () {
@@ -200,9 +208,12 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
200208 previousNotification.Message (),
201209 currentIdx + 1 ,
202210 previousNotification.category ,
211+ previousNotification.timeArrived ,
212+ std::chrono::system_clock::to_time_t (this ->dateTimeController .CurrentDateTime ()),
203213 notificationManager.NbNotifications (),
204214 alertNotificationService,
205- motorController);
215+ motorController,
216+ notificationManager);
206217 }
207218 return true ;
208219 case Pinetime::Applications::TouchEvents::SwipeUp: {
@@ -227,9 +238,12 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
227238 nextNotification.Message (),
228239 currentIdx + 1 ,
229240 nextNotification.category ,
241+ nextNotification.timeArrived ,
242+ std::chrono::system_clock::to_time_t (this ->dateTimeController .CurrentDateTime ()),
230243 notificationManager.NbNotifications (),
231244 alertNotificationService,
232- motorController);
245+ motorController,
246+ notificationManager);
233247 }
234248 return true ;
235249 default :
@@ -245,24 +259,31 @@ namespace {
245259}
246260
247261Notifications::NotificationItem::NotificationItem (Pinetime::Controllers::AlertNotificationService& alertNotificationService,
248- Pinetime::Controllers::MotorController& motorController)
262+ Pinetime::Controllers::MotorController& motorController,
263+ Pinetime::Controllers::NotificationManager& notificationManager)
249264 : NotificationItem(" Notification" ,
250265 " No notification to display" ,
251266 0 ,
252267 Controllers::NotificationManager::Categories::Unknown,
253268 0 ,
269+ 0 ,
270+ 0 ,
254271 alertNotificationService,
255- motorController) {
272+ motorController,
273+ notificationManager) {
256274}
257275
258276Notifications::NotificationItem::NotificationItem (const char * title,
259277 const char * msg,
260278 uint8_t notifNr,
261279 Controllers::NotificationManager::Categories category,
280+ std::time_t timeArrived,
281+ std::time_t timeNow,
262282 uint8_t notifNb,
263283 Pinetime::Controllers::AlertNotificationService& alertNotificationService,
264- Pinetime::Controllers::MotorController& motorController)
265- : alertNotificationService {alertNotificationService}, motorController {motorController} {
284+ Pinetime::Controllers::MotorController& motorController,
285+ Pinetime::Controllers::NotificationManager& notificationManager)
286+ : alertNotificationService {alertNotificationService}, motorController {motorController}, notificationManager {notificationManager} {
266287 container = lv_cont_create (lv_scr_act (), nullptr );
267288 lv_obj_set_size (container, LV_HOR_RES, LV_VER_RES);
268289 lv_obj_set_style_local_bg_color (container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
@@ -276,14 +297,48 @@ Notifications::NotificationItem::NotificationItem(const char* title,
276297 lv_obj_set_style_local_pad_inner (subject_container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5 );
277298 lv_obj_set_style_local_border_width (subject_container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0 );
278299
279- lv_obj_set_pos (subject_container, 0 , 50 );
280- lv_obj_set_size (subject_container, LV_HOR_RES, LV_VER_RES - 50 );
300+ lv_obj_set_pos (subject_container, 0 , 37 );
301+ lv_obj_set_size (subject_container, LV_HOR_RES, LV_VER_RES - 66 );
281302 lv_cont_set_layout (subject_container, LV_LAYOUT_COLUMN_LEFT);
282303 lv_cont_set_fit (subject_container, LV_FIT_NONE);
283304
305+ // draw notification stack
306+ if (category != Pinetime::Controllers::NotificationManager::Categories::IncomingCall) {
307+ for (int i = 0 ; i < notifNb; i++) {
308+ lv_obj_t * alert_icon = lv_label_create (container, nullptr );
309+ if (i + 1 == notifNr) { // currently selected should be orange
310+ lv_obj_set_style_local_text_color (alert_icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange);
311+ }
312+ // TODO: get categories for the other notifications
313+ lv_label_set_text_fmt (alert_icon, NotificationIcon::GetCategoryIcon (notificationManager.CategoryAt (i)));
314+ lv_obj_align (alert_icon, nullptr , LV_ALIGN_IN_BOTTOM_RIGHT, -5 + (-25 * i), -3 );
315+ }
316+ }
317+
284318 lv_obj_t * alert_count = lv_label_create (container, nullptr );
285319 lv_label_set_text_fmt (alert_count, " %i/%i" , notifNr, notifNb);
286- lv_obj_align (alert_count, nullptr , LV_ALIGN_IN_TOP_RIGHT, 0 , 16 );
320+ lv_obj_align (alert_count, nullptr , LV_ALIGN_IN_TOP_RIGHT, 0 , 8 );
321+
322+ // almost impossible to receive a real notification at time 0, so skip because it is the "no notifications" notification
323+ if (timeNow != 0 ) {
324+ auto diff = std::chrono::system_clock::from_time_t (timeNow) - std::chrono::system_clock::from_time_t (timeArrived);
325+ std::chrono::minutes age = std::chrono::duration_cast<std::chrono::minutes>(diff);
326+ uint32_t ageInt = static_cast <uint32_t >(age.count ());
327+ char timeUnit;
328+ if (ageInt >= 60 * 24 ) {
329+ ageInt /= (60 * 24 );
330+ timeUnit = ' d' ;
331+ } else if (ageInt >= 60 ) {
332+ ageInt /= 60 ;
333+ timeUnit = ' h' ;
334+ } else {
335+ timeUnit = ' m' ;
336+ }
337+ lv_obj_t * alert_age = lv_label_create (container, nullptr );
338+ lv_label_set_text_fmt (alert_age, " %d%c ago" , ageInt, timeUnit);
339+ // same format as alert_count
340+ lv_obj_align (alert_age, container, LV_ALIGN_IN_BOTTOM_LEFT, 5 , -3 );
341+ }
287342
288343 lv_obj_t * alert_type = lv_label_create (container, nullptr );
289344 lv_obj_set_style_local_text_color (alert_type, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange);
@@ -301,7 +356,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
301356 }
302357 lv_label_set_long_mode (alert_type, LV_LABEL_LONG_SROLL_CIRC);
303358 lv_obj_set_width (alert_type, 180 );
304- lv_obj_align (alert_type, nullptr , LV_ALIGN_IN_TOP_LEFT, 0 , 16 );
359+ lv_obj_align (alert_type, nullptr , LV_ALIGN_IN_TOP_LEFT, 0 , 8 );
305360
306361 lv_obj_t * alert_subject = lv_label_create (subject_container, nullptr );
307362 lv_label_set_long_mode (alert_subject, LV_LABEL_LONG_BREAK);
0 commit comments