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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user