Add a button to mark spaces as read

[BUG: 508122](https://bugs.kde.org/show_bug.cgi?id=508122)
This commit is contained in:
Azhar Momin
2026-01-24 01:59:51 +05:30
committed by Joshua Goins
parent fb8ee02e3b
commit ade5750550
5 changed files with 109 additions and 0 deletions

View File

@@ -157,12 +157,14 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
if (isSpace()) {
Q_EMIT childrenNotificationCountChanged();
Q_EMIT childrenHaveHighlightNotificationsChanged();
Q_EMIT spaceHasUnreadMessagesChanged();
}
});
connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceNotificationCountChanged, this, [this](const QStringList &spaces) {
if (spaces.contains(id())) {
Q_EMIT childrenNotificationCountChanged();
Q_EMIT childrenHaveHighlightNotificationsChanged();
Q_EMIT spaceHasUnreadMessagesChanged();
}
});
@@ -1906,4 +1908,20 @@ void NeoChatRoom::invalidateLastUnreadHighlightId(const QString &fromEventId, co
}
}
bool NeoChatRoom::spaceHasUnreadMessages() const
{
if (!isSpace()) {
return false;
}
return SpaceHierarchyCache::instance().spaceHasUnreadMessages(id());
}
void NeoChatRoom::markAllChildrenMessagesAsRead()
{
if (isSpace()) {
SpaceHierarchyCache::instance().markAllChildrenMessagesAsRead(id());
}
};
#include "moc_neochatroom.cpp"

View File

@@ -213,6 +213,13 @@ class NeoChatRoom : public Quotient::Room
*/
Q_PROPERTY(bool highlightCycleStarted READ highlightCycleStarted NOTIFY highlightCycleStartedChanged)
/**
* @brief Whether the space has unread messages.
*
* Will always return false if this is not a space.
*/
Q_PROPERTY(bool spaceHasUnreadMessages READ spaceHasUnreadMessages NOTIFY spaceHasUnreadMessagesChanged)
public:
explicit NeoChatRoom(Quotient::Connection *connection, QString roomId, Quotient::JoinState joinState = {});
@@ -652,6 +659,18 @@ public:
*/
bool highlightCycleStarted() const;
/**
* @brief Whether the space has unread messages.
*
* Will always return false if this is not a space.
*/
bool spaceHasUnreadMessages() const;
/**
* @brief Mark the space and all its children messages as read.
*/
Q_INVOKABLE void markAllChildrenMessagesAsRead();
private:
bool m_visible = false;
@@ -722,6 +741,7 @@ Q_SIGNALS:
void inviteTimestampChanged();
void pinnedMessageChanged();
void highlightCycleStartedChanged();
void spaceHasUnreadMessagesChanged();
/**
* @brief Request a message be shown to the user of the given type.

View File

@@ -187,6 +187,21 @@ bool SpaceHierarchyCache::isChild(const QString &roomId) const
return false;
}
bool SpaceHierarchyCache::spaceHasUnreadMessages(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->notificationCount() > 0) {
return true;
}
}
}
return false;
}
NeoChatConnection *SpaceHierarchyCache::connection() const
{
return m_connection;
@@ -239,4 +254,40 @@ void SpaceHierarchyCache::setRecommendedSpaceHidden(bool hidden)
Q_EMIT recommendedSpaceHiddenChanged();
}
void SpaceHierarchyCache::markAllChildrenMessagesAsRead(const QString &spaceId)
{
const auto children = m_spaceHierarchy[spaceId];
for (const auto &childId : children) {
if (const auto child = static_cast<NeoChatRoom *>(m_connection->room(childId))) {
if (child->notificationCount() <= 0) {
continue;
}
if (child->messageEvents().crbegin() == child->historyEdge()) {
if (!child->eventsHistoryJob()) {
if (child->allHistoryLoaded()) {
continue;
}
child->getPreviousContent();
}
connect(
child,
&NeoChatRoom::addedMessages,
child,
[child] {
if (child->messageEvents().crbegin() != child->historyEdge()) {
child->markAllMessagesAsRead();
}
},
Qt::SingleShotConnection);
} else {
child->markAllMessagesAsRead();
}
}
}
}
#include "moc_spacehierarchycache.cpp"

View File

@@ -84,6 +84,11 @@ public:
*/
[[nodiscard]] bool isChild(const QString &roomId) const;
/**
* @brief Return whether the given space has unread messages.
*/
bool spaceHasUnreadMessages(const QString &spaceId);
NeoChatConnection *connection() const;
void setConnection(NeoChatConnection *connection);
@@ -95,6 +100,8 @@ public:
bool recommendedSpaceHidden() const;
void setRecommendedSpaceHidden(bool hidden);
void markAllChildrenMessagesAsRead(const QString &spaceId);
Q_SIGNALS:
void spaceHierarchyChanged();
void connectionChanged();

View File

@@ -40,6 +40,19 @@ KirigamiComponents.ConvergentContextMenu {
}
}
QQC2.Action {
text: i18nc("@action:inmenu", "Mark Space as Read")
icon.name: "checkmark"
enabled: root.room.spaceHasUnreadMessages
onTriggered: {
root.room.markAllChildrenMessagesAsRead();
}
}
Kirigami.Action {
separator: true
}
QQC2.Action {
text: i18nc("'Space' is a matrix space", "View Space")
icon.name: "view-list-details"