Skip to content

Commit 23ef551

Browse files
committed
PR InfiniTimeOrg#1697 + restyle
1 parent 374baaf commit 23ef551

11 files changed

Lines changed: 150 additions & 23 deletions

File tree

src/components/ble/NotificationManager.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ constexpr uint8_t NotificationManager::MessageSize;
1010
void NotificationManager::Push(NotificationManager::Notification&& notif) {
1111
notif.id = GetNextId();
1212
notif.valid = true;
13+
notif.timeArrived = std::chrono::system_clock::to_time_t(dateTimeController.CurrentDateTime());
1314
newNotification = true;
1415
if (beginIdx > 0) {
1516
--beginIdx;
@@ -61,6 +62,13 @@ NotificationManager::Notification::Idx NotificationManager::IndexOf(Notification
6162
return size;
6263
}
6364

65+
NotificationManager::Categories NotificationManager::CategoryAt(Notification::Idx idx) const {
66+
if (idx >= this->size) {
67+
return NotificationManager::Categories::Unknown;
68+
}
69+
return this->At(idx).category;
70+
}
71+
6472
NotificationManager::Notification NotificationManager::Get(NotificationManager::Notification::Id id) const {
6573
NotificationManager::Notification::Idx idx = this->IndexOf(id);
6674
if (idx == this->size) {

src/components/ble/NotificationManager.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <atomic>
55
#include <cstddef>
66
#include <cstdint>
7+
#include <chrono>
8+
#include "components/datetime/DateTimeController.h"
79

810
namespace Pinetime {
911
namespace Controllers {
@@ -30,20 +32,26 @@ namespace Pinetime {
3032
Id id = 0;
3133
bool valid = false;
3234
uint8_t size;
35+
std::time_t timeArrived;
3336
std::array<char, MessageSize + 1> message;
3437
Categories category = Categories::Unknown;
3538

3639
const char* Message() const;
3740
const char* Title() const;
3841
};
3942

43+
NotificationManager(const Controllers::DateTime& dateTimeController)
44+
: dateTimeController {dateTimeController} {
45+
}
46+
4047
void Push(Notification&& notif);
4148
Notification GetLastNotification() const;
4249
Notification Get(Notification::Id id) const;
4350
Notification GetNext(Notification::Id id) const;
4451
Notification GetPrevious(Notification::Id id) const;
4552
// Return the index of the notification with the specified id, if not found return NbNotifications()
4653
Notification::Idx IndexOf(Notification::Id id) const;
54+
Categories CategoryAt(Notification::Idx idx) const;
4755
bool ClearNewNotificationFlag();
4856
bool AreNewNotificationsAvailable() const;
4957
void Dismiss(Notification::Id id);
@@ -59,6 +67,7 @@ namespace Pinetime {
5967
size_t NbNotifications() const;
6068

6169
private:
70+
const Controllers::DateTime& dateTimeController;
6271
Notification::Id nextId {0};
6372
Notification::Id GetNextId();
6473
const Notification& At(Notification::Idx idx) const;

src/displayapp/DisplayApp.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
440440
notificationManager,
441441
systemTask->nimble().alertService(),
442442
motorController,
443+
dateTimeController,
443444
*systemTask,
444445
Screens::Notifications::Modes::Normal);
445446
break;
@@ -448,6 +449,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
448449
notificationManager,
449450
systemTask->nimble().alertService(),
450451
motorController,
452+
dateTimeController,
451453
*systemTask,
452454
Screens::Notifications::Modes::Preview);
453455
break;

src/displayapp/fonts/fonts.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88
{
99
"file": "FontAwesome5-Solid+Brands+Regular.woff",
10-
"range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c"
10+
"range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf059, 0xf0f3, 0xf0e0, 0xf1ea, 0xf7cd, 0xf071, 0xf075"
1111
}
1212
],
1313
"bpp": 1,

src/displayapp/screens/NotificationIcon.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,33 @@ const char* NotificationIcon::GetIcon(bool newNotificationAvailable) {
77
return Symbols::info;
88
else
99
return "";
10-
}
10+
}
11+
12+
// TODO: does this really belong here?
13+
const char* NotificationIcon::GetCategoryIcon(Pinetime::Controllers::NotificationManager::Categories category) {
14+
switch (category) {
15+
case Pinetime::Controllers::NotificationManager::Categories::SimpleAlert:
16+
return Symbols::bell;
17+
case Pinetime::Controllers::NotificationManager::Categories::Email:
18+
return Symbols::envelope;
19+
case Pinetime::Controllers::NotificationManager::Categories::News:
20+
return Symbols::newspaper;
21+
case Pinetime::Controllers::NotificationManager::Categories::IncomingCall:
22+
return Symbols::phone;
23+
case Pinetime::Controllers::NotificationManager::Categories::MissedCall:
24+
return Symbols::phoneSlash;
25+
case Pinetime::Controllers::NotificationManager::Categories::Sms:
26+
return Symbols::smsBubble;
27+
case Pinetime::Controllers::NotificationManager::Categories::VoiceMail:
28+
return Symbols::voicemail;
29+
case Pinetime::Controllers::NotificationManager::Categories::Schedule:
30+
return Symbols::clock;
31+
case Pinetime::Controllers::NotificationManager::Categories::HighProriotyAlert:
32+
return Symbols::warningTriangle;
33+
case Pinetime::Controllers::NotificationManager::Categories::InstantMessage:
34+
return Symbols::messageBubble;
35+
case Pinetime::Controllers::NotificationManager::Categories::Unknown:
36+
default:
37+
return Symbols::questionCircle;
38+
}
39+
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#pragma once
2+
#include "components/ble/NotificationManager.h"
23

34
namespace Pinetime {
45
namespace Applications {
56
namespace Screens {
67
class NotificationIcon {
78
public:
89
static const char* GetIcon(bool newNotificationAvailable);
10+
static const char* GetCategoryIcon(Pinetime::Controllers::NotificationManager::Categories category);
911
};
1012
}
1113
}
12-
}
14+
}

src/displayapp/screens/Notifications.cpp

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
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

123131
void 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

247261
Notifications::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

258276
Notifications::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

Comments
 (0)