diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml
index ec9ef940..ca63bffd 100644
--- a/resources/qml/CommunitiesList.qml
+++ b/resources/qml/CommunitiesList.qml
@@ -71,30 +71,20 @@ Page {
property color unimportantText: Nheko.colors.buttonText
property color bubbleBackground: Nheko.colors.highlight
property color bubbleText: Nheko.colors.highlightedText
- required property string avatarUrl
- required property string displayName
- required property string tooltip
- required property bool collapsed
- required property bool collapsible
- required property bool hidden
- required property int depth
- required property string id
- required property int unreadMessages
- required property bool hasLoudNotification
- required property bool muted
+ required property var model
height: avatarSize + 2 * Nheko.paddingMedium
width: ListView.view.width
state: "normal"
ToolTip.visible: hovered && collapsed
- ToolTip.text: communityItem.tooltip
+ ToolTip.text: model.tooltip
ToolTip.delay: Nheko.tooltipDelay
- onClicked: Communities.setCurrentTagId(communityItem.id)
- onPressAndHold: communityContextMenu.show(communityItem.id, communityItem.hidden, communityItem.muted)
+ onClicked: Communities.setCurrentTagId(model.id)
+ onPressAndHold: communityContextMenu.show(model.id, model.hidden, model.muted)
states: [
State {
name: "highlight"
- when: (communityItem.hovered || communityItem.hidden) && !(Communities.currentTagId === communityItem.id)
+ when: (communityItem.hovered || model.hidden) && !(Communities.currentTagId === model.id)
PropertyChanges {
target: communityItem
@@ -108,7 +98,7 @@ Page {
},
State {
name: "selected"
- when: Communities.currentTagId == communityItem.id
+ when: Communities.currentTagId == model.id
PropertyChanges {
target: communityItem
@@ -127,7 +117,7 @@ Page {
TapHandler {
acceptedButtons: Qt.RightButton
- onSingleTapped: communityContextMenu.show(communityItem.id, communityItem.hidden, communityItem.muted)
+ onSingleTapped: communityContextMenu.show(model.id, model.hidden, model.muted)
gesturePolicy: TapHandler.ReleaseWithinBounds
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus | PointerDevice.TouchPad
}
@@ -139,27 +129,27 @@ Page {
spacing: Nheko.paddingMedium
anchors.fill: parent
anchors.margins: Nheko.paddingMedium
- anchors.leftMargin: Nheko.paddingMedium + (communitySidebar.collapsed ? 0 : (fontMetrics.lineSpacing * communityItem.depth))
+ anchors.leftMargin: Nheko.paddingMedium + (communitySidebar.collapsed ? 0 : (fontMetrics.lineSpacing * model.depth))
ImageButton {
- visible: !communitySidebar.collapsed && communityItem.collapsible
+ visible: !communitySidebar.collapsed && model.collapsible
Layout.preferredHeight: fontMetrics.lineSpacing
Layout.preferredWidth: fontMetrics.lineSpacing
Layout.alignment: Qt.AlignVCenter
height: fontMetrics.lineSpacing
width: fontMetrics.lineSpacing
- image: communityItem.collapsed ? ":/icons/icons/ui/collapsed.svg" : ":/icons/icons/ui/expanded.svg"
+ image: model.collapsed ? ":/icons/icons/ui/collapsed.svg" : ":/icons/icons/ui/expanded.svg"
ToolTip.visible: hovered
ToolTip.delay: Nheko.tooltipDelay
- ToolTip.text: communityItem.collapsed ? qsTr("Expand") : qsTr("Collapse")
+ ToolTip.text: model.collapsed ? qsTr("Expand") : qsTr("Collapse")
hoverEnabled: true
- onClicked: communityItem.collapsed = !communityItem.collapsed
+ onClicked: model.collapsed = !model.collapsed
}
Item {
Layout.preferredWidth: fontMetrics.lineSpacing
- visible: !communitySidebar.collapsed && !communityItem.collapsible && Communities.containsSubspaces
+ visible: !communitySidebar.collapsed && !model.collapsible && Communities.containsSubspaces
}
Avatar {
@@ -170,22 +160,22 @@ Page {
height: avatarSize
width: avatarSize
url: {
- if (communityItem.avatarUrl.startsWith("mxc://"))
- return communityItem.avatarUrl.replace("mxc://", "image://MxcImage/");
+ if (model.avatarUrl.startsWith("mxc://"))
+ return model.avatarUrl.replace("mxc://", "image://MxcImage/");
else
- return "image://colorimage/" + communityItem.avatarUrl + "?" + communityItem.unimportantText;
+ return "image://colorimage/" + model.avatarUrl + "?" + communityItem.unimportantText;
}
- roomid: communityItem.id
- displayName: communityItem.displayName
+ roomid: model.id
+ displayName: model.displayName
color: communityItem.backgroundColor
NotificationBubble {
- notificationCount: communityItem.unreadMessages
- hasLoudNotification: communityItem.hasLoudNotification
+ notificationCount: model.unreadMessages
+ hasLoudNotification: model.hasLoudNotification
bubbleBackgroundColor: communityItem.bubbleBackground
bubbleTextColor: communityItem.bubbleText
font.pixelSize: fontMetrics.font.pixelSize * 0.6
- mayBeVisible: communitySidebar.collapsed && !communityItem.muted && Settings.spaceNotifications
+ mayBeVisible: communitySidebar.collapsed && !model.muted && Settings.spaceNotifications
anchors.right: avatar.right
anchors.bottom: avatar.bottom
anchors.margins: -Nheko.paddingSmall
@@ -199,7 +189,7 @@ Page {
color: communityItem.importantText
Layout.fillWidth: true
elideWidth: width
- fullText: communityItem.displayName
+ fullText: model.displayName
textFormat: Text.PlainText
}
@@ -208,11 +198,11 @@ Page {
}
NotificationBubble {
- notificationCount: communityItem.unreadMessages
- hasLoudNotification: communityItem.hasLoudNotification
+ notificationCount: model.unreadMessages
+ hasLoudNotification: model.hasLoudNotification
bubbleBackgroundColor: communityItem.bubbleBackground
bubbleTextColor: communityItem.bubbleText
- mayBeVisible: !communitySidebar.collapsed && !communityItem.muted && Settings.spaceNotifications
+ mayBeVisible: !communitySidebar.collapsed && !model.muted && Settings.spaceNotifications
Layout.alignment: Qt.AlignRight
Layout.leftMargin: Nheko.paddingSmall
}
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 3a90bd50..d98669e0 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -881,21 +881,3 @@ utils::markRoomAsDirect(QString roomid, std::vector<RoomMember> members)
});
});
}
-
-QPair<int, int>
-utils::getChildNotificationsForSpace(const QString &spaceId)
-{
- auto children = cache::getRoomInfo(cache::client()->getChildRoomIds(spaceId.toStdString()));
- QPair<int, int> retVal;
- for (const auto &[childId, child] : children) {
- 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 retVal;
-}
diff --git a/src/Utils.h b/src/Utils.h
index bdd56d55..0b6034ac 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -311,9 +311,4 @@ removeDirectFromRoom(QString roomid);
void
markRoomAsDirect(QString roomid, std::vector<RoomMember> members);
-
-//! 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 0d47c64d..c75f4265 100644
--- a/src/timeline/CommunitiesModel.cpp
+++ b/src/timeline/CommunitiesModel.cpp
@@ -208,9 +208,15 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
case CommunitiesModel::Roles::Id:
return "tag:" + tag;
case CommunitiesModel::Roles::UnreadMessages:
- return (int)tagNotificationCache.at(tag).notification_count;
+ if (auto it = tagNotificationCache.find(tag); it != tagNotificationCache.end())
+ return (int)it->second.notification_count;
+ else
+ return 0;
case CommunitiesModel::Roles::HasLoudNotification:
- return (int)tagNotificationCache.at(tag).highlight_count > 0;
+ if (auto it = tagNotificationCache.find(tag); it != tagNotificationCache.end())
+ return it->second.highlight_count > 0;
+ else
+ return 0;
}
}
return QVariant();
@@ -265,6 +271,21 @@ CommunitiesModel::initializeSidebar()
tags_.clear();
spaceOrder_.tree.clear();
spaces_.clear();
+ tagNotificationCache.clear();
+ globalUnreads.notification_count = {};
+ dmUnreads.notification_count = {};
+
+ auto e = cache::client()->getAccountData(mtx::events::EventType::Direct);
+ if (e) {
+ if (auto event =
+ std::get_if<mtx::events::AccountDataEvent<mtx::events::account_data::Direct>>(
+ &e.value())) {
+ directMessages_.clear();
+ for (const auto &[userId, roomIds] : event->content.user_to_rooms)
+ for (const auto &roomId : roomIds)
+ directMessages_.push_back(roomId);
+ }
+ }
std::set<std::string> ts;
@@ -284,6 +305,19 @@ CommunitiesModel::initializeSidebar()
}
}
}
+
+ for (const auto &t : it->tags) {
+ auto tagId = QString::fromStdString(t);
+ auto &tNs = tagNotificationCache[tagId];
+ tNs.notification_count += it->notification_count;
+ tNs.highlight_count += it->highlight_count;
+ }
+
+ auto &e = roomNotificationCache[it.key()];
+ e.highlight_count = it->highlight_count;
+ e.notification_count = it->notification_count;
+ globalUnreads.notification_count += it->notification_count;
+ globalUnreads.highlight_count += it->highlight_count;
}
// NOTE(Nico): We build a forrest from the Directed Cyclic(!) Graph of spaces. To do that we
@@ -319,6 +353,14 @@ CommunitiesModel::initializeSidebar()
spaceOrder_.restoreCollapsed();
+ for (auto &space : spaceOrder_.tree) {
+ for (const auto &c : cache::client()->getChildRoomIds(space.id.toStdString())) {
+ const auto &counts = roomNotificationCache[QString::fromStdString(c)];
+ space.notificationCounts.highlight_count += counts.highlight_count;
+ space.notificationCounts.notification_count += counts.notification_count;
+ }
+ }
+
endResetModel();
emit tagsChanged();
@@ -413,16 +455,21 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
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);
+ auto roomId = QString::fromStdString(roomid);
+ auto &oldUnreads = roomNotificationCache[roomId];
+ auto notificationCDiff = -static_cast<int64_t>(oldUnreads.notification_count) +
+ static_cast<int64_t>(room.unread_notifications.notification_count);
+ auto highlightCDiff = -static_cast<int64_t>(oldUnreads.highlight_count) +
+ static_cast<int64_t>(room.unread_notifications.highlight_count);
+
+ auto applyDiff = [notificationCDiff,
+ highlightCDiff](mtx::responses::UnreadNotifications &n) {
+ n.highlight_count = static_cast<int64_t>(n.highlight_count) + highlightCDiff;
+ n.notification_count = static_cast<int64_t>(n.notification_count) + notificationCDiff;
+ };
if (highlightCDiff || notificationCDiff) {
// bool hidden = hiddenTagIds_.contains(roomId);
- globalUnreads.notification_count += notificationCDiff;
- globalUnreads.highlight_count += highlightCDiff;
+ applyDiff(globalUnreads);
emit dataChanged(index(0),
index(0),
{
@@ -431,8 +478,7 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
});
if (std::find(begin(directMessages_), end(directMessages_), roomid) !=
end(directMessages_)) {
- dmUnreads.notification_count += notificationCDiff;
- dmUnreads.highlight_count += highlightCDiff;
+ applyDiff(dmUnreads);
emit dataChanged(index(1),
index(1),
{
@@ -446,11 +492,8 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
for (const auto &t : tags) {
auto tagId = QString::fromStdString(t);
- auto &tNs = tagNotificationCache[tagId];
- tNs.notification_count += notificationCDiff;
- tNs.highlight_count += highlightCDiff;
+ applyDiff(tagNotificationCache[tagId]);
int idx = tags_.indexOf(tagId) + 2 + spaceOrder_.size();
- ;
emit dataChanged(index(idx),
index(idx),
{
@@ -463,8 +506,10 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
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;
+ if (spaceOrder_.tree[i].id != spaceId)
+ continue;
+
+ applyDiff(spaceOrder_.tree[i].notificationCounts);
int idx = i;
do {
@@ -474,10 +519,13 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
UnreadMessages,
HasLoudNotification,
});
+ idx = spaceOrder_.parent(idx);
} while (idx != -1);
}
}
}
+
+ roomNotificationCache[roomId] = room.unread_notifications;
}
for (const auto &[roomid, room] : sync_.rooms.leave) {
(void)room;
diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp
index 3b46c053..1869d2e0 100644
--- a/src/timeline/RoomlistModel.cpp
+++ b/src/timeline/RoomlistModel.cpp
@@ -642,15 +642,18 @@ RoomlistModel::clear()
}
void
-RoomlistModel::joinPreview(QString roomid, QString parentSpace)
+RoomlistModel::joinPreview(QString roomid)
{
if (previewedRooms.contains(roomid)) {
- auto child = cache::client()->getStateEvent<mtx::events::state::space::Child>(
- parentSpace.toStdString(), roomid.toStdString());
- ChatPage::instance()->joinRoomVia(
- roomid.toStdString(),
- (child && child->content.via) ? child->content.via.value() : std::vector<std::string>{},
- false);
+ std::vector<std::string> vias;
+ auto parents = cache::client()->getParentRoomIds(roomid.toStdString());
+ for (const auto &p : parents) {
+ auto child = cache::client()->getStateEvent<mtx::events::state::space::Child>(
+ p, roomid.toStdString());
+ if (child && child->content.via)
+ vias.insert(vias.end(), child->content.via->begin(), child->content.via->end());
+ }
+ ChatPage::instance()->joinRoomVia(roomid.toStdString(), vias, false);
}
}
void
diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h
index cf2b45d8..61bf2e7c 100644
--- a/src/timeline/RoomlistModel.h
+++ b/src/timeline/RoomlistModel.h
@@ -105,7 +105,7 @@ public slots:
return -1;
}
- void joinPreview(QString roomid, QString parentSpace);
+ void joinPreview(QString roomid);
void acceptInvite(QString roomid);
void declineInvite(QString roomid);
void leave(QString roomid, QString reason = "");
@@ -169,11 +169,7 @@ public slots:
{
return mapFromSource(roomlistmodel->index(roomlistmodel->roomidToIndex(roomid))).row();
}
- void joinPreview(QString roomid)
- {
- roomlistmodel->joinPreview(roomid,
- filterType == FilterBy::Space ? filterStr : QLatin1String(""));
- }
+ void joinPreview(QString roomid) { roomlistmodel->joinPreview(roomid); }
void acceptInvite(QString roomid) { roomlistmodel->acceptInvite(roomid); }
void declineInvite(QString roomid) { roomlistmodel->declineInvite(roomid); }
void leave(QString roomid, QString reason = "") { roomlistmodel->leave(roomid, reason); }
|