summary refs log tree commit diff
path: root/src/timeline
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2022-07-14 01:26:48 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2022-07-14 01:26:48 +0200
commitaa63e50cea35926634f5c6af5598dd3950bee3d9 (patch)
tree6da789587167725b3e5cb54c90dc6a0db8aecaa2 /src/timeline
parentUse normal instead of recursive mutex (diff)
parentmake lint (diff)
downloadnheko-aa63e50cea35926634f5c6af5598dd3950bee3d9.tar.xz
Merge remote-tracking branch 'origin/perSpaceNotifs' into perSpaceNotifs
Diffstat (limited to 'src/timeline')
-rw-r--r--src/timeline/CommunitiesModel.cpp145
-rw-r--r--src/timeline/CommunitiesModel.h15
-rw-r--r--src/timeline/RoomlistModel.cpp5
-rw-r--r--src/timeline/TimelineModel.cpp20
4 files changed, 150 insertions, 35 deletions
diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp

index 4f650f49..91f7d555 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp
@@ -9,12 +9,24 @@ #include "Cache.h" #include "Cache_p.h" +#include "ChatPage.h" #include "Logging.h" #include "UserSettingsPage.h" +#include "Utils.h" 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 @@ -28,6 +40,9 @@ CommunitiesModel::roleNames() const {Hidden, "hidden"}, {Depth, "depth"}, {Id, "id"}, + {UnreadMessages, "unreadMessages"}, + {HasLoudNotification, "hasLoudNotification"}, + {Muted, "muted"}, }; } @@ -50,6 +65,13 @@ CommunitiesModel::setData(const QModelIndex &index, const QVariant &value, int r QVariant CommunitiesModel::data(const QModelIndex &index, int role) const { + if (role == CommunitiesModel::Roles::Muted) { + if (index.row() == 0) + return mutedTagIds_.contains(QStringLiteral("global")); + else + return mutedTagIds_.contains(data(index, CommunitiesModel::Roles::Id).toString()); + } + if (index.row() == 0) { switch (role) { case CommunitiesModel::Roles::AvatarUrl: @@ -70,6 +92,17 @@ 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::HasLoudNotification: + for (const auto &[id, info] : cache::getRoomInfo(cache::joinedRooms())) + if (info.highlight_count > 0) + return true; + return false; } } else if (index.row() == 1) { switch (role) { @@ -84,16 +117,27 @@ CommunitiesModel::data(const QModelIndex &index, int role) const case CommunitiesModel::Roles::Collapsible: return false; case CommunitiesModel::Roles::Hidden: - return hiddentTagIds_.contains(QStringLiteral("dm")); + return hiddenTagIds_.contains(QStringLiteral("dm")); case CommunitiesModel::Roles::Parent: return ""; case CommunitiesModel::Roles::Depth: 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::HasLoudNotification: + for (const auto &[id, info] : cache::getRoomInfo(directMessages_)) + if (info.highlight_count > 0) + return true; + return false; } } else if (index.row() - 2 < spaceOrder_.size()) { - auto id = spaceOrder_.tree.at(index.row() - 2).name; + auto id = spaceOrder_.tree.at(index.row() - 2).id; switch (role) { case CommunitiesModel::Roles::AvatarUrl: return QString::fromStdString(spaces_.at(id).avatar_url); @@ -107,10 +151,10 @@ CommunitiesModel::data(const QModelIndex &index, int role) const return idx != spaceOrder_.lastChild(idx); } case CommunitiesModel::Roles::Hidden: - return hiddentTagIds_.contains("space:" + id); + return hiddenTagIds_.contains("space:" + id); case CommunitiesModel::Roles::Parent: { if (auto p = spaceOrder_.parent(index.row() - 2); p >= 0) - return spaceOrder_.tree[p].name; + return spaceOrder_.tree[p].id; return ""; } @@ -118,6 +162,10 @@ 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; } } else if (index.row() - 2 < tags_.size() + spaceOrder_.size()) { auto tag = tags_.at(index.row() - 2 - spaceOrder_.size()); @@ -160,7 +208,7 @@ CommunitiesModel::data(const QModelIndex &index, int role) const switch (role) { case CommunitiesModel::Roles::Hidden: - return hiddentTagIds_.contains("tag:" + tag); + return hiddenTagIds_.contains("tag:" + tag); case CommunitiesModel::Roles::Collapsed: return true; case CommunitiesModel::Roles::Collapsible: @@ -171,6 +219,24 @@ 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; + } } } return QVariant(); @@ -277,8 +343,8 @@ CommunitiesModel::initializeSidebar() for (const auto &t : ts) tags_.push_back(QString::fromStdString(t)); - hiddentTagIds_ = UserSettings::instance()->hiddenTags(); spaceOrder_.restoreCollapsed(); + endResetModel(); emit tagsChanged(); @@ -298,12 +364,12 @@ CommunitiesModel::FlatTree::storeCollapsed() for (const auto &e : tree) { if (e.depth > depth) { - current.push_back(e.name); + current.push_back(e.id); } else if (e.depth == depth) { - current.back() = e.name; + current.back() = e.id; } else { current.pop_back(); - current.back() = e.name; + current.back() = e.id; } if (e.collapsed) @@ -323,12 +389,12 @@ CommunitiesModel::FlatTree::restoreCollapsed() for (auto &e : tree) { if (e.depth > depth) { - current.push_back(e.name); + current.push_back(e.id); } else if (e.depth == depth) { - current.back() = e.name; + current.back() = e.id; } else { current.pop_back(); - current.back() = e.name; + current.back() = e.id; } if (elements.contains(current)) @@ -353,7 +419,6 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_) bool tagsUpdated = false; for (const auto &[roomid, room] : sync_.rooms.join) { - (void)roomid; for (const auto &e : room.account_data.events) if (std::holds_alternative< mtx::events::AccountDataEvent<mtx::events::account_data::Tags>>(e)) { @@ -380,8 +445,12 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_) tagsUpdated = true; } for (const auto &e : sync_.account_data.events) { - if (std::holds_alternative< - mtx::events::AccountDataEvent<mtx::events::account_data::Direct>>(e)) { + if (auto event = + std::get_if<mtx::events::AccountDataEvent<mtx::events::account_data::Direct>>(&e)) { + directMessages_.clear(); + for (const auto &[userId, roomIds] : event->content.user_to_rooms) + for (const auto &roomId : roomIds) + directMessages_.push_back(roomId); tagsUpdated = true; break; } @@ -392,7 +461,7 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_) } void -CommunitiesModel::setCurrentTagId(QString tagId) +CommunitiesModel::setCurrentTagId(const QString &tagId) { if (tagId.startsWith(QLatin1String("tag:"))) { auto tag = tagId.mid(4); @@ -406,7 +475,7 @@ CommunitiesModel::setCurrentTagId(QString tagId) } else if (tagId.startsWith(QLatin1String("space:"))) { auto tag = tagId.mid(6); for (const auto &t : spaceOrder_.tree) { - if (t.name == tag) { + if (t.id == tag) { this->currentTagId_ = tagId; emit currentTagIdChanged(currentTagId_); return; @@ -425,13 +494,11 @@ CommunitiesModel::setCurrentTagId(QString tagId) void CommunitiesModel::toggleTagId(QString tagId) { - if (hiddentTagIds_.contains(tagId)) { - hiddentTagIds_.removeOne(tagId); - UserSettings::instance()->setHiddenTags(hiddentTagIds_); - } else { - hiddentTagIds_.push_back(tagId); - UserSettings::instance()->setHiddenTags(hiddentTagIds_); - } + if (hiddenTagIds_.contains(tagId)) + hiddenTagIds_.removeOne(tagId); + else + hiddenTagIds_.push_back(tagId); + UserSettings::instance()->setHiddenTags(hiddenTagIds_); if (tagId.startsWith(QLatin1String("tag:"))) { auto idx = tags_.indexOf(tagId.mid(4)); @@ -449,6 +516,34 @@ CommunitiesModel::toggleTagId(QString tagId) emit hiddenTagsChanged(); } +void +CommunitiesModel::toggleTagMute(QString tagId) +{ + if (tagId.isEmpty()) + tagId = QStringLiteral("global"); + + if (mutedTagIds_.contains(tagId)) + mutedTagIds_.removeOne(tagId); + else + mutedTagIds_.push_back(tagId); + UserSettings::instance()->setMutedTags(mutedTagIds_); + + if (tagId.startsWith(QLatin1String("tag:"))) { + auto idx = tags_.indexOf(tagId.mid(4)); + if (idx != -1) + emit dataChanged(index(idx + 1 + spaceOrder_.size()), + index(idx + 1 + spaceOrder_.size())); + } else if (tagId.startsWith(QLatin1String("space:"))) { + auto idx = spaceOrder_.indexOf(tagId.mid(6)); + if (idx != -1) + emit dataChanged(index(idx + 1), index(idx + 1)); + } else if (tagId == QLatin1String("dm")) { + emit dataChanged(index(1), index(1)); + } else if (tagId == QLatin1String("global")) { + emit dataChanged(index(0), index(0)); + } +} + FilteredCommunitiesModel::FilteredCommunitiesModel(CommunitiesModel *model, QObject *parent) : QSortFilterProxyModel(parent) { diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h
index 5da7d1bd..5a659751 100644 --- a/src/timeline/CommunitiesModel.h +++ b/src/timeline/CommunitiesModel.h
@@ -48,13 +48,17 @@ public: Parent, Depth, Id, + UnreadMessages, + HasLoudNotification, + Muted, + IsDirect, }; struct FlatTree { struct Elem { - QString name; + QString id; int depth = 0; bool collapsed = false; }; @@ -65,7 +69,7 @@ public: int indexOf(const QString &s) const { for (int i = 0; i < size(); i++) - if (tree[i].name == s) + if (tree[i].id == s) return i; return -1; } @@ -121,7 +125,7 @@ public slots: void sync(const mtx::responses::Sync &sync_); void clear(); QString currentTagId() const { return currentTagId_; } - void setCurrentTagId(QString tagId); + void setCurrentTagId(const QString &tagId); void resetCurrentTagId() { currentTagId_.clear(); @@ -138,6 +142,7 @@ public slots: return tagsWD; } void toggleTagId(QString tagId); + void toggleTagMute(QString tagId); FilteredCommunitiesModel *filtered() { return new FilteredCommunitiesModel(this, this); } signals: @@ -149,9 +154,11 @@ signals: private: QStringList tags_; QString currentTagId_; - QStringList hiddentTagIds_; + QStringList hiddenTagIds_; + QStringList mutedTagIds_; FlatTree spaceOrder_; std::map<QString, RoomInfo> spaces_; + std::vector<std::string> directMessages_; friend class FilteredCommunitiesModel; }; diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp
index 1cf16243..3b46c053 100644 --- a/src/timeline/RoomlistModel.cpp +++ b/src/timeline/RoomlistModel.cpp
@@ -330,10 +330,13 @@ RoomlistModel::addRoom(const QString &room_id, bool suppressInsertNotification) Qt::DisplayRole, }); + if (getRoomById(room_id)->isSpace()) + return; // no need to update space notifications + int total_unread_msgs = 0; for (const auto &room : qAsConst(models)) { - if (!room.isNull()) + if (!room.isNull() && !room->isSpace()) total_unread_msgs += room->notificationCount(); } diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 767fdaa2..db56ac52 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp
@@ -364,16 +364,26 @@ 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 = roomInfo.notification_count; - this->highlight_count = roomInfo.highlight_count; - lastMessage_.timestamp = roomInfo.approximate_last_modification_ts; + 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(); + }); + connect( this, &TimelineModel::redactionFailed,