From a9de4329b8f22b8e28e10d0271d37c90b5e7d8a4 Mon Sep 17 00:00:00 2001 From: OmgRod <89850217+OmgRod@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:25:08 +0100 Subject: [PATCH 1/3] Add skippable notifications --- loader/include/Geode/ui/Notification.hpp | 32 ++++++++++++++++++++++++ loader/src/ui/nodes/Notification.cpp | 22 ++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/loader/include/Geode/ui/Notification.hpp b/loader/include/Geode/ui/Notification.hpp index ce79bd922..3f60bf766 100644 --- a/loader/include/Geode/ui/Notification.hpp +++ b/loader/include/Geode/ui/Notification.hpp @@ -27,6 +27,7 @@ namespace geode { cocos2d::CCSprite* m_icon = nullptr; float m_time; bool m_showing = false; + bool m_skippableOnQueue = false; bool init(std::string const& text, cocos2d::CCSprite* icon, float time); void updateLayout(); @@ -37,6 +38,7 @@ namespace geode { void animateOut(); void showNextNotification(); void wait(); + void maybeSkipForQueuedNotification(); public: /** @@ -67,6 +69,36 @@ namespace geode { cocos2d::CCSprite* icon, float time = NOTIFICATION_DEFAULT_TIME ); + /** + * Create a low-priority notification that is shown for at most + * maxTime seconds, but can be skipped early if another notification + * enters the queue. + * @param text Notification text + * @param icon Icon to show in the notification + * @param maxTime Maximum time to show the notification on screen + * @returns The new notification. Make sure to call show() to show the + * notification + */ + static Notification* createSkippable( + std::string const& text, + NotificationIcon icon = NotificationIcon::None, + float maxTime = NOTIFICATION_DEFAULT_TIME + ); + /** + * Create a low-priority notification with a custom icon that is shown + * for at most maxTime seconds, but can be skipped early if another + * notification enters the queue. + * @param text Notification text + * @param icon Icon to show in the notification + * @param maxTime Maximum time to show the notification on screen + * @returns The new notification. Make sure to call show() to show the + * notification + */ + static Notification* createSkippable( + std::string const& text, + cocos2d::CCSprite* icon, + float maxTime = NOTIFICATION_DEFAULT_TIME + ); void setString(std::string const& text); void setIcon(NotificationIcon icon); diff --git a/loader/src/ui/nodes/Notification.cpp b/loader/src/ui/nodes/Notification.cpp index 2b4afbd88..d0431ccf0 100644 --- a/loader/src/ui/nodes/Notification.cpp +++ b/loader/src/ui/nodes/Notification.cpp @@ -114,6 +114,18 @@ Notification* Notification::create(std::string const& text, CCSprite* icon, floa return nullptr; } +Notification* Notification::createSkippable(std::string const& text, NotificationIcon icon, float maxTime) { + return Notification::createSkippable(text, createIcon(icon), maxTime); +} + +Notification* Notification::createSkippable(std::string const& text, CCSprite* icon, float maxTime) { + if (auto ret = Notification::create(text, icon, maxTime)) { + ret->m_skippableOnQueue = true; + return ret; + } + return nullptr; +} + void Notification::setString(std::string const& text) { m_label->setString(text.c_str()); this->updateLayout(); @@ -173,6 +185,10 @@ void Notification::show() { s_queue->addObject(this); } if (s_queue->firstObject() != this) { + auto current = static_cast(s_queue->firstObject()); + if (current) { + current->maybeSkipForQueuedNotification(); + } return; } if (!this->getParent()) { @@ -203,6 +219,12 @@ void Notification::wait() { } } +void Notification::maybeSkipForQueuedNotification() { + if (m_showing && m_skippableOnQueue) { + this->hide(); + } +} + void Notification::hide() { this->stopAllActions(); this->runAction(CCSequence::create( From 42d3884eab1537aa71eafa2ce7c1486893e32f2c Mon Sep 17 00:00:00 2001 From: OmgRod <89850217+OmgRod@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:35:59 +0100 Subject: [PATCH 2/3] Fix Notification merge resolution for skippable API --- loader/include/Geode/ui/Notification.hpp | 1 + loader/src/ui/nodes/Notification.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/loader/include/Geode/ui/Notification.hpp b/loader/include/Geode/ui/Notification.hpp index 12b775b06..4e780afe0 100644 --- a/loader/include/Geode/ui/Notification.hpp +++ b/loader/include/Geode/ui/Notification.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace geode { constexpr auto NOTIFICATION_DEFAULT_TIME = 1.8f; diff --git a/loader/src/ui/nodes/Notification.cpp b/loader/src/ui/nodes/Notification.cpp index d8045caa0..4b2bdfa36 100644 --- a/loader/src/ui/nodes/Notification.cpp +++ b/loader/src/ui/nodes/Notification.cpp @@ -2,6 +2,7 @@ #include #include #include +#include using namespace geode::prelude; From 79de2d4afe5dd33974539d4bd452afb196c92dc5 Mon Sep 17 00:00:00 2001 From: OmgRod <89850217+OmgRod@users.noreply.github.com> Date: Tue, 7 Apr 2026 19:01:16 +0100 Subject: [PATCH 3/3] fix notification queue --- loader/src/ui/nodes/Notification.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/loader/src/ui/nodes/Notification.cpp b/loader/src/ui/nodes/Notification.cpp index 4b2bdfa36..78f1fa0a0 100644 --- a/loader/src/ui/nodes/Notification.cpp +++ b/loader/src/ui/nodes/Notification.cpp @@ -77,10 +77,12 @@ void Notification::showNextNotification() { this->removeFromParent(); // remove self from front of queue and show next popup if it exists - s_queue.pop_front(); + if (!s_queue.empty()) { + s_queue.pop_front(); + } - if (s_queue.size() != 0) { - s_queue.at(0)->show(); + if (!s_queue.empty()) { + s_queue.front()->show(); } } @@ -200,9 +202,11 @@ void Notification::show() { s_queue.push_back(this); } + if (s_queue.empty()) return; + // if we're not the current notification, return - if (s_queue.at(0) != this) { - if (auto current = s_queue.at(0).data()) { + if (s_queue.front() != this) { + if (auto current = s_queue.front().data()) { current->maybeSkipForQueuedNotification(); } return;