This commit is contained in:
Nicolas Werner 2022-07-15 16:19:06 +02:00
parent aa63e50cea
commit f76fd4ca83
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
4 changed files with 107 additions and 74 deletions

View file

@ -18,15 +18,7 @@ CommunitiesModel::CommunitiesModel(QObject *parent)
: QAbstractListModel(parent) : QAbstractListModel(parent)
, hiddenTagIds_{UserSettings::instance()->hiddenTags()} , hiddenTagIds_{UserSettings::instance()->hiddenTags()}
, mutedTagIds_{UserSettings::instance()->mutedTags()} , 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> QHash<int, QByteArray>
CommunitiesModel::roleNames() const CommunitiesModel::roleNames() const
@ -92,17 +84,10 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
return 0; return 0;
case CommunitiesModel::Roles::Id: case CommunitiesModel::Roles::Id:
return ""; return "";
case CommunitiesModel::Roles::UnreadMessages: { case CommunitiesModel::Roles::UnreadMessages:
int total{0}; return (int)globalUnreads.notification_count;
for (const auto &[id, info] : cache::getRoomInfo(cache::joinedRooms()))
total += info.notification_count;
return total;
}
case CommunitiesModel::Roles::HasLoudNotification: case CommunitiesModel::Roles::HasLoudNotification:
for (const auto &[id, info] : cache::getRoomInfo(cache::joinedRooms())) return globalUnreads.highlight_count > 0;
if (info.highlight_count > 0)
return true;
return false;
} }
} else if (index.row() == 1) { } else if (index.row() == 1) {
switch (role) { switch (role) {
@ -124,17 +109,10 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
return 0; return 0;
case CommunitiesModel::Roles::Id: case CommunitiesModel::Roles::Id:
return "dm"; return "dm";
case CommunitiesModel::Roles::UnreadMessages: { case CommunitiesModel::Roles::UnreadMessages:
int total{0}; return (int)dmUnreads.notification_count;
for (const auto &[id, info] : cache::getRoomInfo(directMessages_))
total += info.notification_count;
return total;
}
case CommunitiesModel::Roles::HasLoudNotification: case CommunitiesModel::Roles::HasLoudNotification:
for (const auto &[id, info] : cache::getRoomInfo(directMessages_)) return dmUnreads.highlight_count > 0;
if (info.highlight_count > 0)
return true;
return false;
} }
} else if (index.row() - 2 < spaceOrder_.size()) { } else if (index.row() - 2 < spaceOrder_.size()) {
auto id = spaceOrder_.tree.at(index.row() - 2).id; 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; return spaceOrder_.tree.at(index.row() - 2).depth;
case CommunitiesModel::Roles::Id: case CommunitiesModel::Roles::Id:
return "space:" + id; return "space:" + id;
case CommunitiesModel::Roles::UnreadMessages: case CommunitiesModel::Roles::UnreadMessages: {
return utils::getChildNotificationsForSpace(id).first; int count = 0;
case CommunitiesModel::Roles::HasLoudNotification: auto end = spaceOrder_.lastChild(index.row() - 2);
return utils::getChildNotificationsForSpace(id).second > 0; 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()) { } else if (index.row() - 2 < tags_.size() + spaceOrder_.size()) {
auto tag = tags_.at(index.row() - 2 - 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; return 0;
case CommunitiesModel::Roles::Id: case CommunitiesModel::Roles::Id:
return "tag:" + tag; return "tag:" + tag;
case CommunitiesModel::Roles::UnreadMessages: { case CommunitiesModel::Roles::UnreadMessages:
int total{0}; return (int)tagNotificationCache.at(tag).notification_count;
auto rooms{cache::joinedRooms()}; case CommunitiesModel::Roles::HasLoudNotification:
for (const auto &[roomid, info] : cache::getRoomInfo(rooms)) return (int)tagNotificationCache.at(tag).highlight_count > 0;
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;
}
} }
} }
return QVariant(); return QVariant();
@ -438,6 +412,72 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
e)) { e)) {
tagsUpdated = true; 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) { for (const auto &[roomid, room] : sync_.rooms.leave) {
(void)room; (void)room;

View file

@ -22,7 +22,7 @@ class FilteredCommunitiesModel : public QSortFilterProxyModel
Q_OBJECT Q_OBJECT
public: 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 lessThan(const QModelIndex &left, const QModelIndex &right) const override;
bool filterAcceptsRow(int sourceRow, const QModelIndex &) const override; bool filterAcceptsRow(int sourceRow, const QModelIndex &) const override;
}; };
@ -59,7 +59,10 @@ public:
struct Elem struct Elem
{ {
QString id; QString id;
int depth = 0; int depth = 0;
mtx::responses::UnreadNotifications notificationCounts = {0, 0};
bool collapsed = false; bool collapsed = false;
}; };
@ -160,5 +163,10 @@ private:
std::map<QString, RoomInfo> spaces_; std::map<QString, RoomInfo> spaces_;
std::vector<std::string> directMessages_; 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; friend class FilteredCommunitiesModel;
}; };

View file

@ -364,25 +364,11 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
{ {
this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString()); this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
auto roomInfo = cache::singleRoomInfo(room_id_.toStdString()); auto roomInfo = cache::singleRoomInfo(room_id_.toStdString());
this->isSpace_ = roomInfo.is_space; this->isSpace_ = roomInfo.is_space;
this->notification_count = this->notification_count = roomInfo.notification_count;
isSpace_ ? utils::getChildNotificationsForSpace(room_id_).first : roomInfo.notification_count; this->highlight_count = roomInfo.highlight_count;
this->highlight_count = lastMessage_.timestamp = roomInfo.approximate_last_modification_ts;
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();
});
connect( connect(
this, this,

View file

@ -182,7 +182,7 @@ class TimelineModel : public QAbstractListModel
bool paginationInProgress READ paginationInProgress NOTIFY paginationInProgressChanged) bool paginationInProgress READ paginationInProgress NOTIFY paginationInProgressChanged)
Q_PROPERTY(QString roomId READ roomId CONSTANT) Q_PROPERTY(QString roomId READ roomId CONSTANT)
Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged) 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 roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged)
Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged) Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
Q_PROPERTY(QStringList pinnedMessages READ pinnedMessages NOTIFY pinnedMessagesChanged) Q_PROPERTY(QStringList pinnedMessages READ pinnedMessages NOTIFY pinnedMessagesChanged)
@ -429,7 +429,6 @@ signals:
void encryptionChanged(); void encryptionChanged();
void trustlevelChanged(); void trustlevelChanged();
void roomNameChanged(); void roomNameChanged();
void plainRoomNameChanged();
void roomTopicChanged(); void roomTopicChanged();
void pinnedMessagesChanged(); void pinnedMessagesChanged();
void widgetLinksChanged(); void widgetLinksChanged();