[network/neochat] src: This moves the handling of typing notifications out of ChatBarMessageContentModel in the continued effort to remove its dependence on room. This also conveniently hooks up an isEmpty parameter and contentChanged signal which will be used for more going forward.
James Graham <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 0b17b8dd78f7c7287c84067fa927940fbad4edb7 by James Graham.
Committed on 05/08/2026 at 15:34.
Pushed by nvrwhere into branch 'master'.
This moves the handling of typing notifications out of ChatBarMessageContentModel in the continued effort to remove its dependence on room. This also conveniently hooks up an isEmpty parameter and contentChanged signal which will be used for more going forward.
M +2 -0 src/app/qml/RoomPage.qml
M +4 -0 src/app/roommanager.cpp
M +6 -0 src/chatbar/ChatBar.qml
M +6 -1 src/chatbar/ChatBarCore.qml
M +17 -1 src/libneochat/neochatroom.cpp
M +5 -0 src/libneochat/neochatroom.h
M +4 -38 src/messagecontent/models/chatbarmessagecontentmodel.cpp
M +3 -14 src/messagecontent/models/chatbarmessagecontentmodel.h
https://invent.kde.org/network/neochat/-/commit/0b17b8dd78f7c7287c84067fa927940fbad4edb7
diff --git a/src/app/qml/RoomPage.qml b/src/app/qml/RoomPage.qml
index fc143fe71..c59a765f0 100644
--- a/src/app/qml/RoomPage.qml
+++ b/src/app/qml/RoomPage.qml
@@ -312,6 +312,8 @@ Kirigami.Page {
width: parent.width
currentRoom: root.currentRoom
+ onContentChanged: root.currentRoom.sendTypingNotification(!isEmpty)
+
// Creating a reply (or doing anything in the chat bar) can change the height, but this isn't picked up on the root's onHeightChanged.
onHeightChanged: root.resetViewSettling()
}
diff --git a/src/app/roommanager.cpp b/src/app/roommanager.cpp
index 47b36c0aa..83e11f1e8 100644
--- a/src/app/roommanager.cpp
+++ b/src/app/roommanager.cpp
@@ -92,6 +92,10 @@ RoomManager::RoomManager(QObject *parent)
m_roomListModel->setConnection(m_connection);
m_roomTreeModel->setConnection(m_connection);
});
+ NeoChatRoom::setTypingNotificationsActive(NeoChatConfig::self()->typingNotifications());
+ connect(NeoChatConfig::self(), &NeoChatConfig::TypingNotificationsChanged, this, [] {
+ NeoChatRoom::setTypingNotificationsActive(NeoChatConfig::self()->typingNotifications());
+ });
connect(m_sortFilterSpaceListModel, &SortFilterSpaceListModel::layoutChanged, m_sortFilterRoomTreeModel, &SortFilterRoomTreeModel::invalidate);
connect(&ActionsModel::instance(), &ActionsModel::resolveResource, this, [this](const QString &idOrUri, const QString &action) {
resolveResource(idOrUri, action);
diff --git a/src/chatbar/ChatBar.qml b/src/chatbar/ChatBar.qml
index cbc335b26..2dc4c3ab1 100644
--- a/src/chatbar/ChatBar.qml
+++ b/src/chatbar/ChatBar.qml
@@ -44,6 +44,10 @@ Item {
property alias model: core.model
+ readonly property alias isEmpty: core.isEmpty
+
+ signal contentChanged
+
onActiveFocusChanged: if (activeFocus) {
core.forceActiveFocus();
}
@@ -83,6 +87,8 @@ Item {
room: root.currentRoom
maxAvailableWidth: chatBarSizeHelper.availableWidth
visible: !root.currentRoom.readOnly
+
+ onContentChanged: root.contentChanged()
}
QQC2.Label {
visible: root.currentRoom.readOnly
diff --git a/src/chatbar/ChatBarCore.qml b/src/chatbar/ChatBarCore.qml
index f03211013..30ce5ab66 100644
--- a/src/chatbar/ChatBarCore.qml
+++ b/src/chatbar/ChatBarCore.qml
@@ -30,9 +30,14 @@ QQC2.Control {
threadRootId: root.threadRootId
room: root.room
sendMessageWithEnter: NeoChatConfig.sendMessageWith === 0
- sendTypingNotifications: NeoChatConfig.typingNotifications
+
+ onContentChanged: root.contentChanged()
}
+ readonly property bool isEmpty: !model.hasAnyContent
+
+ signal contentChanged
+
signal cancel
Connections {
diff --git a/src/libneochat/neochatroom.cpp b/src/libneochat/neochatroom.cpp
index 532735f8c..aa0e20f55 100644
--- a/src/libneochat/neochatroom.cpp
+++ b/src/libneochat/neochatroom.cpp
@@ -68,12 +68,15 @@
using namespace Quotient;
using namespace std::ranges::views;
+bool NeoChatRoom::m_typingNotificationActive = true;
+
std::function<bool(const Quotient::RoomEvent *)> NeoChatRoom::m_hiddenFilter = [](const Quotient::RoomEvent *) -> bool {
return false;
};
NeoChatRoom::NeoChatRoom(Connection *c, QString roomId, JoinState joinState)
: Room(c, std::move(roomId), joinState)
+ , m_typingTimer(new QTimer(this))
{
const auto connection = static_cast<NeoChatConnection *>(c);
Q_ASSERT(connection);
@@ -82,6 +85,9 @@ NeoChatRoom::NeoChatRoom(Connection *c, QString roomId, JoinState joinState)
m_editCache = new ChatBarCache(this);
m_threadCache = new ChatBarCache(this);
+ m_typingTimer->setInterval(std::chrono::milliseconds(5000));
+ m_typingTimer->setSingleShot(true);
+
connect(connection, &Connection::accountDataChanged, this, &NeoChatRoom::updatePushNotificationState);
connect(this, &Room::fileTransferCompleted, this, [this] {
setFileUploadingProgress(0);
@@ -369,12 +375,22 @@ void NeoChatRoom::forget()
}
}
+void NeoChatRoom::setTypingNotificationsActive(bool typingNotificationActive)
+{
+ m_typingNotificationActive = typingNotificationActive;
+}
+
void NeoChatRoom::sendTypingNotification(bool isTyping)
{
// During the chatbar setup sequence, this may get called while we're still initializing
- if (localMember().isEmpty()) {
+ if (localMember().isEmpty() || !m_typingNotificationActive || m_typingTimer->isActive() == isTyping) {
return;
}
+ if (!m_typingTimer->isActive() && isTyping) {
+ m_typingTimer->start();
+ } else if (m_typingTimer->isActive() && !isTyping) {
+ m_typingTimer->stop();
+ }
connection()->callApi<SetTypingJob>(BackgroundRequest, localMember().id(), id(), isTyping, 10000);
}
diff --git a/src/libneochat/neochatroom.h b/src/libneochat/neochatroom.h
index c734b23e4..6e90cad8c 100644
--- a/src/libneochat/neochatroom.h
+++ b/src/libneochat/neochatroom.h
@@ -741,6 +741,8 @@ public:
*/
Q_INVOKABLE QString forwardMessage(NeoChatRoom *targetRoom, const QString &eventId);
+ static void setTypingNotificationsActive(bool typingNotificationActive);
+
private:
bool m_visible = false;
@@ -778,6 +780,9 @@ private:
QString m_lastUnreadHighlightId;
QList<QString> m_sortedMemberIds;
+ static bool m_typingNotificationActive;
+ QTimer *m_typingTimer;
+
private Q_SLOTS:
void updatePushNotificationState(QString type);
diff --git a/src/messagecontent/models/chatbarmessagecontentmodel.cpp b/src/messagecontent/models/chatbarmessagecontentmodel.cpp
index 7165851b5..c7df81393 100644
--- a/src/messagecontent/models/chatbarmessagecontentmodel.cpp
+++ b/src/messagecontent/models/chatbarmessagecontentmodel.cpp
@@ -33,13 +33,9 @@ ChatBarMessageContentModel::ChatBarMessageContentModel(QObject *parent)
: MessageContentModel(parent)
, m_markdownHelper(new ChatMarkdownHelper(this))
, m_keyHelper(new ChatKeyHelper(this))
- , m_typingTimer(new QTimer(this))
{
m_editableActive = true;
- m_typingTimer->setInterval(std::chrono::milliseconds(5000));
- m_typingTimer->setSingleShot(true);
-
connect(this, &ChatBarMessageContentModel::roomChanged, this, [this](NeoChatRoom *oldRoom) {
if (m_type == ChatBarType::None || !m_room) {
return;
@@ -82,9 +78,9 @@ ChatBarMessageContentModel::ChatBarMessageContentModel(QObject *parent)
initializeFromCache();
});
connect(m_markdownHelper, &ChatMarkdownHelper::unhandledBlockFormat, this, &ChatBarMessageContentModel::insertStyleAtCursor);
- connect(this, &ChatBarMessageContentModel::modelReset, this, &ChatBarMessageContentModel::hasAnyContentChanged);
- connect(this, &ChatBarMessageContentModel::rowsInserted, this, &ChatBarMessageContentModel::hasAnyContentChanged);
- connect(this, &ChatBarMessageContentModel::rowsRemoved, this, &ChatBarMessageContentModel::hasAnyContentChanged);
+ connect(this, &ChatBarMessageContentModel::modelReset, this, &ChatBarMessageContentModel::contentChanged);
+ connect(this, &ChatBarMessageContentModel::rowsInserted, this, &ChatBarMessageContentModel::contentChanged);
+ connect(this, &ChatBarMessageContentModel::rowsRemoved, this, &ChatBarMessageContentModel::contentChanged);
connectCache();
connectKeyHelper();
@@ -397,8 +393,7 @@ void ChatBarMessageContentModel::connectTextItem(ChatTextItemHelper *chattextite
connect(chattextitemhelper, &ChatTextItemHelper::cleared, this, [this](ChatTextItemHelper *helper) {
removeComponent(helper);
});
- connect(chattextitemhelper, &ChatTextItemHelper::contentsChanged, this, &ChatBarMessageContentModel::hasAnyContentChanged);
- connect(chattextitemhelper, &ChatTextItemHelper::contentsChanged, this, &ChatBarMessageContentModel::handleTyping);
+ connect(chattextitemhelper, &ChatTextItemHelper::contentsChanged, this, &ChatBarMessageContentModel::contentChanged);
}
ChatTextItemHelper *ChatBarMessageContentModel::textItemForComponent(Blocks::Block *component) const
@@ -724,15 +719,6 @@ void ChatBarMessageContentModel::setSendMessageWithEnter(bool sendMessageWithEnt
Q_EMIT sendMessageWithEnterChanged();
}
-void ChatBarMessageContentModel::setSendTypingNotifications(bool sendTypingNotifications)
-{
- m_sendTypingNotifications = sendTypingNotifications;
- if (!m_sendTypingNotifications && m_typingTimer->isActive()) {
- m_typingTimer->stop();
- m_room->sendTypingNotification(false);
- }
-}
-
Blocks::BlockPtrsIt ChatBarMessageContentModel::removeComponent(Blocks::BlockPtrsIt it)
{
if (it == m_components.end()) {
@@ -910,24 +896,4 @@ void ChatBarMessageContentModel::clearModel()
}
}
-void ChatBarMessageContentModel::handleTyping()
-{
- if (m_type == ChatBarType::None || !m_room || !m_sendTypingNotifications) {
- return;
- }
-
- if (!m_typingTimer->isActive() && hasAnyContent()) {
- m_typingTimer->start();
- m_room->sendTypingNotification(true);
- } else if (m_typingTimer->isActive() && !hasAnyContent()) {
- m_typingTimer->stop();
- m_room->sendTypingNotification(false);
- }
-}
-
-bool ChatBarMessageContentModel::sendTypingNotifications() const
-{
- return m_sendTypingNotifications;
-}
-
#include "moc_chatbarmessagecontentmodel.cpp"
diff --git a/src/messagecontent/models/chatbarmessagecontentmodel.h b/src/messagecontent/models/chatbarmessagecontentmodel.h
index 761fa1f57..a0e33181b 100644
--- a/src/messagecontent/models/chatbarmessagecontentmodel.h
+++ b/src/messagecontent/models/chatbarmessagecontentmodel.h
@@ -86,12 +86,7 @@ class ChatBarMessageContentModel : public MessageContentModel
/**
* @brief Whether the model has any content, ideal for checking if there is anything to send.
*/
- Q_PROPERTY(bool hasAnyContent READ hasAnyContent NOTIFY hasAnyContentChanged)
-
- /**
- * @brief Whether to send typing notifications to the server when the content changes.
- */
- Q_PROPERTY(bool sendTypingNotifications READ sendTypingNotifications WRITE setSendTypingNotifications)
+ Q_PROPERTY(bool hasAnyContent READ hasAnyContent NOTIFY contentChanged)
public:
explicit ChatBarMessageContentModel(QObject *parent = nullptr);
@@ -125,9 +120,6 @@ public:
bool sendMessageWithEnter() const;
void setSendMessageWithEnter(bool sendMessageWithEnter);
- void setSendTypingNotifications(bool sendTypingNotifications);
- [[nodiscard]] bool sendTypingNotifications() const;
-
Q_INVOKABLE void resetModel();
Q_INVOKABLE void postMessage();
@@ -143,7 +135,8 @@ Q_SIGNALS:
void hasRichFormattingChanged();
void hasAttachmentChanged();
void sendMessageWithEnterChanged();
- void hasAnyContentChanged();
+
+ void contentChanged();
private:
ChatBarType::Type m_type = ChatBarType::None;
@@ -183,10 +176,6 @@ private:
void updateCache() const;
bool m_sendMessageWithEnter = true;
- bool m_sendTypingNotifications = false;
void clearModel();
-
- QTimer *m_typingTimer;
- void handleTyping();
};