[network/ruqola] src/core/model: Allow to decrypt message when we load from Database
Laurent Montel <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 3dc01346f297000d393aac2913450d311e74b4d7 by Laurent Montel.
Committed on 13/08/2026 at 18:31.
Pushed by mlaurent into branch 'master'.
Allow to decrypt message when we load from Database
M +44 -7 src/core/model/messagesmodel.cpp
M +8 -0 src/core/model/messagesmodel.h
https://invent.kde.org/network/ruqola/-/commit/3dc01346f297000d393aac2913450d311e74b4d7
diff --git a/src/core/model/messagesmodel.cpp b/src/core/model/messagesmodel.cpp
index b1ea93f42f..f46548f6ad 100644
--- a/src/core/model/messagesmodel.cpp
+++ b/src/core/model/messagesmodel.cpp
@@ -173,14 +173,15 @@ void MessagesModel::addMessage(const Message &message)
const QModelIndex index = createIndex(rowNumber, 0);
Q_EMIT dataChanged(index, index, roles);
};
- if (mRoom && !mRoom->sessionKey().isEmpty()) {
- if (auto f = message.messageEncrypted()) {
- f->decryptContent(mRoom->sessionKey());
- }
- }
+ decryptMessage(message);
// When we have 1 element.
if (mAllMessages.count() == 1 && (*mAllMessages.begin()).messageId() == message.messageId()) {
+ if (message.pendingMessage()) {
+ // If we already have a message and we must add pending message it's that server
+ // send quickly new message => replace not it by a pending message
+ return;
+ }
(*mAllMessages.begin()) = message;
qCDebug(RUQOLA_MESSAGEMODELS_LOG) << "Update first message";
emitChanged(0, {OriginalMessageOrAttachmentDescription});
@@ -208,6 +209,7 @@ void MessagesModel::addMessagesSyncAfterLoadingFromDatabase(QList<Message> messa
beginResetModel();
std::sort(messages.begin(), messages.end(), compareTimeStamps);
const QList<Message> reducedMessageList = messages.mid(messages.count() - 50);
+ decryptMessageList(reducedMessageList);
mAllMessages = reducedMessageList;
endResetModel();
} else {
@@ -224,11 +226,13 @@ void MessagesModel::addMessages(const QList<Message> &messages, bool insertListM
return;
}
if (mAllMessages.isEmpty()) {
+ decryptMessageList(messages);
beginInsertRows(QModelIndex(), 0, messages.count() - 1);
mAllMessages = messages;
std::sort(mAllMessages.begin(), mAllMessages.end(), compareTimeStamps);
endInsertRows();
} else if (insertListMessages) {
+ decryptMessageList(messages);
beginResetModel();
mAllMessages += messages;
std::sort(mAllMessages.begin(), mAllMessages.end(), compareTimeStamps);
@@ -437,11 +441,44 @@ void MessagesModel::generateText(const Message &message, const QString &searchTe
// mNumberOfTextSearched = numberOfTextSearched;
}
+void MessagesModel::decryptMessage(const Message &message) const
+{
+ if (!mRoom) {
+ return;
+ }
+ if (const auto sessionKey = mRoom->sessionKey(); !sessionKey.isEmpty()) {
+ if (auto f = message.messageEncrypted()) {
+ f->decryptContent(sessionKey);
+ }
+ }
+}
+
+void MessagesModel::decryptMessageList(const QList<Message> &messages) const
+{
+ if (!mRoom) {
+ return;
+ }
+ if (const auto sessionKey = mRoom->sessionKey(); !sessionKey.isEmpty()) {
+ for (const Message &message : messages) {
+ if (auto f = message.messageEncrypted()) {
+ f->decryptContent(sessionKey);
+ }
+ }
+ }
+}
+
void MessagesModel::decryptMessages(const QByteArray &sessionKey)
{
- for (auto &msg : std::as_const(mAllMessages)) {
- if (auto f = msg.messageEncrypted()) {
+ // The session key usually arrives after the messages have been loaded and painted, so the rows
+ // that just became readable must be announced, otherwise they keep showing the encrypted text.
+ for (int row = 0, total = mAllMessages.count(); row < total; ++row) {
+ // QList::at() hands out a const reference on purpose: decryptContent() only fills the
+ // mutable decrypted members of the shared MessageEncrypted, no detach needed here.
+ if (auto f = mAllMessages.at(row).messageEncrypted()) {
f->decryptContent(sessionKey);
+ // One signal per row: the view drops its text/size-hint cache for topLeft only.
+ const QModelIndex idx = createIndex(row, 0);
+ Q_EMIT dataChanged(idx, idx, {OriginalMessageOrAttachmentDescription});
}
}
}
diff --git a/src/core/model/messagesmodel.h b/src/core/model/messagesmodel.h
index a4329525ac..b90463d60d 100644
--- a/src/core/model/messagesmodel.h
+++ b/src/core/model/messagesmodel.h
@@ -193,6 +193,14 @@ private:
LIBRUQOLACORE_NO_EXPORT void addMessage(const Message &message);
LIBRUQOLACORE_NO_EXPORT void refresh();
+ /**
+ * @brief Decrypts @p message in place with the room session key, if we already have one.
+ *
+ * Must be called on every path that puts messages into the model, otherwise an encrypted
+ * message stays displayed as such.
+ */
+ LIBRUQOLACORE_NO_EXPORT void decryptMessage(const Message &message) const;
+ LIBRUQOLACORE_NO_EXPORT void decryptMessageList(const QList<Message> &messages) const;
[[nodiscard]] LIBRUQOLACORE_NO_EXPORT bool threadMessageFollowed(const QByteArray &threadMessageId) const;
[[nodiscard]] LIBRUQOLACORE_NO_EXPORT QStringList roomRoles(const QByteArray &userId) const;
[[nodiscard]] LIBRUQOLACORE_NO_EXPORT QString convertMessageText(const Message &message,