summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/timeline/CommunitiesModel.cpp142
-rw-r--r--src/timeline/CommunitiesModel.h12
-rw-r--r--src/timeline/TimelineModel.cpp24
-rw-r--r--src/timeline/TimelineModel.h3
4 files changed, 107 insertions, 74 deletions
diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp
index 91f7d555..0d47c64d 100644
--- a/src/timeline/CommunitiesModel.cpp
+++ b/src/timeline/CommunitiesModel.cpp
@@ -18,15 +18,7 @@ CommunitiesModel::CommunitiesModel(QObject *parent)
   : QAbstractListModel(parent)
   , hiddenTagIds_{UserSettings::instance()->hiddenTags()}
   , mutedTagIds_{UserSettings::instance()->mutedTags()}
-{
-    connect(ChatPage::instance(), &ChatPage::unreadMessages, this, [this](int) {
-        // Simply updating every space is easier than tracking which ones need updated.
-        if (!spaces_.empty())
-            emit dataChanged(index(0, 0),
-                             index(spaces_.size() + tags_.size() + 1, 0),
-                             {Roles::UnreadMessages, Roles::HasLoudNotification});
-    });
-}
+{}
 
 QHash<int, QByteArray>
 CommunitiesModel::roleNames() const
@@ -92,17 +84,10 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
             return 0;
         case CommunitiesModel::Roles::Id:
             return "";
-        case CommunitiesModel::Roles::UnreadMessages: {
-            int total{0};
-            for (const auto &[id, info] : cache::getRoomInfo(cache::joinedRooms()))
-                total += info.notification_count;
-            return total;
-        }
+        case CommunitiesModel::Roles::UnreadMessages:
+            return (int)globalUnreads.notification_count;
         case CommunitiesModel::Roles::HasLoudNotification:
-            for (const auto &[id, info] : cache::getRoomInfo(cache::joinedRooms()))
-                if (info.highlight_count > 0)
-                    return true;
-            return false;
+            return globalUnreads.highlight_count > 0;
         }
     } else if (index.row() == 1) {
         switch (role) {
@@ -124,17 +109,10 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
             return 0;
         case CommunitiesModel::Roles::Id:
             return "dm";
-        case CommunitiesModel::Roles::UnreadMessages: {
-            int total{0};
-            for (const auto &[id, info] : cache::getRoomInfo(directMessages_))
-                total += info.notification_count;
-            return total;
-        }
+        case CommunitiesModel::Roles::UnreadMessages:
+            return (int)dmUnreads.notification_count;
         case CommunitiesModel::Roles::HasLoudNotification:
-            for (const auto &[id, info] : cache::getRoomInfo(directMessages_))
-                if (info.highlight_count > 0)
-                    return true;
-            return false;
+            return dmUnreads.highlight_count > 0;
         }
     } else if (index.row() - 2 < spaceOrder_.size()) {
         auto id = spaceOrder_.tree.at(index.row() - 2).id;
@@ -162,10 +140,20 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
             return spaceOrder_.tree.at(index.row() - 2).depth;
         case CommunitiesModel::Roles::Id:
             return "space:" + id;
-        case CommunitiesModel::Roles::UnreadMessages:
-            return utils::getChildNotificationsForSpace(id).first;
-        case CommunitiesModel::Roles::HasLoudNotification:
-            return utils::getChildNotificationsForSpace(id).second > 0;
+        case CommunitiesModel::Roles::UnreadMessages: {
+            int count = 0;
+            auto end  = spaceOrder_.lastChild(index.row() - 2);
+            for (int i = index.row() - 2; i <= end; i++)
+                count += spaceOrder_.tree[i].notificationCounts.notification_count;
+            return count;
+        }
+        case CommunitiesModel::Roles::HasLoudNotification: {
+            auto end = spaceOrder_.lastChild(index.row() - 2);
+            for (int i = index.row() - 2; i <= end; i++)
+                if (spaceOrder_.tree[i].notificationCounts.highlight_count > 0)
+                    return true;
+            return false;
+        }
         }
     } else if (index.row() - 2 < tags_.size() + spaceOrder_.size()) {
         auto tag = tags_.at(index.row() - 2 - spaceOrder_.size());
@@ -219,24 +207,10 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
             return 0;
         case CommunitiesModel::Roles::Id:
             return "tag:" + tag;
-        case CommunitiesModel::Roles::UnreadMessages: {
-            int total{0};
-            auto rooms{cache::joinedRooms()};
-            for (const auto &[roomid, info] : cache::getRoomInfo(rooms))
-                if (std::find(std::begin(info.tags), std::end(info.tags), tag.toStdString()) !=
-                    std::end(info.tags))
-                    total += info.notification_count;
-            return total;
-        }
-        case CommunitiesModel::Roles::HasLoudNotification: {
-            auto rooms{cache::joinedRooms()};
-            for (const auto &[roomid, info] : cache::getRoomInfo(rooms))
-                if (std::find(std::begin(info.tags), std::end(info.tags), tag.toStdString()) !=
-                    std::end(info.tags))
-                    if (info.highlight_count > 0)
-                        return true;
-            return false;
-        }
+        case CommunitiesModel::Roles::UnreadMessages:
+            return (int)tagNotificationCache.at(tag).notification_count;
+        case CommunitiesModel::Roles::HasLoudNotification:
+            return (int)tagNotificationCache.at(tag).highlight_count > 0;
         }
     }
     return QVariant();
@@ -438,6 +412,72 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
                   e)) {
                 tagsUpdated = true;
             }
+
+        auto roomId           = QString::fromStdString(roomid);
+        auto oldUnreads       = roomNotificationCache[roomId];
+        int notificationCDiff = -static_cast<int64_t>(oldUnreads.highlight_count) +
+                                static_cast<int64_t>(room.unread_notifications.highlight_count);
+        int highlightCDiff = -static_cast<int64_t>(oldUnreads.highlight_count) +
+                             static_cast<int64_t>(room.unread_notifications.highlight_count);
+        if (highlightCDiff || notificationCDiff) {
+            // bool hidden = hiddenTagIds_.contains(roomId);
+            globalUnreads.notification_count += notificationCDiff;
+            globalUnreads.highlight_count += highlightCDiff;
+            emit dataChanged(index(0),
+                             index(0),
+                             {
+                               UnreadMessages,
+                               HasLoudNotification,
+                             });
+            if (std::find(begin(directMessages_), end(directMessages_), roomid) !=
+                end(directMessages_)) {
+                dmUnreads.notification_count += notificationCDiff;
+                dmUnreads.highlight_count += highlightCDiff;
+                emit dataChanged(index(1),
+                                 index(1),
+                                 {
+                                   UnreadMessages,
+                                   HasLoudNotification,
+                                 });
+            }
+
+            auto spaces = cache::client()->getParentRoomIds(roomid);
+            auto tags   = cache::singleRoomInfo(roomid).tags;
+
+            for (const auto &t : tags) {
+                auto tagId = QString::fromStdString(t);
+                auto &tNs  = tagNotificationCache[tagId];
+                tNs.notification_count += notificationCDiff;
+                tNs.highlight_count += highlightCDiff;
+                int idx = tags_.indexOf(tagId) + 2 + spaceOrder_.size();
+                ;
+                emit dataChanged(index(idx),
+                                 index(idx),
+                                 {
+                                   UnreadMessages,
+                                   HasLoudNotification,
+                                 });
+            }
+
+            for (const auto &s : spaces) {
+                auto spaceId = QString::fromStdString(s);
+
+                for (int i = 0; i < spaceOrder_.size(); i++) {
+                    spaceOrder_.tree[i].notificationCounts.notification_count += notificationCDiff;
+                    spaceOrder_.tree[i].notificationCounts.highlight_count += highlightCDiff;
+
+                    int idx = i;
+                    do {
+                        emit dataChanged(index(idx + 2),
+                                         index(idx + 2),
+                                         {
+                                           UnreadMessages,
+                                           HasLoudNotification,
+                                         });
+                    } while (idx != -1);
+                }
+            }
+        }
     }
     for (const auto &[roomid, room] : sync_.rooms.leave) {
         (void)room;
diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h
index 5a659751..08269e21 100644
--- a/src/timeline/CommunitiesModel.h
+++ b/src/timeline/CommunitiesModel.h
@@ -22,7 +22,7 @@ class FilteredCommunitiesModel : public QSortFilterProxyModel
     Q_OBJECT
 
 public:
-    FilteredCommunitiesModel(CommunitiesModel *model, QObject *parent = nullptr);
+    explicit FilteredCommunitiesModel(CommunitiesModel *model, QObject *parent = nullptr);
     bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
     bool filterAcceptsRow(int sourceRow, const QModelIndex &) const override;
 };
@@ -59,7 +59,10 @@ public:
         struct Elem
         {
             QString id;
-            int depth      = 0;
+            int depth = 0;
+
+            mtx::responses::UnreadNotifications notificationCounts = {0, 0};
+
             bool collapsed = false;
         };
 
@@ -160,5 +163,10 @@ private:
     std::map<QString, RoomInfo> spaces_;
     std::vector<std::string> directMessages_;
 
+    std::unordered_map<QString, mtx::responses::UnreadNotifications> roomNotificationCache;
+    std::unordered_map<QString, mtx::responses::UnreadNotifications> tagNotificationCache;
+    mtx::responses::UnreadNotifications globalUnreads{};
+    mtx::responses::UnreadNotifications dmUnreads{};
+
     friend class FilteredCommunitiesModel;
 };
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index db56ac52..9b48a878 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -364,25 +364,11 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
 {
     this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
 
-    auto roomInfo  = cache::singleRoomInfo(room_id_.toStdString());
-    this->isSpace_ = roomInfo.is_space;
-    this->notification_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
-    // needs to be
-    connect(this, &TimelineModel::roomNameChanged, this, &TimelineModel::plainRoomNameChanged);
-
-    if (isSpace_)
-        connect(ChatPage::instance(), &ChatPage::unreadMessages, this, [this](int) {
-            auto temp{utils::getChildNotificationsForSpace(room_id_)};
-            notification_count = temp.first;
-            highlight_count    = temp.second;
-            emit notificationsChanged();
-        });
+    auto roomInfo            = cache::singleRoomInfo(room_id_.toStdString());
+    this->isSpace_           = roomInfo.is_space;
+    this->notification_count = roomInfo.notification_count;
+    this->highlight_count    = roomInfo.highlight_count;
+    lastMessage_.timestamp   = roomInfo.approximate_last_modification_ts;
 
     connect(
       this,
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 6d424981..47fd27f1 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -182,7 +182,7 @@ class TimelineModel : public QAbstractListModel
       bool paginationInProgress READ paginationInProgress NOTIFY paginationInProgressChanged)
     Q_PROPERTY(QString roomId READ roomId CONSTANT)
     Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
-    Q_PROPERTY(QString plainRoomName READ plainRoomName NOTIFY plainRoomNameChanged)
+    Q_PROPERTY(QString plainRoomName READ plainRoomName NOTIFY roomNameChanged)
     Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged)
     Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
     Q_PROPERTY(QStringList pinnedMessages READ pinnedMessages NOTIFY pinnedMessagesChanged)
@@ -429,7 +429,6 @@ signals:
     void encryptionChanged();
     void trustlevelChanged();
     void roomNameChanged();
-    void plainRoomNameChanged();
     void roomTopicChanged();
     void pinnedMessagesChanged();
     void widgetLinksChanged();