Notification Consistency

Make sure that the new rules for counting notifications for muted, mention and low priority rooms is applied consistently to the room list, space drawer and the task manager notification badge

implements #644
This commit is contained in:
James Graham
2024-03-01 17:56:13 +00:00
parent 943f6c762c
commit f557ceda19
15 changed files with 238 additions and 154 deletions

View File

@@ -26,6 +26,7 @@
#include <Quotient/qt_connection_util.h>
#include "neochatconfig.h"
#include "neochatconnection.h"
#include "neochatroom.h"
#include "notificationsmanager.h"
#include "proxycontroller.h"
@@ -37,6 +38,14 @@
#include "trayicon_sni.h"
#endif
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
#ifndef Q_OS_ANDROID
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusMessage>
#endif
#endif
bool testMode = false;
using namespace Quotient;
@@ -149,6 +158,7 @@ void Controller::addConnection(NeoChatConnection *c)
connect(c, &NeoChatConnection::loggedOut, this, [this, c] {
dropConnection(c);
});
connect(c, &NeoChatConnection::badgeNotificationCountChanged, this, &Controller::updateBadgeNotificationCount);
c->sync();
@@ -291,7 +301,14 @@ void Controller::setActiveConnection(NeoChatConnection *connection)
if (connection == m_connection) {
return;
}
m_connection = connection;
if (m_connection != nullptr) {
m_connection->refreshBadgeNotificationCount();
updateBadgeNotificationCount(m_connection, m_connection->badgeNotificationCount());
}
Q_EMIT activeConnectionChanged();
}
@@ -316,6 +333,36 @@ void Controller::listenForNotifications()
#endif
}
void Controller::updateBadgeNotificationCount(NeoChatConnection *connection, int count)
{
if (connection == m_connection) {
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
#ifndef Q_OS_ANDROID
// copied from Telegram desktop
const auto launcherUrl = "application://org.kde.neochat.desktop"_ls;
// Gnome requires that count is a 64bit integer
const qint64 counterSlice = std::min(count, 9999);
QVariantMap dbusUnityProperties;
if (counterSlice > 0) {
dbusUnityProperties["count"_ls] = counterSlice;
dbusUnityProperties["count-visible"_ls] = true;
} else {
dbusUnityProperties["count-visible"_ls] = false;
}
auto signal = QDBusMessage::createSignal("/com/canonical/unity/launcherentry/neochat"_ls, "com.canonical.Unity.LauncherEntry"_ls, "Update"_ls);
signal.setArguments({launcherUrl, dbusUnityProperties});
QDBusConnection::sessionBus().send(signal);
#endif // Q_OS_ANDROID
#else
qGuiApp->setBadgeNumber(count);
#endif // QT_VERSION_CHECK(6, 6, 0)
}
}
bool Controller::isFlatpak() const
{
#ifdef NEOCHAT_FLATPAK

View File

@@ -117,6 +117,7 @@ private:
private Q_SLOTS:
void invokeLogin();
void setQuitOnLastWindowClosed();
void updateBadgeNotificationCount(NeoChatConnection *connection, int count);
Q_SIGNALS:
void errorOccured(const QString &error, const QString &detail);

View File

@@ -9,17 +9,7 @@
#include "roommanager.h"
#include "spacehierarchycache.h"
#include <QDebug>
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
#ifndef Q_OS_ANDROID
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusMessage>
#endif
#endif
#include <KLocalizedString>
#include <QGuiApplication>
using namespace Quotient;
@@ -28,32 +18,6 @@ Q_DECLARE_METATYPE(Quotient::JoinState)
RoomListModel::RoomListModel(QObject *parent)
: QAbstractListModel(parent)
{
connect(this, &RoomListModel::highlightCountChanged, this, [this]() {
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
#ifndef Q_OS_ANDROID
// copied from Telegram desktop
const auto launcherUrl = "application://org.kde.neochat.desktop"_ls;
// Gnome requires that count is a 64bit integer
const qint64 counterSlice = std::min(m_highlightCount, 9999);
QVariantMap dbusUnityProperties;
if (counterSlice > 0) {
dbusUnityProperties["count"_ls] = counterSlice;
dbusUnityProperties["count-visible"_ls] = true;
} else {
dbusUnityProperties["count-visible"_ls] = false;
}
auto signal = QDBusMessage::createSignal("/com/canonical/unity/launcherentry/neochat"_ls, "com.canonical.Unity.LauncherEntry"_ls, "Update"_ls);
signal.setArguments({launcherUrl, dbusUnityProperties});
QDBusConnection::sessionBus().send(signal);
#endif // Q_OS_ANDROID
#else
qGuiApp->setBadgeNumber(m_highlightCount);
#endif // QT_VERSION_CHECK(6, 6, 0)
});
connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() {
Q_EMIT dataChanged(index(0, 0), index(rowCount(), 0), {IsChildSpaceRole});
});
@@ -122,7 +86,6 @@ void RoomListModel::doResetModel()
doAddRoom(room);
}
endResetModel();
refreshNotificationCount();
}
NeoChatRoom *RoomListModel::roomAt(int row) const
@@ -148,7 +111,7 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room)
refresh(room, {DisplayNameRole});
});
connect(room, &Room::unreadStatsChanged, this, [this, room] {
refresh(room, {NotificationCountRole, HighlightCountRole});
refresh(room, {ContextNotificationCountRole, HasHighlightNotificationsRole});
});
connect(room, &Room::notificationCountChanged, this, [this, room] {
refresh(room);
@@ -171,44 +134,6 @@ void RoomListModel::connectRoomSignals(NeoChatRoom *room)
connect(room, &Room::pendingEventMerged, this, [this, room] {
refresh(room, {SubtitleTextRole});
});
connect(room, &Room::unreadStatsChanged, this, &RoomListModel::refreshNotificationCount);
connect(room, &Room::highlightCountChanged, this, &RoomListModel::refreshHighlightCount);
}
int RoomListModel::notificationCount() const
{
return m_notificationCount;
}
int RoomListModel::highlightCount() const
{
return m_highlightCount;
}
void RoomListModel::refreshNotificationCount()
{
int count = 0;
for (auto room : std::as_const(m_rooms)) {
count += room->notificationCount();
}
if (m_notificationCount == count) {
return;
}
m_notificationCount = count;
Q_EMIT notificationCountChanged();
}
void RoomListModel::refreshHighlightCount()
{
int count = 0;
for (auto room : std::as_const(m_rooms)) {
count += room->highlightCount();
}
if (m_highlightCount == count) {
return;
}
m_highlightCount = count;
Q_EMIT highlightCountChanged();
}
void RoomListModel::updateRoom(Room *room, Room *prev)
@@ -295,11 +220,11 @@ QVariant RoomListModel::data(const QModelIndex &index, int role) const
if (role == CategoryRole) {
return NeoChatRoomType::typeForRoom(room);
}
if (role == NotificationCountRole) {
return room->notificationCount();
if (role == ContextNotificationCountRole) {
return room->contextAwareNotificationCount();
}
if (role == HighlightCountRole) {
return room->highlightCount();
if (role == HasHighlightNotificationsRole) {
return room->highlightCount() > 0 && room->contextAwareNotificationCount() > 0;
}
if (role == LastActiveTimeRole) {
return room->lastActiveTime();
@@ -361,8 +286,8 @@ QHash<int, QByteArray> RoomListModel::roleNames() const
roles[CanonicalAliasRole] = "canonicalAlias";
roles[TopicRole] = "topic";
roles[CategoryRole] = "category";
roles[NotificationCountRole] = "notificationCount";
roles[HighlightCountRole] = "highlightCount";
roles[ContextNotificationCountRole] = "contextNotificationCount";
roles[HasHighlightNotificationsRole] = "hasHighlightNotifications";
roles[LastActiveTimeRole] = "lastActiveTime";
roles[JoinStateRole] = "joinState";
roles[CurrentRoomRole] = "currentRoom";

View File

@@ -31,11 +31,6 @@ class RoomListModel : public QAbstractListModel
*/
Q_PROPERTY(Quotient::Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
/**
* @brief The total number of notifications for all the rooms.
*/
Q_PROPERTY(int notificationCount READ notificationCount NOTIFY notificationCountChanged)
public:
/**
* @brief Defines the model roles.
@@ -46,8 +41,8 @@ public:
CanonicalAliasRole, /**< The room canonical alias. */
TopicRole, /**< The room topic. */
CategoryRole, /**< The room category, e.g favourite. */
NotificationCountRole, /**< The number of notifications in the room. */
HighlightCountRole, /**< The number of highlighted messages in the room. */
ContextNotificationCountRole, /**< The context aware notification count for the room. */
HasHighlightNotificationsRole, /**< Whether there are any highlight notifications. */
LastActiveTimeRole, /**< The timestamp of the last event sent in the room. */
JoinStateRole, /**< The local user's join state in the room. */
CurrentRoomRole, /**< The room object for the room. */
@@ -67,9 +62,6 @@ public:
[[nodiscard]] Quotient::Connection *connection() const;
void setConnection(Quotient::Connection *connection);
[[nodiscard]] int notificationCount() const;
[[nodiscard]] int highlightCount() const;
/**
* @brief Get the given role value at the given index.
*
@@ -114,23 +106,16 @@ private Q_SLOTS:
void updateRoom(Quotient::Room *room, Quotient::Room *prev);
void deleteRoom(Quotient::Room *room);
void refresh(NeoChatRoom *room, const QList<int> &roles = {});
void refreshNotificationCount();
void refreshHighlightCount();
private:
Quotient::Connection *m_connection = nullptr;
QList<NeoChatRoom *> m_rooms;
int m_notificationCount = 0;
int m_highlightCount = 0;
QString m_activeSpaceId;
void connectRoomSignals(NeoChatRoom *room);
Q_SIGNALS:
void connectionChanged();
void notificationCountChanged();
void highlightCountChanged();
void roomAdded(NeoChatRoom *_t1);
};

View File

@@ -127,7 +127,7 @@ void RoomTreeModel::connectRoomSignals(NeoChatRoom *room)
refreshRoomRoles(room, {DisplayNameRole});
});
connect(room, &Room::unreadStatsChanged, this, [this, room] {
refreshRoomRoles(room, {NotificationCountRole, HighlightCountRole});
refreshRoomRoles(room, {ContextNotificationCountRole, HasHighlightNotificationsRole});
});
connect(room, &Room::avatarChanged, this, [this, room] {
refreshRoomRoles(room, {AvatarRole});
@@ -144,6 +144,9 @@ void RoomTreeModel::connectRoomSignals(NeoChatRoom *room)
connect(room, &Room::pendingEventMerged, this, [this, room] {
refreshRoomRoles(room, {SubtitleTextRole});
});
connect(room, &NeoChatRoom::pushNotificationStateChanged, this, [this, room] {
refreshRoomRoles(room, {ContextNotificationCountRole, HasHighlightNotificationsRole});
});
}
void RoomTreeModel::refreshRoomRoles(NeoChatRoom *room, const QList<int> &roles)
@@ -208,8 +211,8 @@ QHash<int, QByteArray> RoomTreeModel::roleNames() const
roles[CanonicalAliasRole] = "canonicalAlias";
roles[TopicRole] = "topic";
roles[CategoryRole] = "category";
roles[NotificationCountRole] = "notificationCount";
roles[HighlightCountRole] = "highlightCount";
roles[ContextNotificationCountRole] = "contextNotificationCount";
roles[HasHighlightNotificationsRole] = "hasHighlightNotifications";
roles[LastActiveTimeRole] = "lastActiveTime";
roles[JoinStateRole] = "joinState";
roles[CurrentRoomRole] = "currentRoom";
@@ -271,11 +274,11 @@ QVariant RoomTreeModel::data(const QModelIndex &index, int role) const
if (role == CategoryRole) {
return NeoChatRoomType::typeForRoom(room);
}
if (role == NotificationCountRole) {
return int(room->notificationCount());
if (role == ContextNotificationCountRole) {
return int(room->contextAwareNotificationCount());
}
if (role == HighlightCountRole) {
return int(room->highlightCount());
if (role == HasHighlightNotificationsRole) {
return room->highlightCount() > 0 && room->contextAwareNotificationCount() > 0;
}
if (role == LastActiveTimeRole) {
return room->lastActiveTime();

View File

@@ -33,8 +33,8 @@ public:
CanonicalAliasRole, /**< The room canonical alias. */
TopicRole, /**< The room topic. */
CategoryRole, /**< The room category, e.g favourite. */
NotificationCountRole, /**< The number of notifications in the room. */
HighlightCountRole, /**< The number of highlighted messages in the room. */
ContextNotificationCountRole, /**< The context aware notification count for the room. */
HasHighlightNotificationsRole, /**< Whether there are any highlight notifications. */
LastActiveTimeRole, /**< The timestamp of the last event sent in the room. */
JoinStateRole, /**< The local user's join state in the room. */
CurrentRoomRole, /**< The room object for the room. */

View File

@@ -52,8 +52,8 @@ static const QVector<RoomTreeModel::EventRoles> activitySortPriorities{
// Anything useful at the top, quiet rooms at the bottom
RoomTreeModel::AttentionRole,
// Organize by highlights, notifications, unread favorites, all other unread, in that order
RoomTreeModel::HighlightCountRole,
RoomTreeModel::NotificationCountRole,
RoomTreeModel::HasHighlightNotificationsRole,
RoomTreeModel::ContextNotificationCountRole,
RoomTreeModel::FavouriteRole,
// Finally sort by last activity time
RoomTreeModel::LastActiveTimeRole,

View File

@@ -77,7 +77,9 @@ void NeoChatConnection::connectSignals()
for (const auto &chatId : additions) {
if (const auto chat = room(chatId)) {
connect(chat, &Room::unreadStatsChanged, this, [this]() {
refreshBadgeNotificationCount();
Q_EMIT directChatNotificationsChanged();
Q_EMIT directChatsHaveHighlightNotificationsChanged();
});
}
}
@@ -91,29 +93,51 @@ void NeoChatConnection::connectSignals()
if (room->isDirectChat()) {
connect(room, &Room::unreadStatsChanged, this, [this]() {
Q_EMIT directChatNotificationsChanged();
Q_EMIT directChatsHaveHighlightNotificationsChanged();
});
}
connect(room, &Room::unreadStatsChanged, this, [this]() {
refreshBadgeNotificationCount();
Q_EMIT homeNotificationsChanged();
Q_EMIT homeHaveHighlightNotificationsChanged();
});
});
connect(this, &NeoChatConnection::leftRoom, this, [this](Room *room, Room *prev) {
Q_UNUSED(room)
if (prev && prev->isDirectChat()) {
Q_EMIT directChatInvitesChanged();
Q_EMIT directChatNotificationsChanged();
Q_EMIT directChatsHaveHighlightNotificationsChanged();
}
refreshBadgeNotificationCount();
Q_EMIT homeNotificationsChanged();
Q_EMIT homeHaveHighlightNotificationsChanged();
});
connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() {
refreshBadgeNotificationCount();
Q_EMIT homeNotificationsChanged();
Q_EMIT homeHaveHighlightNotificationsChanged();
});
for (const auto room : allRooms()) {
connect(room, &NeoChatRoom::unreadStatsChanged, this, [this, room]() {
if (room != nullptr) {
auto category = NeoChatRoomType::typeForRoom(static_cast<NeoChatRoom *>(room));
if (!SpaceHierarchyCache::instance().isChild(room->id()) && (category == NeoChatRoomType::Normal || category == NeoChatRoomType::Favorite)
&& room->successorId().isEmpty()) {
Q_EMIT homeNotificationsChanged();
}
}
});
}
int NeoChatConnection::badgeNotificationCount() const
{
return m_badgeNotificationCount;
}
void NeoChatConnection::refreshBadgeNotificationCount()
{
int count = 0;
for (const auto &r : allRooms()) {
if (const auto room = static_cast<NeoChatRoom *>(r)) {
count += room->contextAwareNotificationCount();
}
}
if (count != m_badgeNotificationCount) {
m_badgeNotificationCount = count;
Q_EMIT badgeNotificationCountChanged(this, m_badgeNotificationCount);
}
}
@@ -329,7 +353,7 @@ qsizetype NeoChatConnection::directChatNotifications() const
for (const auto &chatId : directChats()) {
if (!added.contains(chatId)) {
if (const auto chat = room(chatId)) {
notifications += chat->notificationCount();
notifications += dynamic_cast<NeoChatRoom *>(chat)->contextAwareNotificationCount();
added += chatId;
}
}
@@ -337,29 +361,47 @@ qsizetype NeoChatConnection::directChatNotifications() const
return notifications;
}
bool NeoChatConnection::directChatsHaveHighlightNotifications() const
{
for (const auto &childId : directChats()) {
if (const auto child = static_cast<NeoChatRoom *>(room(childId))) {
if (child->highlightCount() > 0) {
return true;
}
}
}
return false;
}
qsizetype NeoChatConnection::homeNotifications() const
{
qsizetype notifications = 0;
QStringList added;
const auto &spaceHierarchyCache = SpaceHierarchyCache::instance();
for (const auto &room : allRooms()) {
auto category = NeoChatRoomType::typeForRoom(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();
for (const auto &r : allRooms()) {
if (const auto room = static_cast<NeoChatRoom *>(r)) {
if (!added.contains(room->id()) && !room->isDirectChat() && !spaceHierarchyCache.isChild(room->id())) {
notifications += dynamic_cast<NeoChatRoom *>(room)->contextAwareNotificationCount();
added += room->id();
}
added += room->id();
}
}
return notifications;
}
bool NeoChatConnection::homeHaveHighlightNotifications() const
{
const auto &spaceHierarchyCache = SpaceHierarchyCache::instance();
for (const auto &r : allRooms()) {
if (const auto room = static_cast<NeoChatRoom *>(r)) {
if (!room->isDirectChat() && !spaceHierarchyCache.isChild(room->id()) && room->highlightCount() > 0) {
return true;
}
}
}
return false;
}
bool NeoChatConnection::directChatInvites() const
{
auto inviteRooms = rooms(JoinState::Invite);

View File

@@ -32,11 +32,21 @@ class NeoChatConnection : public Quotient::Connection
*/
Q_PROPERTY(qsizetype directChatNotifications READ directChatNotifications NOTIFY directChatNotificationsChanged)
/**
* @brief Whether any direct chats have highlight notifications.
*/
Q_PROPERTY(bool directChatsHaveHighlightNotifications READ directChatsHaveHighlightNotifications NOTIFY directChatsHaveHighlightNotificationsChanged)
/**
* @brief The total number of notifications for all rooms in the home tab.
*/
Q_PROPERTY(qsizetype homeNotifications READ homeNotifications NOTIFY homeNotificationsChanged)
/**
* @brief Whether any of the rooms in the home tab have highlight notifications.
*/
Q_PROPERTY(bool homeHaveHighlightNotifications READ homeHaveHighlightNotifications NOTIFY homeHaveHighlightNotificationsChanged)
/**
* @brief Whether there is at least one invite to a direct chat.
*/
@@ -119,7 +129,13 @@ public:
Q_INVOKABLE QString accountDataJsonString(const QString &type) const;
qsizetype directChatNotifications() const;
bool directChatsHaveHighlightNotifications() const;
qsizetype homeNotifications() const;
bool homeHaveHighlightNotifications() const;
int badgeNotificationCount() const;
void refreshBadgeNotificationCount();
bool directChatInvites() const;
// note: this is intentionally a copied QString because
@@ -134,15 +150,20 @@ public:
Q_SIGNALS:
void labelChanged();
void directChatNotificationsChanged();
void directChatsHaveHighlightNotificationsChanged();
void homeNotificationsChanged();
void homeHaveHighlightNotificationsChanged();
void directChatInvitesChanged();
void isOnlineChanged();
void passwordStatus(NeoChatConnection::PasswordStatus status);
void userConsentRequired(QUrl url);
void badgeNotificationCountChanged(NeoChatConnection *connection, int count);
private:
bool m_isOnline = true;
void setIsOnline(bool isOnline);
void connectSignals();
int m_badgeNotificationCount = 0;
};

View File

@@ -10,6 +10,7 @@
#include <QTemporaryFile>
#include <Quotient/jobs/basejob.h>
#include <Quotient/quotient_common.h>
#include <Quotient/user.h>
#include <qcoro/qcorosignal.h>
@@ -129,15 +130,32 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() {
if (isSpace()) {
Q_EMIT childrenNotificationCountChanged();
Q_EMIT childrenHaveHighlightNotificationsChanged();
}
});
connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceNotifcationCountChanged, this, [this](const QStringList &spaces) {
if (spaces.contains(id())) {
Q_EMIT childrenNotificationCountChanged();
Q_EMIT childrenHaveHighlightNotificationsChanged();
}
});
}
int NeoChatRoom::contextAwareNotificationCount() const
{
// DOn't include spaces, rooms that the user hasn't joined and rooms where the user has joined the successor.
if (isSpace() || joinState() != JoinState::Join || successor(JoinState::Join) != nullptr) {
return 0;
}
if (m_currentPushNotificationState == PushNotificationState::Mute) {
return 0;
}
if (m_currentPushNotificationState == PushNotificationState::MentionKeyword || isLowPriority()) {
return int(highlightCount());
}
return int(notificationCount());
}
bool NeoChatRoom::hasFileUploading() const
{
return m_hasFileUploading;
@@ -1300,6 +1318,14 @@ qsizetype NeoChatRoom::childrenNotificationCount()
return SpaceHierarchyCache::instance().notificationCountForSpace(id());
}
bool NeoChatRoom::childrenHaveHighlightNotifications() const
{
if (!isSpace()) {
return false;
}
return SpaceHierarchyCache::instance().spaceHasHighlightNotifications(id());
}
void NeoChatRoom::addChild(const QString &childId, bool setChildParent, bool canonical, bool suggested)
{
if (!isSpace()) {

View File

@@ -133,6 +133,13 @@ class NeoChatRoom : public Quotient::Room
*/
Q_PROPERTY(qsizetype childrenNotificationCount READ childrenNotificationCount NOTIFY childrenNotificationCountChanged)
/**
* @brief Whether this room's children have any highlight notifications.
*
* Will always return false if this is not a space.
*/
Q_PROPERTY(bool childrenHaveHighlightNotifications READ childrenHaveHighlightNotifications NOTIFY childrenHaveHighlightNotificationsChanged)
/**
* @brief Whether the local user has an invite to the room.
*
@@ -405,6 +412,16 @@ public:
*/
[[nodiscard]] bool lastEventIsSpoiler() const;
/**
* @brief Return the notification count for the room accounting for tags and notification state.
*
* The following rules are observed:
* - Rooms tagged as low priority or mentions and keywords notification state
* only return the number of highlights.
* - Muted rooms always return 0.
*/
int contextAwareNotificationCount() const;
[[nodiscard]] bool hasFileUploading() const;
void setHasFileUploading(bool value);
@@ -535,6 +552,8 @@ public:
qsizetype childrenNotificationCount();
bool childrenHaveHighlightNotifications() const;
/**
* @brief Add the given room as a child.
*
@@ -825,6 +844,7 @@ Q_SIGNALS:
void canonicalParentChanged();
void lastActiveTimeChanged();
void childrenNotificationCountChanged();
void childrenHaveHighlightNotificationsChanged();
void isInviteChanged();
void readOnlyChanged();
void displayNameChanged();

View File

@@ -18,8 +18,8 @@ Delegates.RoundedItemDelegate {
id: root
required property int index
required property int notificationCount
required property int highlightCount
required property int contextNotificationCount
required property bool hasHighlightNotifications
required property NeoChatRoom currentRoom
required property NeoChatConnection connection
required property string avatar
@@ -28,7 +28,7 @@ Delegates.RoundedItemDelegate {
property bool collapsed: false
readonly property bool hasNotifications: currentRoom.pushNotificationState === PushNotificationState.MentionKeyword || currentRoom.isLowPriority ? highlightCount > 0 : notificationCount > 0
readonly property bool hasNotifications: contextNotificationCount > 0
Accessible.name: root.displayName
Accessible.onPressAction: clicked()
@@ -106,16 +106,16 @@ Delegates.RoundedItemDelegate {
QQC2.Label {
id: notificationCountLabel
text: currentRoom.pushNotificationState === PushNotificationState.MentionKeyword || currentRoom.isLowPriority ? root.highlightCount : root.notificationCount
visible: root.hasNotifications && currentRoom.pushNotificationState !== PushNotificationState.Mute && !root.collapsed
text: root.contextNotificationCount
visible: root.hasNotifications && !root.collapsed
color: Kirigami.Theme.textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
background: Rectangle {
visible: root.hasNotifications
Kirigami.Theme.colorSet: Kirigami.Theme.Button
color: highlightCount > 0 ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.disabledTextColor
opacity: highlightCount > 0 ? 1 : 0.3
Kirigami.Theme.inherit: false
color: root.hasHighlightNotifications > 0 ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.backgroundColor
radius: height / 2
}
@@ -141,7 +141,7 @@ Delegates.RoundedItemDelegate {
}
function createRoomListContextMenu() {
const component = Qt.createComponent(Qt.createComponent('org.kde.neochat', 'ContextMenu.qml'));
const component = Qt.createComponent('org.kde.neochat', 'ContextMenu.qml');
if (component.status === Component.Error) {
console.error(component.errorString());
}

View File

@@ -125,7 +125,8 @@ QQC2.Control {
background: Rectangle {
visible: true
Kirigami.Theme.colorSet: Kirigami.Theme.Button
color: Kirigami.Theme.positiveTextColor
Kirigami.Theme.inherit: false
color: root.connection.homeHaveHighlightNotifications ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.backgroundColor
radius: height / 2
}
@@ -173,7 +174,8 @@ QQC2.Control {
background: Rectangle {
visible: true
Kirigami.Theme.colorSet: Kirigami.Theme.Button
color: Kirigami.Theme.positiveTextColor
Kirigami.Theme.inherit: false
color: root.connection.directChatsHaveHighlightNotifications ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.backgroundColor
radius: height / 2
}
@@ -239,10 +241,12 @@ QQC2.Control {
visible: spaceDelegate.currentRoom.childrenNotificationCount > 0 && root.selectedSpaceId != spaceDelegate.roomId
color: Kirigami.Theme.textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
background: Rectangle {
visible: true
Kirigami.Theme.colorSet: Kirigami.Theme.Button
color: Kirigami.Theme.positiveTextColor
Kirigami.Theme.inherit: false
color: spaceDelegate.currentRoom.childrenHaveHighlightNotifications ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.backgroundColor
radius: height / 2
}

View File

@@ -126,16 +126,8 @@ qsizetype SpaceHierarchyCache::notificationCountForSpace(const QString &spaceId)
for (const auto &childId : children) {
if (const auto child = static_cast<NeoChatRoom *>(m_connection->room(childId))) {
auto category = NeoChatRoomType::typeForRoom(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();
}
if (!added.contains(child->id())) {
notifications += child->contextAwareNotificationCount();
added += child->id();
}
}
@@ -143,6 +135,19 @@ qsizetype SpaceHierarchyCache::notificationCountForSpace(const QString &spaceId)
return notifications;
}
bool SpaceHierarchyCache::spaceHasHighlightNotifications(const QString &spaceId)
{
auto children = m_spaceHierarchy[spaceId];
for (const auto &childId : children) {
if (const auto child = static_cast<NeoChatRoom *>(m_connection->room(childId))) {
if (child->highlightCount() > 0) {
return true;
}
}
}
return false;
}
bool SpaceHierarchyCache::isChild(const QString &roomId) const
{
const auto childrens = m_spaceHierarchy.values();

View File

@@ -69,6 +69,11 @@ public:
*/
qsizetype notificationCountForSpace(const QString &spaceId);
/**
* @brief Whether any of the child rooms have highlight notifications.
*/
bool spaceHasHighlightNotifications(const QString &spaceId);
/**
* @brief Returns whether the room is a child space of any space.
*