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();
|