diff --git a/src/components/ble/NotificationManager.cpp b/src/components/ble/NotificationManager.cpp index 223f6221af..da9236357b 100644 --- a/src/components/ble/NotificationManager.cpp +++ b/src/components/ble/NotificationManager.cpp @@ -61,6 +61,13 @@ NotificationManager::Notification::Idx NotificationManager::IndexOf(Notification return size; } +NotificationManager::Categories NotificationManager::CategoryAt(Notification::Idx idx) const { + if (idx < 0 || idx >= this->size) { + return NotificationManager::Categories::Unknown; + } + return this->At(idx).category; +} + NotificationManager::Notification NotificationManager::Get(NotificationManager::Notification::Id id) const { NotificationManager::Notification::Idx idx = this->IndexOf(id); if (idx == this->size) { diff --git a/src/components/ble/NotificationManager.h b/src/components/ble/NotificationManager.h index 09b5a5610e..d3847759af 100644 --- a/src/components/ble/NotificationManager.h +++ b/src/components/ble/NotificationManager.h @@ -44,6 +44,7 @@ namespace Pinetime { Notification GetPrevious(Notification::Id id) const; // Return the index of the notification with the specified id, if not found return NbNotifications() Notification::Idx IndexOf(Notification::Id id) const; + Categories CategoryAt(Notification::Idx idx) const; bool ClearNewNotificationFlag(); bool AreNewNotificationsAvailable() const; void Dismiss(Notification::Id id); diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 914ba16314..ee798f68bf 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -7,7 +7,7 @@ }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", - "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" + "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" } ], "bpp": 1, diff --git a/src/displayapp/screens/NotificationIcon.cpp b/src/displayapp/screens/NotificationIcon.cpp index 0e913ae764..14cf51ac62 100644 --- a/src/displayapp/screens/NotificationIcon.cpp +++ b/src/displayapp/screens/NotificationIcon.cpp @@ -7,4 +7,33 @@ const char* NotificationIcon::GetIcon(bool newNotificationAvailable) { return Symbols::info; else return ""; +} + +// TODO: does this really belong here? +const char* NotificationIcon::GetCategoryIcon(Pinetime::Controllers::NotificationManager::Categories category) { + switch (category) { + case Pinetime::Controllers::NotificationManager::Categories::SimpleAlert: + return Symbols::bell; + case Pinetime::Controllers::NotificationManager::Categories::Email: + return Symbols::envelope; + case Pinetime::Controllers::NotificationManager::Categories::News: + return Symbols::newspaper; + case Pinetime::Controllers::NotificationManager::Categories::IncomingCall: + return Symbols::phone; + case Pinetime::Controllers::NotificationManager::Categories::MissedCall: + return Symbols::phoneSlash; + case Pinetime::Controllers::NotificationManager::Categories::Sms: + return Symbols::smsBubble; + case Pinetime::Controllers::NotificationManager::Categories::VoiceMail: + return Symbols::voicemail; + case Pinetime::Controllers::NotificationManager::Categories::Schedule: + return Symbols::clock; + case Pinetime::Controllers::NotificationManager::Categories::HighProriotyAlert: + return Symbols::warningTriangle; + case Pinetime::Controllers::NotificationManager::Categories::InstantMessage: + return Symbols::messageBubble; + case Pinetime::Controllers::NotificationManager::Categories::Unknown: + default: + return Symbols::questionCircle; + } } \ No newline at end of file diff --git a/src/displayapp/screens/NotificationIcon.h b/src/displayapp/screens/NotificationIcon.h index dc34c3f083..3ec3805b4c 100644 --- a/src/displayapp/screens/NotificationIcon.h +++ b/src/displayapp/screens/NotificationIcon.h @@ -1,4 +1,5 @@ #pragma once +#include "components/ble/NotificationManager.h" namespace Pinetime { namespace Applications { @@ -6,6 +7,7 @@ namespace Pinetime { class NotificationIcon { public: static const char* GetIcon(bool newNotificationAvailable); + static const char* GetCategoryIcon(Pinetime::Controllers::NotificationManager::Categories category); }; } } diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 037c43a7f6..a06477af9b 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -1,4 +1,5 @@ #include "displayapp/screens/Notifications.h" +#include "displayapp/screens/NotificationIcon.h" #include "displayapp/DisplayApp.h" #include "components/ble/MusicService.h" #include "components/ble/AlertNotificationService.h" @@ -33,10 +34,11 @@ Notifications::Notifications(DisplayApp* app, notification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + motorController, + notificationManager); validDisplay = true; } else { - currentItem = std::make_unique(alertNotificationService, motorController); + currentItem = std::make_unique(alertNotificationService, motorController, notificationManager); validDisplay = false; } if (mode == Modes::Preview) { @@ -82,7 +84,7 @@ void Notifications::Refresh() { } else if (mode == Modes::Preview && dismissingNotification) { running = false; - currentItem = std::make_unique(alertNotificationService, motorController); + currentItem = std::make_unique(alertNotificationService, motorController, notificationManager); } else if (dismissingNotification) { dismissingNotification = false; @@ -111,9 +113,10 @@ void Notifications::Refresh() { notification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + motorController, + notificationManager); } else { - currentItem = std::make_unique(alertNotificationService, motorController); + currentItem = std::make_unique(alertNotificationService, motorController, notificationManager); } } @@ -202,7 +205,8 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { previousNotification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + motorController, + notificationManager); } return true; case Pinetime::Applications::TouchEvents::SwipeUp: { @@ -229,7 +233,8 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { nextNotification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + motorController, + notificationManager); } return true; default: @@ -245,14 +250,16 @@ namespace { } Notifications::NotificationItem::NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController) + Pinetime::Controllers::MotorController& motorController, + Pinetime::Controllers::NotificationManager& notificationManager) : NotificationItem("Notification", "No notification to display", 0, Controllers::NotificationManager::Categories::Unknown, 0, alertNotificationService, - motorController) { + motorController, + notificationManager) { } Notifications::NotificationItem::NotificationItem(const char* title, @@ -261,8 +268,9 @@ Notifications::NotificationItem::NotificationItem(const char* title, Controllers::NotificationManager::Categories category, uint8_t notifNb, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController) - : alertNotificationService {alertNotificationService}, motorController {motorController} { + Pinetime::Controllers::MotorController& motorController, + Pinetime::Controllers::NotificationManager& notificationManager) + : alertNotificationService {alertNotificationService}, motorController {motorController}, notificationManager {notificationManager} { container = lv_cont_create(lv_scr_act(), nullptr); lv_obj_set_size(container, LV_HOR_RES, LV_VER_RES); lv_obj_set_style_local_bg_color(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); @@ -281,6 +289,19 @@ Notifications::NotificationItem::NotificationItem(const char* title, lv_cont_set_layout(subject_container, LV_LAYOUT_COLUMN_LEFT); lv_cont_set_fit(subject_container, LV_FIT_NONE); + // draw notification stack + if (category != Pinetime::Controllers::NotificationManager::Categories::IncomingCall) { + for (int i = 0; i < notifNb; i++) { + lv_obj_t* alert_icon = lv_label_create(container, nullptr); + if (i + 1 == notifNr) { // currently selected should be orange + lv_obj_set_style_local_text_color(alert_icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); + } + // TODO: get categories for the other notifications + lv_label_set_text_fmt(alert_icon, NotificationIcon::GetCategoryIcon(notificationManager.CategoryAt(i))); + lv_obj_align(alert_icon, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, -22 * i); + } + } + lv_obj_t* alert_count = lv_label_create(container, nullptr); lv_label_set_text_fmt(alert_count, "%i/%i", notifNr, notifNb); lv_obj_align(alert_count, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 16); diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index 114316b35b..9ea42acd44 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -37,14 +37,16 @@ namespace Pinetime { class NotificationItem { public: NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController); + Pinetime::Controllers::MotorController& motorController, + Pinetime::Controllers::NotificationManager& notificationManager); NotificationItem(const char* title, const char* msg, uint8_t notifNr, Controllers::NotificationManager::Categories, uint8_t notifNb, Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController); + Pinetime::Controllers::MotorController& motorController, + Pinetime::Controllers::NotificationManager& notificationManager); ~NotificationItem(); bool IsRunning() const { @@ -64,6 +66,7 @@ namespace Pinetime { lv_obj_t* label_reject; Pinetime::Controllers::AlertNotificationService& alertNotificationService; Pinetime::Controllers::MotorController& motorController; + Pinetime::Controllers::NotificationManager& notificationManager; bool running = true; }; diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 934cdc3f65..e208b556ba 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -50,6 +50,19 @@ namespace Pinetime { static constexpr const char* flashlight = "\xEF\x80\x8B"; static constexpr const char* paintbrushLg = "\xEE\x90\x8A"; + + // used for notification stack icons + static constexpr const char* questionCircle = "\xEF\x81\x99"; // F059 + static constexpr const char* bell = "\xEF\x83\xB3"; // F0F3 + static constexpr const char* envelope = "\xEF\x83\xA0"; // F0E0 + static constexpr const char* newspaper = "\xEF\x87\xAA"; // F1EA + static constexpr const char* smsBubble = "\xEF\x9F\x8D"; // F7CD + // TODO codepoint F897 should exist in fontawesome 5, but our version doesn't have it + // need to do something about that + // static constexpr const char* voicemail = "\xEF\xA2\x97"; // F897 + static constexpr const char* voicemail = questionCircle; // TODO revert to above once fontaweosme issue is resolved + static constexpr const char* warningTriangle = "\xEF\x81\xB1"; // F071 + static constexpr const char* messageBubble = "\xEF\x81\xB5"; // F075 } } }