Space notification count
Show the number of notifications for a space if it isn't selected. This respects choices like low priority only adding highlights.
This commit is contained in:
@@ -298,30 +298,7 @@ QVariant RoomListModel::data(const QModelIndex &index, int role) const
|
||||
return room->topic();
|
||||
}
|
||||
if (role == CategoryRole) {
|
||||
if (room->joinState() == JoinState::Invite) {
|
||||
return NeoChatRoomType::Invited;
|
||||
}
|
||||
if (room->isFavourite()) {
|
||||
return NeoChatRoomType::Favorite;
|
||||
}
|
||||
if (room->isLowPriority()) {
|
||||
return NeoChatRoomType::Deprioritized;
|
||||
}
|
||||
if (room->isDirectChat()) {
|
||||
return NeoChatRoomType::Direct;
|
||||
}
|
||||
const RoomCreateEvent *creationEvent = room->creation();
|
||||
if (!creationEvent) {
|
||||
return NeoChatRoomType::Normal;
|
||||
}
|
||||
QJsonObject contentJson = creationEvent->contentJson();
|
||||
QJsonObject::const_iterator typeIter = contentJson.find("type"_ls);
|
||||
if (typeIter != contentJson.end()) {
|
||||
if (typeIter.value().toString() == "m.space"_ls) {
|
||||
return NeoChatRoomType::Space;
|
||||
}
|
||||
}
|
||||
return NeoChatRoomType::Normal;
|
||||
return category(room);
|
||||
}
|
||||
if (role == NotificationCountRole) {
|
||||
return room->notificationCount();
|
||||
@@ -406,6 +383,26 @@ QHash<int, QByteArray> RoomListModel::roleNames() const
|
||||
return roles;
|
||||
}
|
||||
|
||||
NeoChatRoomType::Types RoomListModel::category(NeoChatRoom *room)
|
||||
{
|
||||
if (room->isSpace()) {
|
||||
return NeoChatRoomType::Space;
|
||||
}
|
||||
if (room->joinState() == JoinState::Invite) {
|
||||
return NeoChatRoomType::Invited;
|
||||
}
|
||||
if (room->isFavourite()) {
|
||||
return NeoChatRoomType::Favorite;
|
||||
}
|
||||
if (room->isLowPriority()) {
|
||||
return NeoChatRoomType::Deprioritized;
|
||||
}
|
||||
if (room->isDirectChat()) {
|
||||
return NeoChatRoomType::Direct;
|
||||
}
|
||||
return NeoChatRoomType::Normal;
|
||||
}
|
||||
|
||||
QString RoomListModel::categoryName(int category)
|
||||
{
|
||||
switch (category) {
|
||||
|
||||
@@ -116,6 +116,11 @@ public:
|
||||
*/
|
||||
Q_INVOKABLE [[nodiscard]] NeoChatRoom *roomAt(int row) const;
|
||||
|
||||
/**
|
||||
* @brief The category for the given room.
|
||||
*/
|
||||
static NeoChatRoomType::Types category(NeoChatRoom *room);
|
||||
|
||||
/**
|
||||
* @brief Return a string to represent the given room category.
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#include "controller.h"
|
||||
#include "jobs/neochatchangepasswordjob.h"
|
||||
#include "jobs/neochatdeactivateaccountjob.h"
|
||||
#include "neochatroom.h"
|
||||
#include "roommanager.h"
|
||||
#include "spacehierarchycache.h"
|
||||
|
||||
#include <Quotient/connection.h>
|
||||
#include <Quotient/quotient_common.h>
|
||||
@@ -97,6 +99,21 @@ void NeoChatConnection::connectSignals()
|
||||
Q_EMIT directChatInvitesChanged();
|
||||
}
|
||||
});
|
||||
|
||||
connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() {
|
||||
Q_EMIT homeNotificationsChanged();
|
||||
});
|
||||
for (const auto room : allRooms()) {
|
||||
connect(room, &NeoChatRoom::unreadStatsChanged, this, [this, room]() {
|
||||
if (room != nullptr) {
|
||||
auto category = RoomListModel::category(static_cast<NeoChatRoom *>(room));
|
||||
if (!SpaceHierarchyCache::instance().isChild(room->id()) && (category == NeoChatRoomType::Normal || category == NeoChatRoomType::Favorite)
|
||||
&& room->successorId().isEmpty()) {
|
||||
Q_EMIT homeNotificationsChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void NeoChatConnection::logout(bool serverSideLogout)
|
||||
@@ -319,6 +336,29 @@ qsizetype NeoChatConnection::directChatNotifications() const
|
||||
return notifications;
|
||||
}
|
||||
|
||||
qsizetype NeoChatConnection::homeNotifications() const
|
||||
{
|
||||
qsizetype notifications = 0;
|
||||
QStringList added;
|
||||
const auto &spaceHierarchyCache = SpaceHierarchyCache::instance();
|
||||
for (const auto &room : allRooms()) {
|
||||
auto category = RoomListModel::category(static_cast<NeoChatRoom *>(room));
|
||||
if (!added.contains(room->id()) && room->joinState() == JoinState::Join && !room->isDirectChat() && !spaceHierarchyCache.isChild(room->id())
|
||||
&& room->successorId().isEmpty()) {
|
||||
switch (category) {
|
||||
case NeoChatRoomType::Normal:
|
||||
case NeoChatRoomType::Favorite:
|
||||
notifications += room->notificationCount();
|
||||
break;
|
||||
default:
|
||||
notifications += room->highlightCount();
|
||||
}
|
||||
added += room->id();
|
||||
}
|
||||
}
|
||||
return notifications;
|
||||
}
|
||||
|
||||
bool NeoChatConnection::directChatInvites() const
|
||||
{
|
||||
auto inviteRooms = rooms(JoinState::Invite);
|
||||
|
||||
@@ -32,6 +32,11 @@ class NeoChatConnection : public Quotient::Connection
|
||||
*/
|
||||
Q_PROPERTY(qsizetype directChatNotifications READ directChatNotifications NOTIFY directChatNotificationsChanged)
|
||||
|
||||
/**
|
||||
* @brief The total number of notifications for all rooms in the home tab.
|
||||
*/
|
||||
Q_PROPERTY(qsizetype homeNotifications READ homeNotifications NOTIFY homeNotificationsChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether there is at least one invite to a direct chat.
|
||||
*/
|
||||
@@ -109,6 +114,7 @@ public:
|
||||
Q_INVOKABLE void openOrCreateDirectChat(Quotient::User *user);
|
||||
|
||||
qsizetype directChatNotifications() const;
|
||||
qsizetype homeNotifications() const;
|
||||
bool directChatInvites() const;
|
||||
|
||||
// note: this is intentionally a copied QString because
|
||||
@@ -123,6 +129,7 @@ public:
|
||||
Q_SIGNALS:
|
||||
void labelChanged();
|
||||
void directChatNotificationsChanged();
|
||||
void homeNotificationsChanged();
|
||||
void directChatInvitesChanged();
|
||||
void isOnlineChanged();
|
||||
void passwordStatus(NeoChatConnection::PasswordStatus status);
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "neochatconfig.h"
|
||||
#include "notificationsmanager.h"
|
||||
#include "roomlastmessageprovider.h"
|
||||
#include "spacehierarchycache.h"
|
||||
#include "texthandler.h"
|
||||
#include "urlhelper.h"
|
||||
#include "utils.h"
|
||||
@@ -125,6 +126,16 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
|
||||
Q_EMIT urlPreviewEnabledChanged();
|
||||
}
|
||||
});
|
||||
connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() {
|
||||
if (isSpace()) {
|
||||
Q_EMIT childrenNotificationCountChanged();
|
||||
}
|
||||
});
|
||||
connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceNotifcationCountChanged, this, [this](const QStringList &spaces) {
|
||||
if (spaces.contains(id())) {
|
||||
Q_EMIT childrenNotificationCountChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool NeoChatRoom::hasFileUploading() const
|
||||
@@ -1278,6 +1289,14 @@ bool NeoChatRoom::isSpace()
|
||||
return creationEvent->roomType() == RoomType::Space;
|
||||
}
|
||||
|
||||
qsizetype NeoChatRoom::childrenNotificationCount()
|
||||
{
|
||||
if (!isSpace()) {
|
||||
return 0;
|
||||
}
|
||||
return SpaceHierarchyCache::instance().notificationCountForSpace(id());
|
||||
}
|
||||
|
||||
void NeoChatRoom::addChild(const QString &childId, bool setChildParent, bool canonical, bool suggested)
|
||||
{
|
||||
if (!isSpace()) {
|
||||
|
||||
@@ -126,6 +126,13 @@ class NeoChatRoom : public Quotient::Room
|
||||
*/
|
||||
Q_PROPERTY(bool isSpace READ isSpace CONSTANT)
|
||||
|
||||
/**
|
||||
* @brief The number of notifications in this room's children.
|
||||
*
|
||||
* Will always return 0 if this is not a space.
|
||||
*/
|
||||
Q_PROPERTY(qsizetype childrenNotificationCount READ childrenNotificationCount NOTIFY childrenNotificationCountChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the local user has an invite to the room.
|
||||
*
|
||||
@@ -526,6 +533,8 @@ public:
|
||||
|
||||
[[nodiscard]] bool isSpace();
|
||||
|
||||
qsizetype childrenNotificationCount();
|
||||
|
||||
/**
|
||||
* @brief Add the given room as a child.
|
||||
*
|
||||
@@ -815,6 +824,7 @@ Q_SIGNALS:
|
||||
void parentIdsChanged();
|
||||
void canonicalParentChanged();
|
||||
void lastActiveTimeChanged();
|
||||
void childrenNotificationCountChanged();
|
||||
void isInviteChanged();
|
||||
void readOnlyChanged();
|
||||
void displayNameChanged();
|
||||
|
||||
@@ -108,6 +108,32 @@ QQC2.Control {
|
||||
RoomManager.lastSpaceId = "";
|
||||
root.selectionChanged();
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
id: homeNotificationCountLabel
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Kirigami.Units.smallSpacing / 2
|
||||
z: 1
|
||||
width: Math.max(homeNotificationCountTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 2, height)
|
||||
height: Kirigami.Units.iconSizes.smallMedium
|
||||
|
||||
text: root.connection.homeNotifications > 0 ? root.connection.homeNotifications : ""
|
||||
visible: root.connection.homeNotifications > 0 && (root.selectedSpaceId !== "" || root.showDirectChats === true)
|
||||
color: Kirigami.Theme.textColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
background: Rectangle {
|
||||
visible: true
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Button
|
||||
color: Kirigami.Theme.positiveTextColor
|
||||
radius: height / 2
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: homeNotificationCountTextMetrics
|
||||
text: homeNotificationCountLabel.text
|
||||
}
|
||||
}
|
||||
}
|
||||
AvatarTabButton {
|
||||
id: directChatButton
|
||||
@@ -132,16 +158,16 @@ QQC2.Control {
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
id: notificationCountLabel
|
||||
id: directChatNotificationCountLabel
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Kirigami.Units.smallSpacing / 2
|
||||
z: 1
|
||||
width: Math.max(notificationCountTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 2, height)
|
||||
width: Math.max(directChatNotificationCountTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 2, height)
|
||||
height: Kirigami.Units.iconSizes.smallMedium
|
||||
|
||||
text: root.connection.directChatNotifications > 0 ? root.connection.directChatNotifications : ""
|
||||
visible: root.connection.directChatNotifications > 0 || root.connection.directChatInvites
|
||||
visible: (root.connection.directChatNotifications > 0 || root.connection.directChatInvites) && root.showDirectChats === false
|
||||
color: Kirigami.Theme.textColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
background: Rectangle {
|
||||
@@ -152,8 +178,8 @@ QQC2.Control {
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: notificationCountTextMetrics
|
||||
text: notificationCountLabel.text
|
||||
id: directChatNotificationCountTextMetrics
|
||||
text: directChatNotificationCountLabel.text
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,6 +225,32 @@ QQC2.Control {
|
||||
}
|
||||
checked: root.selectedSpaceId === roomId
|
||||
onContextMenuRequested: root.createContextMenu(currentRoom)
|
||||
|
||||
QQC2.Label {
|
||||
id: notificationCountLabel
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Kirigami.Units.smallSpacing / 2
|
||||
z: 1
|
||||
width: Math.max(notificationCountTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 2, height)
|
||||
height: Kirigami.Units.iconSizes.smallMedium
|
||||
|
||||
text: spaceDelegate.currentRoom.childrenNotificationCount > 0 ? spaceDelegate.currentRoom.childrenNotificationCount : ""
|
||||
visible: spaceDelegate.currentRoom.childrenNotificationCount > 0 && root.selectedSpaceId != spaceDelegate.roomId
|
||||
color: Kirigami.Theme.textColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
background: Rectangle {
|
||||
visible: true
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Button
|
||||
color: Kirigami.Theme.positiveTextColor
|
||||
radius: height / 2
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: notificationCountTextMetrics
|
||||
text: notificationCountLabel.text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <Quotient/qt_connection_util.h>
|
||||
|
||||
#include "neochatroom.h"
|
||||
#include "roomlistmodel.h"
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
@@ -33,6 +34,15 @@ void SpaceHierarchyCache::cacheSpaceHierarchy()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
connect(neoChatRoom, &NeoChatRoom::unreadStatsChanged, this, [this, neoChatRoom]() {
|
||||
if (neoChatRoom != nullptr) {
|
||||
const auto parents = parentSpaces(neoChatRoom->id());
|
||||
if (parents.count() > 0) {
|
||||
Q_EMIT spaceNotifcationCountChanged(parents);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +84,18 @@ void SpaceHierarchyCache::removeSpaceFromHierarchy(Quotient::Room *room)
|
||||
}
|
||||
}
|
||||
|
||||
QStringList SpaceHierarchyCache::parentSpaces(const QString &roomId)
|
||||
{
|
||||
auto spaces = m_spaceHierarchy.keys();
|
||||
QStringList parents;
|
||||
for (const auto &space : spaces) {
|
||||
if (m_spaceHierarchy[space].contains(roomId)) {
|
||||
parents += space;
|
||||
}
|
||||
}
|
||||
return parents;
|
||||
}
|
||||
|
||||
bool SpaceHierarchyCache::isSpaceChild(const QString &spaceId, const QString &roomId)
|
||||
{
|
||||
return getRoomListForSpace(spaceId, false).contains(roomId);
|
||||
@@ -87,6 +109,31 @@ QList<QString> &SpaceHierarchyCache::getRoomListForSpace(const QString &spaceId,
|
||||
return m_spaceHierarchy[spaceId];
|
||||
}
|
||||
|
||||
qsizetype SpaceHierarchyCache::notificationCountForSpace(const QString &spaceId)
|
||||
{
|
||||
qsizetype notifications = 0;
|
||||
auto children = m_spaceHierarchy[spaceId];
|
||||
QStringList added;
|
||||
|
||||
for (const auto &childId : children) {
|
||||
if (const auto child = static_cast<NeoChatRoom *>(m_connection->room(childId))) {
|
||||
auto category = RoomListModel::category(child);
|
||||
if (!added.contains(child->id()) && child->successorId().isEmpty()) {
|
||||
switch (category) {
|
||||
case NeoChatRoomType::Normal:
|
||||
case NeoChatRoomType::Favorite:
|
||||
notifications += child->notificationCount();
|
||||
break;
|
||||
default:
|
||||
notifications += child->highlightCount();
|
||||
}
|
||||
added += child->id();
|
||||
}
|
||||
}
|
||||
}
|
||||
return notifications;
|
||||
}
|
||||
|
||||
bool SpaceHierarchyCache::isChild(const QString &roomId) const
|
||||
{
|
||||
const auto childrens = m_spaceHierarchy.values();
|
||||
|
||||
@@ -44,6 +44,11 @@ public:
|
||||
return &instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the list of parent spaces for a child if any.
|
||||
*/
|
||||
QStringList parentSpaces(const QString &roomId);
|
||||
|
||||
/**
|
||||
* @brief Whether the given room is a member of the given space.
|
||||
*/
|
||||
@@ -54,6 +59,11 @@ public:
|
||||
*/
|
||||
[[nodiscard]] QList<QString> &getRoomListForSpace(const QString &spaceId, bool updateCache);
|
||||
|
||||
/**
|
||||
* @brief Return the number of notifications for the child rooms in a given space ID.
|
||||
*/
|
||||
qsizetype notificationCountForSpace(const QString &spaceId);
|
||||
|
||||
/**
|
||||
* @brief Returns whether the room is a child space of any space.
|
||||
*
|
||||
@@ -69,6 +79,7 @@ public:
|
||||
Q_SIGNALS:
|
||||
void spaceHierarchyChanged();
|
||||
void connectionChanged();
|
||||
void spaceNotifcationCountChanged(const QStringList &spaces);
|
||||
|
||||
private Q_SLOTS:
|
||||
void addSpaceToHierarchy(Quotient::Room *room);
|
||||
|
||||
Reference in New Issue
Block a user