From e446e3d6792ff6a1664934b24e19fc80ffbbd22e Mon Sep 17 00:00:00 2001
From: Loren Burkholder <computersemiexpert@outlook.com>
Date: Wed, 20 Apr 2022 21:30:16 -0400
Subject: [PATCH] Add loud notifications for spaces

---
 resources/qml/CommunitiesList.qml |  8 ++++----
 src/Utils.cpp                     | 18 +++++++++++-------
 src/Utils.h                       |  4 +++-
 src/timeline/CommunitiesModel.cpp |  8 +++++++-
 src/timeline/CommunitiesModel.h   |  1 +
 src/timeline/TimelineModel.cpp    |  9 ++++++---
 6 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml
index f5f20a91d..371e347ea 100644
--- a/resources/qml/CommunitiesList.qml
+++ b/resources/qml/CommunitiesList.qml
@@ -164,7 +164,7 @@ Page {
                         height: collapsedNotificationBubbleText.height + Nheko.paddingMedium
                         width: Math.max(collapsedNotificationBubbleText.width, height)
                         radius: height / 2
-                        color: /*hasLoudNotification ? Nheko.theme.red :*/ communityItem.bubbleBackground
+                        color: model.hasLoudNotification ? Nheko.theme.red : communityItem.bubbleBackground
                         ToolTip.text: model.unreadMessages
                         ToolTip.delay: Nheko.tooltipDelay
                         ToolTip.visible: collapsedNotificationBubbleHover.hovered && (model.unreadMessages > 9999)
@@ -178,7 +178,7 @@ Page {
                             width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height)
                             font.bold: true
                             font.pixelSize: fontMetrics.font.pixelSize * 0.6
-                            color: /*hasLoudNotification ? "white" :*/ communityItem.bubbleText
+                            color: model.hasLoudNotification ? "white" : communityItem.bubbleText
                             text: model.unreadMessages > 9999 ? "9999+" : model.unreadMessages
 
                             HoverHandler {
@@ -214,7 +214,7 @@ Page {
                     height: notificationBubbleText.height + Nheko.paddingMedium
                     Layout.preferredWidth: Math.max(notificationBubbleText.width, height)
                     radius: height / 2
-                    color: /*hasLoudNotification ? Nheko.theme.red :*/ communityItem.bubbleBackground
+                    color: model.hasLoudNotification ? Nheko.theme.red : communityItem.bubbleBackground
                     ToolTip.text: model.unreadMessages
                     ToolTip.delay: Nheko.tooltipDelay
                     ToolTip.visible: notificationBubbleHover.hovered && (model.unreadMessages > 9999)
@@ -228,7 +228,7 @@ Page {
                         width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height)
                         font.bold: true
                         font.pixelSize: fontMetrics.font.pixelSize * 0.8
-                        color: /*hasLoudNotification ? "white" :*/ communityItem.bubbleText
+                        color: model.hasLoudNotification ? "white" : communityItem.bubbleText
                         text: model.unreadMessages > 9999 ? "9999+" : model.unreadMessages
 
                         HoverHandler {
diff --git a/src/Utils.cpp b/src/Utils.cpp
index aa36d3d99..3a90bd505 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -882,16 +882,20 @@ utils::markRoomAsDirect(QString roomid, std::vector<RoomMember> members)
       });
 }
 
-int
+QPair<int, int>
 utils::getChildNotificationsForSpace(const QString &spaceId)
 {
     auto children = cache::getRoomInfo(cache::client()->getChildRoomIds(spaceId.toStdString()));
-    int total{0};
+    QPair<int, int> retVal;
     for (const auto &[childId, child] : children) {
-        if (child.is_space)
-            total += utils::getChildNotificationsForSpace(childId);
-        else
-            total += child.notification_count;
+        if (child.is_space) {
+            auto temp{utils::getChildNotificationsForSpace(childId)};
+            retVal.first += temp.first;
+            retVal.second += temp.second;
+        } else {
+            retVal.first += child.notification_count;
+            retVal.second += child.highlight_count;
+        }
     }
-    return total;
+    return retVal;
 }
diff --git a/src/Utils.h b/src/Utils.h
index c20544f2e..bdd56d55f 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -312,6 +312,8 @@ removeDirectFromRoom(QString roomid);
 void
 markRoomAsDirect(QString roomid, std::vector<RoomMember> members);
 
-int
+//! Returns a pair of integers representing the unread notifications in a space and how many of them
+//! are loud notifications, respectively.
+QPair<int, int>
 getChildNotificationsForSpace(const QString &spaceId);
 }
diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp
index 724a6e60a..ccc0adfef 100644
--- a/src/timeline/CommunitiesModel.cpp
+++ b/src/timeline/CommunitiesModel.cpp
@@ -37,6 +37,7 @@ CommunitiesModel::roleNames() const
       {Depth, "depth"},
       {Id, "id"},
       {UnreadMessages, "unreadMessages"},
+      {HasLoudNotification, "hasLoudNotification"},
     };
 }
 
@@ -80,6 +81,7 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
         case CommunitiesModel::Roles::Id:
             return "";
         case CommunitiesModel::Roles::UnreadMessages:
+        case CommunitiesModel::Roles::HasLoudNotification:
             return 0;
         }
     } else if (index.row() == 1) {
@@ -103,6 +105,7 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
         case CommunitiesModel::Roles::Id:
             return "dm";
         case CommunitiesModel::Roles::UnreadMessages:
+        case CommunitiesModel::Roles::HasLoudNotification:
             return 0;
         }
     } else if (index.row() - 2 < spaceOrder_.size()) {
@@ -132,7 +135,9 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
         case CommunitiesModel::Roles::Id:
             return "space:" + id;
         case CommunitiesModel::Roles::UnreadMessages:
-            return utils::getChildNotificationsForSpace(id);
+            return utils::getChildNotificationsForSpace(id).first;
+        case CommunitiesModel::Roles::HasLoudNotification:
+            return utils::getChildNotificationsForSpace(id).second > 0;
         }
     } else if (index.row() - 2 < tags_.size() + spaceOrder_.size()) {
         auto tag = tags_.at(index.row() - 2 - spaceOrder_.size());
@@ -187,6 +192,7 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
         case CommunitiesModel::Roles::Id:
             return "tag:" + tag;
         case CommunitiesModel::Roles::UnreadMessages:
+        case CommunitiesModel::Roles::HasLoudNotification:
             return 0;
         }
     }
diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h
index b29a53854..7be989399 100644
--- a/src/timeline/CommunitiesModel.h
+++ b/src/timeline/CommunitiesModel.h
@@ -49,6 +49,7 @@ public:
         Depth,
         Id,
         UnreadMessages,
+        HasLoudNotification,
     };
 
     struct FlatTree
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 308d358b8..1a9f957bc 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -355,8 +355,9 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
     auto roomInfo  = cache::singleRoomInfo(room_id_.toStdString());
     this->isSpace_ = roomInfo.is_space;
     this->notification_count =
-      isSpace_ ? utils::getChildNotificationsForSpace(room_id_) : roomInfo.notification_count;
-    this->highlight_count  = roomInfo.highlight_count;
+      isSpace_ ? utils::getChildNotificationsForSpace(room_id_).first : roomInfo.notification_count;
+    this->highlight_count =
+      isSpace_ ? utils::getChildNotificationsForSpace(room_id_).second : roomInfo.highlight_count;
     lastMessage_.timestamp = roomInfo.approximate_last_modification_ts;
 
     // this connection will simplify adding the plainRoomNameChanged() signal everywhere that it
@@ -365,7 +366,9 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
 
     if (isSpace_)
         connect(ChatPage::instance(), &ChatPage::unreadMessages, this, [this](int) {
-            notification_count = utils::getChildNotificationsForSpace(room_id_);
+            auto temp{utils::getChildNotificationsForSpace(room_id_)};
+            notification_count = temp.first;
+            highlight_count    = temp.second;
             emit notificationsChanged();
         });
 
-- 
GitLab