From dffc05fb1b70f41f200c9d365f405934610277e3 Mon Sep 17 00:00:00 2001 From: John Crawford Date: Fri, 2 Feb 2024 02:42:11 -0700 Subject: [PATCH] notifications: add option to clear all notifications --- src/displayapp/screens/Notifications.cpp | 98 +++++++++++++++++++++--- src/displayapp/screens/Notifications.h | 15 +++- 2 files changed, 99 insertions(+), 14 deletions(-) diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 037c43a7f6..cfd97c5b21 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -33,10 +33,11 @@ Notifications::Notifications(DisplayApp* app, notification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + motorController, + this); validDisplay = true; } else { - currentItem = std::make_unique(alertNotificationService, motorController); + currentItem = std::make_unique(alertNotificationService, motorController, this); validDisplay = false; } if (mode == Modes::Preview) { @@ -82,7 +83,7 @@ void Notifications::Refresh() { } else if (mode == Modes::Preview && dismissingNotification) { running = false; - currentItem = std::make_unique(alertNotificationService, motorController); + currentItem = std::make_unique(alertNotificationService, motorController, this); } else if (dismissingNotification) { dismissingNotification = false; @@ -111,9 +112,10 @@ void Notifications::Refresh() { notification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + motorController, + this); } else { - currentItem = std::make_unique(alertNotificationService, motorController); + currentItem = std::make_unique(alertNotificationService, motorController, this); } } @@ -139,6 +141,25 @@ void Notifications::DismissToBlack() { dismissingNotification = true; } +void Notifications::DismissAll() { + if (validDisplay) { + auto previousMessage = notificationManager.GetPrevious(currentId); + auto nextMessage = notificationManager.GetNext(currentId); + while (notificationManager.NbNotifications() != 0) { + previousMessage = notificationManager.GetPrevious(currentId); + nextMessage = notificationManager.GetNext(currentId); + afterDismissNextMessageFromAbove = previousMessage.valid; + notificationManager.Dismiss(currentId); + if (previousMessage.valid) { + currentId = previousMessage.id; + } else if (nextMessage.valid) { + currentId = nextMessage.id; + } + } + DismissToBlack(); + } +} + void Notifications::OnPreviewDismiss() { notificationManager.Dismiss(currentId); if (timeoutLine != nullptr) { @@ -163,7 +184,11 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { switch (event) { case Pinetime::Applications::TouchEvents::SwipeRight: - if (validDisplay) { + if (dismissMenuOpen) { + currentItem->hideClearBtn(); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::Left); + dismissMenuOpen = false; + } else if (validDisplay) { auto previousMessage = notificationManager.GetPrevious(currentId); auto nextMessage = notificationManager.GetNext(currentId); afterDismissNextMessageFromAbove = previousMessage.valid; @@ -179,6 +204,14 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return true; } return false; + case Pinetime::Applications::TouchEvents::SwipeLeft: + if (notificationManager.NbNotifications() == 0) { + return false; + } + currentItem->showClearBtn(); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::Right); + dismissMenuOpen = true; + return true; case Pinetime::Applications::TouchEvents::SwipeDown: { Controllers::NotificationManager::Notification previousNotification; if (validDisplay) { @@ -202,7 +235,8 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { previousNotification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + motorController, + this); } return true; case Pinetime::Applications::TouchEvents::SwipeUp: { @@ -229,7 +263,8 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { nextNotification.category, notificationManager.NbNotifications(), alertNotificationService, - motorController); + motorController, + this); } return true; default: @@ -242,17 +277,23 @@ namespace { auto* item = static_cast(obj->user_data); item->OnCallButtonEvent(obj, event); } + void DismissEventHandler(lv_obj_t* obj, lv_event_t event) { + auto* item = static_cast(obj->user_data); + item->OnDismissButtonEvent(event); + } } Notifications::NotificationItem::NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController) + Pinetime::Controllers::MotorController& motorController, + Notifications *parent) : NotificationItem("Notification", "No notification to display", 0, Controllers::NotificationManager::Categories::Unknown, 0, alertNotificationService, - motorController) { + motorController, + parent) { } Notifications::NotificationItem::NotificationItem(const char* title, @@ -261,8 +302,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, + Notifications *parent) + : alertNotificationService {alertNotificationService}, motorController {motorController}, parent {parent} { 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); @@ -307,6 +349,20 @@ Notifications::NotificationItem::NotificationItem(const char* title, lv_label_set_long_mode(alert_subject, LV_LABEL_LONG_BREAK); lv_obj_set_width(alert_subject, LV_HOR_RES - 20); + btnClearAll = lv_btn_create(lv_scr_act(), nullptr); + btnClearAll->user_data = this; + lv_obj_set_size(btnClearAll, 100, 100); + lv_obj_align(btnClearAll, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); + lv_obj_set_style_local_bg_color(btnClearAll, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); + lv_obj_set_style_local_pad_all(btnClearAll, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10); + lv_obj_set_style_local_pad_inner(btnClearAll, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5); + lv_obj_set_style_local_border_width(btnClearAll, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_event_cb(btnClearAll, DismissEventHandler); + labelBtnClearAll = lv_label_create(btnClearAll, nullptr); + lv_label_set_text_static(labelBtnClearAll, "Dismiss\n All"); + lv_obj_set_hidden(btnClearAll, true); + + switch (category) { default: lv_label_set_text(alert_subject, msg); @@ -351,6 +407,16 @@ Notifications::NotificationItem::NotificationItem(const char* title, } } +void Notifications::NotificationItem::showClearBtn() { + lv_obj_set_pos(container, -100, 0); + lv_obj_set_hidden(btnClearAll, false); +} + +void Notifications::NotificationItem::hideClearBtn() { + lv_obj_set_pos(container, 0, 0); + lv_obj_set_hidden(btnClearAll, true); +} + void Notifications::NotificationItem::OnCallButtonEvent(lv_obj_t* obj, lv_event_t event) { if (event != LV_EVENT_CLICKED) { return; @@ -369,6 +435,14 @@ void Notifications::NotificationItem::OnCallButtonEvent(lv_obj_t* obj, lv_event_ running = false; } +void Notifications::NotificationItem::OnDismissButtonEvent(lv_event_t event) { + if (event != LV_EVENT_CLICKED) { + return; + } + + this->parent->DismissAll(); +} + Notifications::NotificationItem::~NotificationItem() { lv_obj_clean(lv_scr_act()); } diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index 114316b35b..653c67fd5d 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -31,27 +31,34 @@ namespace Pinetime { void Refresh() override; bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; void DismissToBlack(); + void DismissAll(); void OnPreviewInteraction(); void OnPreviewDismiss(); class NotificationItem { public: NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, - Pinetime::Controllers::MotorController& motorController); + Pinetime::Controllers::MotorController& motorController, + Notifications *parent); 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, + Notifications *parent); ~NotificationItem(); bool IsRunning() const { return running; } + void showClearBtn(); + void hideClearBtn(); + void OnCallButtonEvent(lv_obj_t*, lv_event_t event); + void OnDismissButtonEvent(lv_event_t event); private: lv_obj_t* container; @@ -62,8 +69,11 @@ namespace Pinetime { lv_obj_t* label_accept; lv_obj_t* label_mute; lv_obj_t* label_reject; + lv_obj_t* btnClearAll; + lv_obj_t* labelBtnClearAll; Pinetime::Controllers::AlertNotificationService& alertNotificationService; Pinetime::Controllers::MotorController& motorController; + Notifications *parent; bool running = true; }; @@ -86,6 +96,7 @@ namespace Pinetime { static const TickType_t timeoutLength = pdMS_TO_TICKS(7000); bool interacted = true; + bool dismissMenuOpen = false; bool dismissingNotification = false;