From 2df2046d1dc5d3e4133f89f634efa6a1726a2f30 Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Tue, 12 Apr 2022 21:49:21 -0400 Subject: Display unread notifications for spaces --- resources/qml/CommunitiesList.qml | 70 +++++++++++++++++++++++++++++++++++++++ resources/qml/RoomList.qml | 3 -- 2 files changed, 70 insertions(+), 3 deletions(-) (limited to 'resources') diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index 61287789..f5f20a91 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -153,6 +153,42 @@ Page { roomid: model.id displayName: model.displayName color: communityItem.backgroundColor + + Rectangle { + id: collapsedNotificationBubble + + visible: model.unreadMessages > 0 && communitySidebar.collapsed + anchors.right: avatar.right + anchors.bottom: avatar.bottom + anchors.margins: -Nheko.paddingSmall + height: collapsedNotificationBubbleText.height + Nheko.paddingMedium + width: Math.max(collapsedNotificationBubbleText.width, height) + radius: height / 2 + color: /*hasLoudNotification ? Nheko.theme.red :*/ communityItem.bubbleBackground + ToolTip.text: model.unreadMessages + ToolTip.delay: Nheko.tooltipDelay + ToolTip.visible: collapsedNotificationBubbleHover.hovered && (model.unreadMessages > 9999) + + Label { + id: collapsedNotificationBubbleText + + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) + font.bold: true + font.pixelSize: fontMetrics.font.pixelSize * 0.6 + color: /*hasLoudNotification ? "white" :*/ communityItem.bubbleText + text: model.unreadMessages > 9999 ? "9999+" : model.unreadMessages + + HoverHandler { + id: collapsedNotificationBubbleHover + } + + } + + } + } ElidedLabel { @@ -169,6 +205,40 @@ Page { Layout.fillWidth: true } + Rectangle { + id: notificationBubble + + visible: model.unreadMessages > 0 && !communitySidebar.collapsed + Layout.alignment: Qt.AlignRight + Layout.leftMargin: Nheko.paddingSmall + height: notificationBubbleText.height + Nheko.paddingMedium + Layout.preferredWidth: Math.max(notificationBubbleText.width, height) + radius: height / 2 + color: /*hasLoudNotification ? Nheko.theme.red :*/ communityItem.bubbleBackground + ToolTip.text: model.unreadMessages + ToolTip.delay: Nheko.tooltipDelay + ToolTip.visible: notificationBubbleHover.hovered && (model.unreadMessages > 9999) + + Label { + id: notificationBubbleText + + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) + font.bold: true + font.pixelSize: fontMetrics.font.pixelSize * 0.8 + color: /*hasLoudNotification ? "white" :*/ communityItem.bubbleText + text: model.unreadMessages > 9999 ? "9999+" : model.unreadMessages + + HoverHandler { + id: notificationBubbleHover + } + + } + + } + } background: Rectangle { diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index f3509f06..910fc252 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -294,9 +294,6 @@ Page { anchors.margins: Nheko.paddingMedium Avatar { - // In the future we could show an online indicator by setting the userid for the avatar - //userid: Nheko.currentUser.userid - id: avatar enabled: false -- cgit 1.5.1 From 169384f0fa41cc8a52428f27bc3042dc849dd8c9 Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Tue, 19 Apr 2022 23:18:11 -0400 Subject: Add space notifications to room list --- resources/qml/RoomList.qml | 80 +++++++++++++++++++++++---------------- src/Utils.cpp | 15 ++++++++ src/Utils.h | 3 ++ src/timeline/CommunitiesModel.cpp | 17 +-------- src/timeline/CommunitiesModel.h | 2 - src/timeline/RoomlistModel.cpp | 5 ++- src/timeline/TimelineModel.cpp | 17 ++++++--- 7 files changed, 84 insertions(+), 55 deletions(-) (limited to 'resources') diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index 910fc252..126d82be 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -348,7 +348,45 @@ Page { height: avatar.height spacing: Nheko.paddingSmall + Component { + id: notificationBubble + + Rectangle { + visible: notificationCount > 0 + Layout.alignment: Qt.AlignRight + Layout.leftMargin: Nheko.paddingSmall + height: notificationBubbleText.height + Nheko.paddingMedium + width: Math.max(notificationBubbleText.width, height) + radius: height / 2 + color: hasLoudNotification ? Nheko.theme.red : roomItem.bubbleBackground + ToolTip.text: notificationCount + ToolTip.delay: Nheko.tooltipDelay + ToolTip.visible: notificationBubbleHover.hovered && (notificationCount > 9999) + + Label { + id: notificationBubbleText + + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) + font.bold: true + font.pixelSize: fontMetrics.font.pixelSize * 0.8 + color: hasLoudNotification ? "white" : roomItem.bubbleText + text: notificationCount > 9999 ? "9999+" : notificationCount + + HoverHandler { + id: notificationBubbleHover + } + + } + + } + } + RowLayout { + id: titleRow + Layout.alignment: Qt.AlignTop Layout.fillWidth: true spacing: Nheko.paddingSmall @@ -374,9 +412,16 @@ Page { text: time } + Loader { + sourceComponent: notificationBubble + active: isSpace + } + } RowLayout { + id: subtextRow + Layout.fillWidth: true spacing: 0 visible: !isSpace @@ -392,40 +437,11 @@ Page { Layout.fillWidth: true } - Rectangle { - id: notificationBubble - - visible: notificationCount > 0 - Layout.alignment: Qt.AlignRight - Layout.leftMargin: Nheko.paddingSmall - height: notificationBubbleText.height + Nheko.paddingMedium - Layout.preferredWidth: Math.max(notificationBubbleText.width, height) - radius: height / 2 - color: hasLoudNotification ? Nheko.theme.red : roomItem.bubbleBackground - ToolTip.text: notificationCount - ToolTip.delay: Nheko.tooltipDelay - ToolTip.visible: notificationBubbleHover.hovered && (notificationCount > 9999) - - Label { - id: notificationBubbleText - - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) - font.bold: true - font.pixelSize: fontMetrics.font.pixelSize * 0.8 - color: hasLoudNotification ? "white" : roomItem.bubbleText - text: notificationCount > 9999 ? "9999+" : notificationCount - - HoverHandler { - id: notificationBubbleHover - } - - } + Loader { + sourceComponent: notificationBubble + active: !isSpace } - } } diff --git a/src/Utils.cpp b/src/Utils.cpp index 0ac37d8e..aa36d3d9 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -27,6 +27,7 @@ #include #include "Cache.h" +#include "Cache_p.h" #include "Config.h" #include "EventAccessors.h" #include "Logging.h" @@ -880,3 +881,17 @@ utils::markRoomAsDirect(QString roomid, std::vector members) }); }); } + +int +utils::getChildNotificationsForSpace(const QString &spaceId) +{ + auto children = cache::getRoomInfo(cache::client()->getChildRoomIds(spaceId.toStdString())); + int total{0}; + for (const auto &[childId, child] : children) { + if (child.is_space) + total += utils::getChildNotificationsForSpace(childId); + else + total += child.notification_count; + } + return total; +} diff --git a/src/Utils.h b/src/Utils.h index 0b6034ac..c20544f2 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -311,4 +311,7 @@ removeDirectFromRoom(QString roomid); void markRoomAsDirect(QString roomid, std::vector members); + +int +getChildNotificationsForSpace(const QString &spaceId); } diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp index 116fa0a0..724a6e60 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp @@ -12,6 +12,7 @@ #include "ChatPage.h" #include "Logging.h" #include "UserSettingsPage.h" +#include "Utils.h" CommunitiesModel::CommunitiesModel(QObject *parent) : QAbstractListModel(parent) @@ -131,7 +132,7 @@ CommunitiesModel::data(const QModelIndex &index, int role) const case CommunitiesModel::Roles::Id: return "space:" + id; case CommunitiesModel::Roles::UnreadMessages: - return getChildNotifications(id); + return utils::getChildNotificationsForSpace(id); } } else if (index.row() - 2 < tags_.size() + spaceOrder_.size()) { auto tag = tags_.at(index.row() - 2 - spaceOrder_.size()); @@ -465,20 +466,6 @@ CommunitiesModel::toggleTagId(QString tagId) emit hiddenTagsChanged(); } -int -CommunitiesModel::getChildNotifications(const QString &space_id) const -{ - auto children = cache::getRoomInfo(cache::client()->getChildRoomIds(space_id.toStdString())); - int total{0}; - for (const auto &[child_id, child] : children) { - if (child.is_space) - total += getChildNotifications(child_id); - else - total += child.notification_count; - } - return total; -} - FilteredCommunitiesModel::FilteredCommunitiesModel(CommunitiesModel *model, QObject *parent) : QSortFilterProxyModel(parent) { diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h index 30980f00..b29a5385 100644 --- a/src/timeline/CommunitiesModel.h +++ b/src/timeline/CommunitiesModel.h @@ -148,8 +148,6 @@ signals: void containsSubspacesChanged(); private: - int getChildNotifications(const QString &space_id) const; - QStringList tags_; QString currentTagId_; QStringList hiddenTagIds_; 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 3fe4c07f..308d358b 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -352,16 +352,23 @@ 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_) : roomInfo.notification_count; + this->highlight_count = 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) { + notification_count = utils::getChildNotificationsForSpace(room_id_); + emit notificationsChanged(); + }); + connect( this, &TimelineModel::redactionFailed, -- cgit 1.5.1 From e446e3d6792ff6a1664934b24e19fc80ffbbd22e Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Wed, 20 Apr 2022 21:30:16 -0400 Subject: Add loud notifications for spaces --- resources/qml/CommunitiesList.qml | 8 ++++---- src/Utils.cpp | 18 +++++++++++------- src/Utils.h | 4 +++- src/timeline/CommunitiesModel.cpp | 8 +++++++- src/timeline/CommunitiesModel.h | 1 + src/timeline/TimelineModel.cpp | 9 ++++++--- 6 files changed, 32 insertions(+), 16 deletions(-) (limited to 'resources') diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index f5f20a91..371e347e 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -164,7 +164,7 @@ Page { height: collapsedNotificationBubbleText.height + Nheko.paddingMedium width: Math.max(collapsedNotificationBubbleText.width, height) radius: height / 2 - color: /*hasLoudNotification ? Nheko.theme.red :*/ communityItem.bubbleBackground + color: model.hasLoudNotification ? Nheko.theme.red : communityItem.bubbleBackground ToolTip.text: model.unreadMessages ToolTip.delay: Nheko.tooltipDelay ToolTip.visible: collapsedNotificationBubbleHover.hovered && (model.unreadMessages > 9999) @@ -178,7 +178,7 @@ Page { width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) font.bold: true font.pixelSize: fontMetrics.font.pixelSize * 0.6 - color: /*hasLoudNotification ? "white" :*/ communityItem.bubbleText + color: model.hasLoudNotification ? "white" : communityItem.bubbleText text: model.unreadMessages > 9999 ? "9999+" : model.unreadMessages HoverHandler { @@ -214,7 +214,7 @@ Page { height: notificationBubbleText.height + Nheko.paddingMedium Layout.preferredWidth: Math.max(notificationBubbleText.width, height) radius: height / 2 - color: /*hasLoudNotification ? Nheko.theme.red :*/ communityItem.bubbleBackground + color: model.hasLoudNotification ? Nheko.theme.red : communityItem.bubbleBackground ToolTip.text: model.unreadMessages ToolTip.delay: Nheko.tooltipDelay ToolTip.visible: notificationBubbleHover.hovered && (model.unreadMessages > 9999) @@ -228,7 +228,7 @@ Page { width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) font.bold: true font.pixelSize: fontMetrics.font.pixelSize * 0.8 - color: /*hasLoudNotification ? "white" :*/ communityItem.bubbleText + color: model.hasLoudNotification ? "white" : communityItem.bubbleText text: model.unreadMessages > 9999 ? "9999+" : model.unreadMessages HoverHandler { diff --git a/src/Utils.cpp b/src/Utils.cpp index aa36d3d9..3a90bd50 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -882,16 +882,20 @@ utils::markRoomAsDirect(QString roomid, std::vector members) }); } -int +QPair utils::getChildNotificationsForSpace(const QString &spaceId) { auto children = cache::getRoomInfo(cache::client()->getChildRoomIds(spaceId.toStdString())); - int total{0}; + QPair retVal; for (const auto &[childId, child] : children) { - if (child.is_space) - total += utils::getChildNotificationsForSpace(childId); - else - total += child.notification_count; + 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 total; + return retVal; } diff --git a/src/Utils.h b/src/Utils.h index c20544f2..bdd56d55 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -312,6 +312,8 @@ removeDirectFromRoom(QString roomid); void markRoomAsDirect(QString roomid, std::vector members); -int +//! Returns a pair of integers representing the unread notifications in a space and how many of them +//! are loud notifications, respectively. +QPair getChildNotificationsForSpace(const QString &spaceId); } diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp index 724a6e60..ccc0adfe 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp @@ -37,6 +37,7 @@ CommunitiesModel::roleNames() const {Depth, "depth"}, {Id, "id"}, {UnreadMessages, "unreadMessages"}, + {HasLoudNotification, "hasLoudNotification"}, }; } @@ -80,6 +81,7 @@ CommunitiesModel::data(const QModelIndex &index, int role) const case CommunitiesModel::Roles::Id: return ""; case CommunitiesModel::Roles::UnreadMessages: + case CommunitiesModel::Roles::HasLoudNotification: return 0; } } else if (index.row() == 1) { @@ -103,6 +105,7 @@ CommunitiesModel::data(const QModelIndex &index, int role) const case CommunitiesModel::Roles::Id: return "dm"; case CommunitiesModel::Roles::UnreadMessages: + case CommunitiesModel::Roles::HasLoudNotification: return 0; } } else if (index.row() - 2 < spaceOrder_.size()) { @@ -132,7 +135,9 @@ CommunitiesModel::data(const QModelIndex &index, int role) const case CommunitiesModel::Roles::Id: return "space:" + id; case CommunitiesModel::Roles::UnreadMessages: - return utils::getChildNotificationsForSpace(id); + 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()); @@ -187,6 +192,7 @@ CommunitiesModel::data(const QModelIndex &index, int role) const case CommunitiesModel::Roles::Id: return "tag:" + tag; case CommunitiesModel::Roles::UnreadMessages: + case CommunitiesModel::Roles::HasLoudNotification: return 0; } } diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h index b29a5385..7be98939 100644 --- a/src/timeline/CommunitiesModel.h +++ b/src/timeline/CommunitiesModel.h @@ -49,6 +49,7 @@ public: Depth, Id, UnreadMessages, + HasLoudNotification, }; struct FlatTree diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 308d358b..1a9f957b 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -355,8 +355,9 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj auto roomInfo = cache::singleRoomInfo(room_id_.toStdString()); this->isSpace_ = roomInfo.is_space; this->notification_count = - isSpace_ ? utils::getChildNotificationsForSpace(room_id_) : roomInfo.notification_count; - this->highlight_count = roomInfo.highlight_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 @@ -365,7 +366,9 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj if (isSpace_) connect(ChatPage::instance(), &ChatPage::unreadMessages, this, [this](int) { - notification_count = utils::getChildNotificationsForSpace(room_id_); + auto temp{utils::getChildNotificationsForSpace(room_id_)}; + notification_count = temp.first; + highlight_count = temp.second; emit notificationsChanged(); }); -- cgit 1.5.1 From 8ec0577807c8abd3e3a1cee33f2d1efcc56b4a58 Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Thu, 21 Apr 2022 18:26:14 -0400 Subject: Make the notification bubble its own component --- resources/qml/CommunitiesList.qml | 122 +++++++++--------------- resources/qml/components/NotificationBubble.qml | 42 ++++++++ resources/res.qrc | 1 + 3 files changed, 86 insertions(+), 79 deletions(-) create mode 100644 resources/qml/components/NotificationBubble.qml (limited to 'resources') diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index 371e347e..1775e5fd 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -3,6 +3,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +import "./components" import "./dialogs" import Qt.labs.platform 1.1 as Platform import QtQml 2.12 @@ -57,19 +58,29 @@ 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 height: avatarSize + 2 * Nheko.paddingMedium width: ListView.view.width state: "normal" ToolTip.visible: hovered && collapsed - ToolTip.text: model.tooltip + ToolTip.text: communityItem.tooltip ToolTip.delay: Nheko.tooltipDelay - onClicked: Communities.setCurrentTagId(model.id) - onPressAndHold: communityContextMenu.show(model.id) + onClicked: Communities.setCurrentTagId(communityItem.id) + onPressAndHold: communityContextMenu.show(communityItem.id) states: [ State { name: "highlight" - when: (communityItem.hovered || model.hidden) && !(Communities.currentTagId == model.id) + when: (communityItem.hovered || communityItem.hidden) && !(Communities.currentTagId === communityItem.id) PropertyChanges { target: communityItem @@ -83,7 +94,7 @@ Page { }, State { name: "selected" - when: Communities.currentTagId == model.id + when: Communities.currentTagId == communityItem.id PropertyChanges { target: communityItem @@ -102,7 +113,7 @@ Page { TapHandler { acceptedButtons: Qt.RightButton - onSingleTapped: communityContextMenu.show(model.id) + onSingleTapped: communityContextMenu.show(communityItem.id) gesturePolicy: TapHandler.ReleaseWithinBounds acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus | PointerDevice.TouchPad } @@ -114,27 +125,27 @@ Page { spacing: Nheko.paddingMedium anchors.fill: parent anchors.margins: Nheko.paddingMedium - anchors.leftMargin: Nheko.paddingMedium + (communitySidebar.collapsed ? 0 : (fontMetrics.lineSpacing * model.depth)) + anchors.leftMargin: Nheko.paddingMedium + (communitySidebar.collapsed ? 0 : (fontMetrics.lineSpacing * communityItem.depth)) ImageButton { - visible: !communitySidebar.collapsed && model.collapsible + visible: !communitySidebar.collapsed && communityItem.collapsible Layout.preferredHeight: fontMetrics.lineSpacing Layout.preferredWidth: fontMetrics.lineSpacing Layout.alignment: Qt.AlignVCenter height: fontMetrics.lineSpacing width: fontMetrics.lineSpacing - image: model.collapsed ? ":/icons/icons/ui/collapsed.svg" : ":/icons/icons/ui/expanded.svg" + image: communityItem.collapsed ? ":/icons/icons/ui/collapsed.svg" : ":/icons/icons/ui/expanded.svg" ToolTip.visible: hovered ToolTip.delay: Nheko.tooltipDelay - ToolTip.text: model.collapsed ? qsTr("Expand") : qsTr("Collapse") + ToolTip.text: communityItem.collapsed ? qsTr("Expand") : qsTr("Collapse") hoverEnabled: true - onClicked: model.collapsed = !model.collapsed + onClicked: communityItem.collapsed = !communityItem.collapsed } Item { Layout.preferredWidth: fontMetrics.lineSpacing - visible: !communitySidebar.collapsed && !model.collapsible && Communities.containsSubspaces + visible: !communitySidebar.collapsed && !communityItem.collapsible && Communities.containsSubspaces } Avatar { @@ -145,48 +156,25 @@ Page { height: avatarSize width: avatarSize url: { - if (model.avatarUrl.startsWith("mxc://")) - return model.avatarUrl.replace("mxc://", "image://MxcImage/"); + if (communityItem.avatarUrl.startsWith("mxc://")) + return communityItem.avatarUrl.replace("mxc://", "image://MxcImage/"); else - return "image://colorimage/" + model.avatarUrl + "?" + communityItem.unimportantText; + return "image://colorimage/" + communityItem.avatarUrl + "?" + communityItem.unimportantText; } - roomid: model.id - displayName: model.displayName + roomid: communityItem.id + displayName: communityItem.displayName color: communityItem.backgroundColor - Rectangle { - id: collapsedNotificationBubble - - visible: model.unreadMessages > 0 && communitySidebar.collapsed + NotificationBubble { + notificationCount: communityItem.unreadMessages + hasLoudNotification: communityItem.hasLoudNotification + bubbleBackgroundColor: communityItem.bubbleBackground + bubbleTextColor: communityItem.bubbleText + font.pixelSize: fontMetrics.font.pixelSize * 0.6 + mayBeVisible: communitySidebar.collapsed anchors.right: avatar.right anchors.bottom: avatar.bottom anchors.margins: -Nheko.paddingSmall - height: collapsedNotificationBubbleText.height + Nheko.paddingMedium - width: Math.max(collapsedNotificationBubbleText.width, height) - radius: height / 2 - color: model.hasLoudNotification ? Nheko.theme.red : communityItem.bubbleBackground - ToolTip.text: model.unreadMessages - ToolTip.delay: Nheko.tooltipDelay - ToolTip.visible: collapsedNotificationBubbleHover.hovered && (model.unreadMessages > 9999) - - Label { - id: collapsedNotificationBubbleText - - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) - font.bold: true - font.pixelSize: fontMetrics.font.pixelSize * 0.6 - color: model.hasLoudNotification ? "white" : communityItem.bubbleText - text: model.unreadMessages > 9999 ? "9999+" : model.unreadMessages - - HoverHandler { - id: collapsedNotificationBubbleHover - } - - } - } } @@ -197,7 +185,7 @@ Page { color: communityItem.importantText Layout.fillWidth: true elideWidth: width - fullText: model.displayName + fullText: communityItem.displayName textFormat: Text.PlainText } @@ -205,44 +193,20 @@ Page { Layout.fillWidth: true } - Rectangle { - id: notificationBubble - - visible: model.unreadMessages > 0 && !communitySidebar.collapsed + NotificationBubble { + notificationCount: communityItem.unreadMessages + hasLoudNotification: communityItem.hasLoudNotification + bubbleBackgroundColor: communityItem.bubbleBackground + bubbleTextColor: communityItem.bubbleText + mayBeVisible: !communitySidebar.collapsed Layout.alignment: Qt.AlignRight Layout.leftMargin: Nheko.paddingSmall - height: notificationBubbleText.height + Nheko.paddingMedium - Layout.preferredWidth: Math.max(notificationBubbleText.width, height) - radius: height / 2 - color: model.hasLoudNotification ? Nheko.theme.red : communityItem.bubbleBackground - ToolTip.text: model.unreadMessages - ToolTip.delay: Nheko.tooltipDelay - ToolTip.visible: notificationBubbleHover.hovered && (model.unreadMessages > 9999) - - Label { - id: notificationBubbleText - - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) - font.bold: true - font.pixelSize: fontMetrics.font.pixelSize * 0.8 - color: model.hasLoudNotification ? "white" : communityItem.bubbleText - text: model.unreadMessages > 9999 ? "9999+" : model.unreadMessages - - HoverHandler { - id: notificationBubbleHover - } - - } - } } background: Rectangle { - color: backgroundColor + color: communityItem.backgroundColor } } diff --git a/resources/qml/components/NotificationBubble.qml b/resources/qml/components/NotificationBubble.qml new file mode 100644 index 00000000..07dd76a8 --- /dev/null +++ b/resources/qml/components/NotificationBubble.qml @@ -0,0 +1,42 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import im.nheko 1.0 + +Rectangle { + id: bubbleRoot + + required property int notificationCount + required property bool hasLoudNotification + required property color bubbleBackgroundColor + required property color bubbleTextColor + property bool mayBeVisible: true + property alias font: notificationBubbleText.font + + visible: mayBeVisible && notificationCount > 0 + implicitHeight: notificationBubbleText.height + Nheko.paddingMedium + implicitWidth: Math.max(notificationBubbleText.width, height) + radius: height / 2 + color: hasLoudNotification ? Nheko.theme.red : bubbleBackgroundColor + ToolTip.text: notificationCount + ToolTip.delay: Nheko.tooltipDelay + ToolTip.visible: notificationBubbleHover.hovered && (notificationCount > 9999) + + Label { + id: notificationBubbleText + + anchors.centerIn: bubbleRoot + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + width: Math.max(implicitWidth + Nheko.paddingMedium, bubbleRoot.height) + font.bold: true + font.pixelSize: fontMetrics.font.pixelSize * 0.8 + color: bubbleRoot.hasLoudNotification ? "white" : bubbleRoot.bubbleTextColor + text: bubbleRoot.notificationCount > 9999 ? "9999+" : bubbleRoot.notificationCount + + HoverHandler { + id: notificationBubbleHover + } + + } + +} diff --git a/resources/res.qrc b/resources/res.qrc index 6e3023ea..94901b2b 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -182,6 +182,7 @@ qml/voip/PlaceCall.qml qml/voip/ScreenShare.qml qml/voip/VideoCall.qml + qml/components/NotificationBubble.qml media/ring.ogg -- cgit 1.5.1 From c2b6728955a74975cc3c01c40f49e70a35b65bd4 Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Thu, 21 Apr 2022 18:26:25 -0400 Subject: Add space notifs to room list --- resources/qml/RoomList.qml | 82 ++++++++++------------------------------------ 1 file changed, 18 insertions(+), 64 deletions(-) (limited to 'resources') diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index 126d82be..614abf92 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -3,6 +3,7 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +import "./components" import "./dialogs" import "./ui" import Qt.labs.platform 1.1 as Platform @@ -305,33 +306,17 @@ Page { userid: isDirect ? directChatOtherUserId : "" roomid: roomId - Rectangle { + NotificationBubble { id: collapsedNotificationBubble + notificationCount: roomItem.notificationCount + hasLoudNotification: roomItem.hasLoudNotification + bubbleBackgroundColor: roomItem.bubbleBackground + bubbleTextColor: roomItem.bubbleText anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: -Nheko.paddingSmall - visible: collapsed && notificationCount > 0 - enabled: false - Layout.alignment: Qt.AlignRight - height: fontMetrics.averageCharacterWidth * 3 - width: Math.max(collapsedBubbleText.width, height) - radius: height / 2 - color: hasLoudNotification ? Nheko.theme.red : roomItem.bubbleBackground - - Label { - id: collapsedBubbleText - - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) - font.bold: true - font.pixelSize: fontMetrics.font.pixelSize * 0.8 - color: hasLoudNotification ? "white" : roomItem.bubbleText - text: notificationCount > 9999 ? "9999+" : notificationCount - } - + mayBeVisible: collapsed } } @@ -348,40 +333,19 @@ Page { height: avatar.height spacing: Nheko.paddingSmall - Component { + NotificationBubble { id: notificationBubble - Rectangle { - visible: notificationCount > 0 - Layout.alignment: Qt.AlignRight - Layout.leftMargin: Nheko.paddingSmall - height: notificationBubbleText.height + Nheko.paddingMedium - width: Math.max(notificationBubbleText.width, height) - radius: height / 2 - color: hasLoudNotification ? Nheko.theme.red : roomItem.bubbleBackground - ToolTip.text: notificationCount - ToolTip.delay: Nheko.tooltipDelay - ToolTip.visible: notificationBubbleHover.hovered && (notificationCount > 9999) - - Label { - id: notificationBubbleText - - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: Math.max(implicitWidth + Nheko.paddingMedium, parent.height) - font.bold: true - font.pixelSize: fontMetrics.font.pixelSize * 0.8 - color: hasLoudNotification ? "white" : roomItem.bubbleText - text: notificationCount > 9999 ? "9999+" : notificationCount - - HoverHandler { - id: notificationBubbleHover - } - - } - - } + parent: isSpace ? titleRow : subtextRow + notificationCount: roomItem.notificationCount + hasLoudNotification: roomItem.hasLoudNotification + bubbleBackgroundColor: roomItem.bubbleBackground + bubbleTextColor: roomItem.bubbleText + Layout.alignment: Qt.AlignRight + Layout.leftMargin: Nheko.paddingSmall + Layout.preferredWidth: implicitWidth + Layout.preferredHeight: implicitHeight + mayBeVisible: !collapsed } RowLayout { @@ -412,11 +376,6 @@ Page { text: time } - Loader { - sourceComponent: notificationBubble - active: isSpace - } - } RowLayout { @@ -437,11 +396,6 @@ Page { Layout.fillWidth: true } - - Loader { - sourceComponent: notificationBubble - active: !isSpace - } } } -- cgit 1.5.1 From 863eaa1910e84c0657a718f880462e661c220528 Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Fri, 22 Apr 2022 20:34:15 -0400 Subject: Add space notification configuration --- resources/qml/CommunitiesList.qml | 27 ++++++++++++++++++-- resources/qml/RoomList.qml | 4 +-- src/UserSettingsPage.cpp | 52 ++++++++++++++++++++++++++++++++++++--- src/UserSettingsPage.h | 16 ++++++++++++ 4 files changed, 92 insertions(+), 7 deletions(-) (limited to 'resources') diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index 1775e5fd..62ac341a 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -171,7 +171,21 @@ Page { bubbleBackgroundColor: communityItem.bubbleBackground bubbleTextColor: communityItem.bubbleText font.pixelSize: fontMetrics.font.pixelSize * 0.6 - mayBeVisible: communitySidebar.collapsed + mayBeVisible: { + if (!communitySidebar.collapsed) + return false + else if (Settings.spaceNotifications === Settings.SpaceNotificationsOff) + return false + else if (Settings.spaceNotifications === Settings.SidebarHiddenRooms) + { + if (communityItem.hidden) + return true + else + return false + } + else + return true + } anchors.right: avatar.right anchors.bottom: avatar.bottom anchors.margins: -Nheko.paddingSmall @@ -198,7 +212,16 @@ Page { hasLoudNotification: communityItem.hasLoudNotification bubbleBackgroundColor: communityItem.bubbleBackground bubbleTextColor: communityItem.bubbleText - mayBeVisible: !communitySidebar.collapsed + mayBeVisible: { + if (communitySidebar.collapsed) + return false + else if (Settings.spaceNotification === Settings.SpaceNotificationsOff) + return false + else if ((Settings.spaceNotifications === Settings.SidebarHiddenRooms) && communityItem.hidden) + return true + else + return true + } Layout.alignment: Qt.AlignRight Layout.leftMargin: Nheko.paddingSmall } diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index 614abf92..b34a94a1 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -316,7 +316,7 @@ Page { anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: -Nheko.paddingSmall - mayBeVisible: collapsed + mayBeVisible: collapsed && (isSpace ? Settings.spaceNotifications === Settings.SidebarAndRoomlist : true) } } @@ -345,7 +345,7 @@ Page { Layout.leftMargin: Nheko.paddingSmall Layout.preferredWidth: implicitWidth Layout.preferredHeight: implicitHeight - mayBeVisible: !collapsed + mayBeVisible: !collapsed && (isSpace ? Settings.spaceNotifications === Settings.SidebarAndRoomlist : true) } RowLayout { diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index 666a03b4..c4cc339b 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -88,7 +88,15 @@ UserSettings::load(std::optional profile) openImageExternal_ = settings.value(QStringLiteral("user/open_image_external"), false).toBool(); openVideoExternal_ = settings.value(QStringLiteral("user/open_video_external"), false).toBool(); decryptSidebar_ = settings.value(QStringLiteral("user/decrypt_sidebar"), true).toBool(); - privacyScreen_ = settings.value(QStringLiteral("user/privacy_screen"), false).toBool(); + auto tempSpaceNotifs = settings.value(QStringLiteral("user/space_notifications"), QString{}) + .toString() + .toStdString(); + auto spaceNotifsValue = + QMetaEnum::fromType().keyToValue(tempSpaceNotifs.c_str()); + if (spaceNotifsValue < 0) + spaceNotifsValue = 0; + spaceNotifications_ = static_cast(spaceNotifsValue); + privacyScreen_ = settings.value(QStringLiteral("user/privacy_screen"), false).toBool(); privacyScreenTimeout_ = settings.value(QStringLiteral("user/privacy_screen_timeout"), 0).toInt(); exposeDBusApi_ = settings.value(QStringLiteral("user/expose_dbus_api"), false).toBool(); @@ -416,6 +424,16 @@ UserSettings::setDecryptSidebar(bool state) save(); } +void +UserSettings::setSpaceNotifications(SpaceNotificationOptions state) +{ + if (state == spaceNotifications_) + return; + spaceNotifications_ = state; + emit spaceNotificationsChanged(state); + save(); +} + void UserSettings::setPrivacyScreen(bool state) { @@ -777,6 +795,9 @@ UserSettings::save() settings.setValue(QStringLiteral("avatar_circles"), avatarCircles_); settings.setValue(QStringLiteral("decrypt_sidebar"), decryptSidebar_); + settings.setValue(QStringLiteral("space_notifications"), + QString::fromUtf8(QMetaEnum::fromType().valueToKey( + static_cast(spaceNotifications_)))); settings.setValue(QStringLiteral("privacy_screen"), privacyScreen_); settings.setValue(QStringLiteral("privacy_screen_timeout"), privacyScreenTimeout_); settings.setValue(QStringLiteral("mobile_mode"), mobileMode_); @@ -923,6 +944,8 @@ UserSettingsModel::data(const QModelIndex &index, int role) const return tr("Open videos with external program"); case DecryptSidebar: return tr("Decrypt messages in sidebar"); + case SpaceNotifications: + return tr("Show message counts for spaces"); case PrivacyScreen: return tr("Privacy Screen"); case PrivacyScreenTimeout: @@ -1053,6 +1076,8 @@ UserSettingsModel::data(const QModelIndex &index, int role) const return i->openVideoExternal(); case DecryptSidebar: return i->decryptSidebar(); + case SpaceNotifications: + return static_cast(i->spaceNotifications()); case PrivacyScreen: return i->privacyScreen(); case PrivacyScreenTimeout: @@ -1208,6 +1233,9 @@ UserSettingsModel::data(const QModelIndex &index, int role) const case DecryptSidebar: return tr("Decrypt the messages shown in the sidebar.\nOnly affects messages in " "encrypted chats."); + case SpaceNotifications: + return tr( + "Choose where to show the total number of notifications contained within a space."); case PrivacyScreen: return tr("When the window loses focus, the timeline will\nbe blurred."); case MobileMode: @@ -1283,6 +1311,7 @@ UserSettingsModel::data(const QModelIndex &index, int role) const case CameraResolution: case CameraFrameRate: case Ringtone: + case SpaceNotifications: return Options; case TimelineMaxWidth: case PrivacyScreenTimeout: @@ -1409,7 +1438,7 @@ UserSettingsModel::data(const QModelIndex &index, int role) const return fontDb.families(); case EmojiFont: return fontDb.families(QFontDatabase::WritingSystem::Symbol); - case Ringtone: + case Ringtone: { QStringList l{ QStringLiteral("Mute"), QStringLiteral("Default"), @@ -1419,6 +1448,12 @@ UserSettingsModel::data(const QModelIndex &index, int role) const l.push_back(i->ringtone()); return l; } + case SpaceNotifications: + return QStringList{QStringLiteral("Sidebar and room list"), + QStringLiteral("Sidebar"), + QStringLiteral("Sidebar (hidden rooms only)"), + QStringLiteral("Off")}; + } } else if (role == Good) { switch (index.row()) { case OnlineBackupKey: @@ -1624,6 +1659,15 @@ UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int return false; } return i->decryptSidebar(); + case SpaceNotifications: { + if (value.toInt() > + static_cast(UserSettings::SpaceNotificationOptions::SpaceNotificationsOff) || + value.toInt() < 0) + return false; + + i->setSpaceNotifications(value.value()); + return true; + } case PrivacyScreen: { if (value.userType() == QMetaType::Bool) { i->setPrivacyScreen(value.toBool()); @@ -1936,7 +1980,9 @@ UserSettingsModel::UserSettingsModel(QObject *p) connect(s.get(), &UserSettings::decryptSidebarChanged, this, [this]() { emit dataChanged(index(DecryptSidebar), index(DecryptSidebar), {Value}); }); - + connect(s.get(), &UserSettings::spaceNotificationsChanged, this, [this] { + emit dataChanged(index(SpaceNotifications), index(SpaceNotifications), {Value}); + }); connect(s.get(), &UserSettings::trayChanged, this, [this]() { emit dataChanged(index(Tray), index(Tray), {Value}); emit dataChanged(index(StartInTray), index(StartInTray), {Enabled}); diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index 1fb3ddcf..daf41383 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -58,6 +58,8 @@ class UserSettings : public QObject bool avatarCircles READ avatarCircles WRITE setAvatarCircles NOTIFY avatarCirclesChanged) Q_PROPERTY( bool decryptSidebar READ decryptSidebar WRITE setDecryptSidebar NOTIFY decryptSidebarChanged) + Q_PROPERTY(SpaceNotificationOptions spaceNotifications READ spaceNotifications WRITE + setSpaceNotifications NOTIFY spaceNotificationsChanged) Q_PROPERTY( bool privacyScreen READ privacyScreen WRITE setPrivacyScreen NOTIFY privacyScreenChanged) Q_PROPERTY(int privacyScreenTimeout READ privacyScreenTimeout WRITE setPrivacyScreenTimeout @@ -134,6 +136,15 @@ public: }; Q_ENUM(Presence) + enum class SpaceNotificationOptions + { + SidebarAndRoomlist = 0, + Sidebar, + SidebarHiddenRooms, + SpaceNotificationsOff, + }; + Q_ENUM(SpaceNotificationOptions) + void save(); void load(std::optional profile); void applyTheme(); @@ -162,6 +173,7 @@ public: void setAlertOnNotification(bool state); void setAvatarCircles(bool state); void setDecryptSidebar(bool state); + void setSpaceNotifications(SpaceNotificationOptions state); void setPrivacyScreen(bool state); void setPrivacyScreenTimeout(int state); void setPresence(Presence state); @@ -202,6 +214,7 @@ public: bool groupView() const { return groupView_; } bool avatarCircles() const { return avatarCircles_; } bool decryptSidebar() const { return decryptSidebar_; } + SpaceNotificationOptions spaceNotifications() const { return spaceNotifications_; } bool privacyScreen() const { return privacyScreen_; } int privacyScreenTimeout() const { return privacyScreenTimeout_; } bool markdown() const { return markdown_; } @@ -278,6 +291,7 @@ signals: void alertOnNotificationChanged(bool state); void avatarCirclesChanged(bool state); void decryptSidebarChanged(bool state); + void spaceNotificationsChanged(SpaceNotificationOptions state); void privacyScreenChanged(bool state); void privacyScreenTimeoutChanged(int state); void timelineMaxWidthChanged(int state); @@ -340,6 +354,7 @@ private: bool hasAlertOnNotification_; bool avatarCircles_; bool decryptSidebar_; + SpaceNotificationOptions spaceNotifications_; bool privacyScreen_; int privacyScreenTimeout_; bool shareKeysWithTrustedUsers_; @@ -424,6 +439,7 @@ class UserSettingsModel : public QAbstractListModel GroupView, SortByImportance, DecryptSidebar, + SpaceNotifications, TraySection, Tray, -- cgit 1.5.1 From 7cbde0712f2f46a8cbed133aa01889f2de99e0e5 Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Thu, 28 Apr 2022 17:00:12 -0400 Subject: Allow muting spaces; other general improvements --- resources/qml/CommunitiesList.qml | 33 ++++++++++++++++++++++----- src/UserSettingsPage.cpp | 19 +++++++++++----- src/UserSettingsPage.h | 9 +++++--- src/timeline/CommunitiesModel.cpp | 47 ++++++++++++++++++++++++++++++++++----- src/timeline/CommunitiesModel.h | 3 +++ 5 files changed, 92 insertions(+), 19 deletions(-) (limited to 'resources') diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index 62ac341a..5bc20dbe 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -37,14 +37,27 @@ Page { id: communityContextMenu property string tagId + property bool hidden + property bool muted - function show(id_, tags_) { + function show(id_, hidden_, muted_) { tagId = id_; + hidden = hidden_; + muted = muted_; open(); } + Platform.MenuItem { + text: qsTr("Do not show notification counts for this space or tag.") + checkable: true + checked: communityContextMenu.muted + onTriggered: Communities.toggleTagMute(communityContextMenu.tagId) + } + Platform.MenuItem { text: qsTr("Hide rooms with this tag or from this space by default.") + checkable: true + checked: communityContextMenu.hidden onTriggered: Communities.toggleTagId(communityContextMenu.tagId) } @@ -68,6 +81,7 @@ Page { required property string id required property int unreadMessages required property bool hasLoudNotification + required property bool muted height: avatarSize + 2 * Nheko.paddingMedium width: ListView.view.width @@ -76,7 +90,7 @@ Page { ToolTip.text: communityItem.tooltip ToolTip.delay: Nheko.tooltipDelay onClicked: Communities.setCurrentTagId(communityItem.id) - onPressAndHold: communityContextMenu.show(communityItem.id) + onPressAndHold: communityContextMenu.show(communityItem.id, communityItem.hidden, communityItem.muted) states: [ State { name: "highlight" @@ -113,7 +127,7 @@ Page { TapHandler { acceptedButtons: Qt.RightButton - onSingleTapped: communityContextMenu.show(communityItem.id) + onSingleTapped: communityContextMenu.show(communityItem.id, communityItem.hidden, communityItem.muted) gesturePolicy: TapHandler.ReleaseWithinBounds acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus | PointerDevice.TouchPad } @@ -174,6 +188,8 @@ Page { mayBeVisible: { if (!communitySidebar.collapsed) return false + else if (communityItem.muted) + return false else if (Settings.spaceNotifications === Settings.SpaceNotificationsOff) return false else if (Settings.spaceNotifications === Settings.SidebarHiddenRooms) @@ -215,10 +231,17 @@ Page { mayBeVisible: { if (communitySidebar.collapsed) return false + else if (communityItem.muted) + return false else if (Settings.spaceNotification === Settings.SpaceNotificationsOff) return false - else if ((Settings.spaceNotifications === Settings.SidebarHiddenRooms) && communityItem.hidden) - return true + else if (Settings.spaceNotifications === Settings.SidebarHiddenRooms) + { + if (communityItem.hidden) + return true + else + return false + } else return true } diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index c4cc339b..2c6dc782 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -140,7 +140,8 @@ UserSettings::load(std::optional profile) userId_ = settings.value(prefix + "auth/user_id", "").toString(); deviceId_ = settings.value(prefix + "auth/device_id", "").toString(); hiddenTags_ = settings.value(prefix + "user/hidden_tags", QStringList{}).toStringList(); - hiddenPins_ = settings.value(prefix + "user/hidden_pins", QStringList{}).toStringList(); + mutedTags_ = settings.value(prefix + "user/muted_tags", QStringList{"global"}).toStringList(); + hiddenPins_ = settings.value(prefix + "user/hidden_pins", QStringList{}).toStringList(); hiddenWidgets_ = settings.value(prefix + "user/hidden_widgets", QStringList{}).toStringList(); recentReactions_ = settings.value(prefix + "user/recent_reactions", QStringList{}).toStringList(); @@ -228,14 +229,21 @@ UserSettings::setGroupView(bool state) } void -UserSettings::setHiddenTags(QStringList hiddenTags) +UserSettings::setHiddenTags(const QStringList &hiddenTags) { hiddenTags_ = hiddenTags; save(); } void -UserSettings::setHiddenPins(QStringList hiddenTags) +UserSettings::setMutedTags(const QStringList &mutedTags) +{ + mutedTags_ = mutedTags; + save(); +} + +void +UserSettings::setHiddenPins(const QStringList &hiddenTags) { hiddenPins_ = hiddenTags; save(); @@ -243,7 +251,7 @@ UserSettings::setHiddenPins(QStringList hiddenTags) } void -UserSettings::setHiddenWidgets(QStringList hiddenTags) +UserSettings::setHiddenWidgets(const QStringList &hiddenTags) { hiddenWidgets_ = hiddenTags; save(); @@ -851,6 +859,7 @@ UserSettings::save() onlyShareKeysWithVerifiedUsers_); settings.setValue(prefix + "user/online_key_backup", useOnlineKeyBackup_); settings.setValue(prefix + "user/hidden_tags", hiddenTags_); + settings.setValue(prefix + "user/muted_tags", mutedTags_); settings.setValue(prefix + "user/hidden_pins", hiddenPins_); settings.setValue(prefix + "user/hidden_widgets", hiddenWidgets_); settings.setValue(prefix + "user/recent_reactions", recentReactions_); @@ -1451,7 +1460,7 @@ UserSettingsModel::data(const QModelIndex &index, int role) const case SpaceNotifications: return QStringList{QStringLiteral("Sidebar and room list"), QStringLiteral("Sidebar"), - QStringLiteral("Sidebar (hidden rooms only)"), + QStringLiteral("Sidebar (hidden spaces and tags only)"), QStringLiteral("Off")}; } } else if (role == Good) { diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index daf41383..db12b1e6 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -196,9 +196,10 @@ public: void setDeviceId(QString deviceId); void setHomeserver(QString homeserver); void setDisableCertificateValidation(bool disabled); - void setHiddenTags(QStringList hiddenTags); - void setHiddenPins(QStringList hiddenTags); - void setHiddenWidgets(QStringList hiddenTags); + void setHiddenTags(const QStringList &hiddenTags); + void setMutedTags(const QStringList &mutedTags); + void setHiddenPins(const QStringList &hiddenTags); + void setHiddenWidgets(const QStringList &hiddenTags); void setRecentReactions(QStringList recent); void setUseIdenticon(bool state); void setOpenImageExternal(bool state); @@ -263,6 +264,7 @@ public: QString homeserver() const { return homeserver_; } bool disableCertificateValidation() const { return disableCertificateValidation_; } QStringList hiddenTags() const { return hiddenTags_; } + QStringList mutedTags() const { return mutedTags_; } QStringList hiddenPins() const { return hiddenPins_; } QStringList hiddenWidgets() const { return hiddenWidgets_; } QStringList recentReactions() const { return recentReactions_; } @@ -385,6 +387,7 @@ private: QString deviceId_; QString homeserver_; QStringList hiddenTags_; + QStringList mutedTags_; QStringList hiddenPins_; QStringList hiddenWidgets_; QStringList recentReactions_; diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp index 8e1cf140..91f7d555 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp @@ -16,6 +16,8 @@ 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. @@ -40,6 +42,7 @@ CommunitiesModel::roleNames() const {Id, "id"}, {UnreadMessages, "unreadMessages"}, {HasLoudNotification, "hasLoudNotification"}, + {Muted, "muted"}, }; } @@ -62,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: @@ -333,7 +343,6 @@ CommunitiesModel::initializeSidebar() for (const auto &t : ts) tags_.push_back(QString::fromStdString(t)); - hiddenTagIds_ = UserSettings::instance()->hiddenTags(); spaceOrder_.restoreCollapsed(); endResetModel(); @@ -485,13 +494,11 @@ CommunitiesModel::setCurrentTagId(const QString &tagId) void CommunitiesModel::toggleTagId(QString tagId) { - if (hiddenTagIds_.contains(tagId)) { + if (hiddenTagIds_.contains(tagId)) hiddenTagIds_.removeOne(tagId); - UserSettings::instance()->setHiddenTags(hiddenTagIds_); - } else { + else hiddenTagIds_.push_back(tagId); - UserSettings::instance()->setHiddenTags(hiddenTagIds_); - } + UserSettings::instance()->setHiddenTags(hiddenTagIds_); if (tagId.startsWith(QLatin1String("tag:"))) { auto idx = tags_.indexOf(tagId.mid(4)); @@ -509,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 bcb487e7..5a659751 100644 --- a/src/timeline/CommunitiesModel.h +++ b/src/timeline/CommunitiesModel.h @@ -50,6 +50,7 @@ public: Id, UnreadMessages, HasLoudNotification, + Muted, IsDirect, }; @@ -141,6 +142,7 @@ public slots: return tagsWD; } void toggleTagId(QString tagId); + void toggleTagMute(QString tagId); FilteredCommunitiesModel *filtered() { return new FilteredCommunitiesModel(this, this); } signals: @@ -153,6 +155,7 @@ private: QStringList tags_; QString currentTagId_; QStringList hiddenTagIds_; + QStringList mutedTagIds_; FlatTree spaceOrder_; std::map spaces_; std::vector directMessages_; -- cgit 1.5.1 From f264941615e67100d5dda94bd7b8606e47ed0351 Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Thu, 28 Apr 2022 17:16:47 -0400 Subject: make license --- resources/qml/components/NotificationBubble.qml | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'resources') diff --git a/resources/qml/components/NotificationBubble.qml b/resources/qml/components/NotificationBubble.qml index 07dd76a8..ca0ae6cb 100644 --- a/resources/qml/components/NotificationBubble.qml +++ b/resources/qml/components/NotificationBubble.qml @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + import QtQuick 2.15 import QtQuick.Controls 2.15 import im.nheko 1.0 -- cgit 1.5.1 From 885a790b1fa16524058a5c8aacf3ec8e9641709d Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Mon, 6 Jun 2022 12:07:25 -0400 Subject: Simplify space notification options --- resources/qml/CommunitiesList.qml | 36 ++---------------------------------- resources/qml/RoomList.qml | 4 ++-- src/UserSettingsPage.cpp | 34 +++++++++------------------------- src/UserSettingsPage.h | 19 +++++-------------- 4 files changed, 18 insertions(+), 75 deletions(-) (limited to 'resources') diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index 5bc20dbe..ec9ef940 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -185,23 +185,7 @@ Page { bubbleBackgroundColor: communityItem.bubbleBackground bubbleTextColor: communityItem.bubbleText font.pixelSize: fontMetrics.font.pixelSize * 0.6 - mayBeVisible: { - if (!communitySidebar.collapsed) - return false - else if (communityItem.muted) - return false - else if (Settings.spaceNotifications === Settings.SpaceNotificationsOff) - return false - else if (Settings.spaceNotifications === Settings.SidebarHiddenRooms) - { - if (communityItem.hidden) - return true - else - return false - } - else - return true - } + mayBeVisible: communitySidebar.collapsed && !communityItem.muted && Settings.spaceNotifications anchors.right: avatar.right anchors.bottom: avatar.bottom anchors.margins: -Nheko.paddingSmall @@ -228,23 +212,7 @@ Page { hasLoudNotification: communityItem.hasLoudNotification bubbleBackgroundColor: communityItem.bubbleBackground bubbleTextColor: communityItem.bubbleText - mayBeVisible: { - if (communitySidebar.collapsed) - return false - else if (communityItem.muted) - return false - else if (Settings.spaceNotification === Settings.SpaceNotificationsOff) - return false - else if (Settings.spaceNotifications === Settings.SidebarHiddenRooms) - { - if (communityItem.hidden) - return true - else - return false - } - else - return true - } + mayBeVisible: !communitySidebar.collapsed && !communityItem.muted && Settings.spaceNotifications Layout.alignment: Qt.AlignRight Layout.leftMargin: Nheko.paddingSmall } diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index b34a94a1..ea066876 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -316,7 +316,7 @@ Page { anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: -Nheko.paddingSmall - mayBeVisible: collapsed && (isSpace ? Settings.spaceNotifications === Settings.SidebarAndRoomlist : true) + mayBeVisible: collapsed && (isSpace ? Settings.spaceNotifications : true) } } @@ -345,7 +345,7 @@ Page { Layout.leftMargin: Nheko.paddingSmall Layout.preferredWidth: implicitWidth Layout.preferredHeight: implicitHeight - mayBeVisible: !collapsed && (isSpace ? Settings.spaceNotifications === Settings.SidebarAndRoomlist : true) + mayBeVisible: !collapsed && (isSpace ? Settings.spaceNotifications : true) } RowLayout { diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index 2c6dc782..b850d2e5 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -88,14 +88,7 @@ UserSettings::load(std::optional profile) openImageExternal_ = settings.value(QStringLiteral("user/open_image_external"), false).toBool(); openVideoExternal_ = settings.value(QStringLiteral("user/open_video_external"), false).toBool(); decryptSidebar_ = settings.value(QStringLiteral("user/decrypt_sidebar"), true).toBool(); - auto tempSpaceNotifs = settings.value(QStringLiteral("user/space_notifications"), QString{}) - .toString() - .toStdString(); - auto spaceNotifsValue = - QMetaEnum::fromType().keyToValue(tempSpaceNotifs.c_str()); - if (spaceNotifsValue < 0) - spaceNotifsValue = 0; - spaceNotifications_ = static_cast(spaceNotifsValue); + spaceNotifications_ = settings.value(QStringLiteral("user/space_notifications"), true).toBool(); privacyScreen_ = settings.value(QStringLiteral("user/privacy_screen"), false).toBool(); privacyScreenTimeout_ = settings.value(QStringLiteral("user/privacy_screen_timeout"), 0).toInt(); @@ -433,7 +426,7 @@ UserSettings::setDecryptSidebar(bool state) } void -UserSettings::setSpaceNotifications(SpaceNotificationOptions state) +UserSettings::setSpaceNotifications(bool state) { if (state == spaceNotifications_) return; @@ -803,9 +796,7 @@ UserSettings::save() settings.setValue(QStringLiteral("avatar_circles"), avatarCircles_); settings.setValue(QStringLiteral("decrypt_sidebar"), decryptSidebar_); - settings.setValue(QStringLiteral("space_notifications"), - QString::fromUtf8(QMetaEnum::fromType().valueToKey( - static_cast(spaceNotifications_)))); + settings.setValue(QStringLiteral("space_notifications"), spaceNotifications_); settings.setValue(QStringLiteral("privacy_screen"), privacyScreen_); settings.setValue(QStringLiteral("privacy_screen_timeout"), privacyScreenTimeout_); settings.setValue(QStringLiteral("mobile_mode"), mobileMode_); @@ -1086,7 +1077,7 @@ UserSettingsModel::data(const QModelIndex &index, int role) const case DecryptSidebar: return i->decryptSidebar(); case SpaceNotifications: - return static_cast(i->spaceNotifications()); + return i->spaceNotifications(); case PrivacyScreen: return i->privacyScreen(); case PrivacyScreenTimeout: @@ -1320,7 +1311,6 @@ UserSettingsModel::data(const QModelIndex &index, int role) const case CameraResolution: case CameraFrameRate: case Ringtone: - case SpaceNotifications: return Options; case TimelineMaxWidth: case PrivacyScreenTimeout: @@ -1355,6 +1345,7 @@ UserSettingsModel::data(const QModelIndex &index, int role) const case ShareKeysWithTrustedUsers: case UseOnlineKeyBackup: case ExposeDBusApi: + case SpaceNotifications: return Toggle; case Profile: case UserId: @@ -1457,11 +1448,6 @@ UserSettingsModel::data(const QModelIndex &index, int role) const l.push_back(i->ringtone()); return l; } - case SpaceNotifications: - return QStringList{QStringLiteral("Sidebar and room list"), - QStringLiteral("Sidebar"), - QStringLiteral("Sidebar (hidden spaces and tags only)"), - QStringLiteral("Off")}; } } else if (role == Good) { switch (index.row()) { @@ -1669,13 +1655,11 @@ UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int } return i->decryptSidebar(); case SpaceNotifications: { - if (value.toInt() > - static_cast(UserSettings::SpaceNotificationOptions::SpaceNotificationsOff) || - value.toInt() < 0) + if (value.userType() == QMetaType::Bool) { + i->setSpaceNotifications(value.toBool()); + return true; + } else return false; - - i->setSpaceNotifications(value.value()); - return true; } case PrivacyScreen: { if (value.userType() == QMetaType::Bool) { diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index db12b1e6..7bb722f1 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -58,7 +58,7 @@ class UserSettings : public QObject bool avatarCircles READ avatarCircles WRITE setAvatarCircles NOTIFY avatarCirclesChanged) Q_PROPERTY( bool decryptSidebar READ decryptSidebar WRITE setDecryptSidebar NOTIFY decryptSidebarChanged) - Q_PROPERTY(SpaceNotificationOptions spaceNotifications READ spaceNotifications WRITE + Q_PROPERTY(bool spaceNotifications READ spaceNotifications WRITE setSpaceNotifications NOTIFY spaceNotificationsChanged) Q_PROPERTY( bool privacyScreen READ privacyScreen WRITE setPrivacyScreen NOTIFY privacyScreenChanged) @@ -136,15 +136,6 @@ public: }; Q_ENUM(Presence) - enum class SpaceNotificationOptions - { - SidebarAndRoomlist = 0, - Sidebar, - SidebarHiddenRooms, - SpaceNotificationsOff, - }; - Q_ENUM(SpaceNotificationOptions) - void save(); void load(std::optional profile); void applyTheme(); @@ -173,7 +164,7 @@ public: void setAlertOnNotification(bool state); void setAvatarCircles(bool state); void setDecryptSidebar(bool state); - void setSpaceNotifications(SpaceNotificationOptions state); + void setSpaceNotifications(bool state); void setPrivacyScreen(bool state); void setPrivacyScreenTimeout(int state); void setPresence(Presence state); @@ -215,7 +206,7 @@ public: bool groupView() const { return groupView_; } bool avatarCircles() const { return avatarCircles_; } bool decryptSidebar() const { return decryptSidebar_; } - SpaceNotificationOptions spaceNotifications() const { return spaceNotifications_; } + bool spaceNotifications() const { return spaceNotifications_; } bool privacyScreen() const { return privacyScreen_; } int privacyScreenTimeout() const { return privacyScreenTimeout_; } bool markdown() const { return markdown_; } @@ -293,7 +284,7 @@ signals: void alertOnNotificationChanged(bool state); void avatarCirclesChanged(bool state); void decryptSidebarChanged(bool state); - void spaceNotificationsChanged(SpaceNotificationOptions state); + void spaceNotificationsChanged(bool state); void privacyScreenChanged(bool state); void privacyScreenTimeoutChanged(int state); void timelineMaxWidthChanged(int state); @@ -356,7 +347,7 @@ private: bool hasAlertOnNotification_; bool avatarCircles_; bool decryptSidebar_; - SpaceNotificationOptions spaceNotifications_; + bool spaceNotifications_; bool privacyScreen_; int privacyScreenTimeout_; bool shareKeysWithTrustedUsers_; -- cgit 1.5.1 From 7b33d14277c3a3ca3db9bf1415c1a7372645b8e1 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 16 Jul 2022 03:07:00 +0200 Subject: Make notification count calculation more efficient --- resources/qml/CommunitiesList.qml | 60 ++++++++++++---------------- src/Utils.cpp | 18 --------- src/Utils.h | 5 --- src/timeline/CommunitiesModel.cpp | 84 ++++++++++++++++++++++++++++++--------- src/timeline/RoomlistModel.cpp | 17 ++++---- src/timeline/RoomlistModel.h | 8 +--- 6 files changed, 103 insertions(+), 89 deletions(-) (limited to 'resources') 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 members) }); }); } - -QPair -utils::getChildNotificationsForSpace(const QString &spaceId) -{ - auto children = cache::getRoomInfo(cache::client()->getChildRoomIds(spaceId.toStdString())); - QPair 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 members); - -//! Returns a pair of integers representing the unread notifications in a space and how many of them -//! are loud notifications, respectively. -QPair -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>( + &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 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(oldUnreads.highlight_count) + - static_cast(room.unread_notifications.highlight_count); - int highlightCDiff = -static_cast(oldUnreads.highlight_count) + - static_cast(room.unread_notifications.highlight_count); + auto roomId = QString::fromStdString(roomid); + auto &oldUnreads = roomNotificationCache[roomId]; + auto notificationCDiff = -static_cast(oldUnreads.notification_count) + + static_cast(room.unread_notifications.notification_count); + auto highlightCDiff = -static_cast(oldUnreads.highlight_count) + + static_cast(room.unread_notifications.highlight_count); + + auto applyDiff = [notificationCDiff, + highlightCDiff](mtx::responses::UnreadNotifications &n) { + n.highlight_count = static_cast(n.highlight_count) + highlightCDiff; + n.notification_count = static_cast(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( - parentSpace.toStdString(), roomid.toStdString()); - ChatPage::instance()->joinRoomVia( - roomid.toStdString(), - (child && child->content.via) ? child->content.via.value() : std::vector{}, - false); + std::vector vias; + auto parents = cache::client()->getParentRoomIds(roomid.toStdString()); + for (const auto &p : parents) { + auto child = cache::client()->getStateEvent( + 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); } -- cgit 1.5.1