From b8262fef92e295223dbc6f908b4f4f743754986b Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Sun, 3 Apr 2022 23:54:28 +0200 Subject: [PATCH] Implement device verification --- CMakeLists.txt | 13 +-- .../Dialog/KeyVerification/EmojiItem.qml | 39 +++++++++ .../Dialog/KeyVerification/EmojiRow.qml | 25 ++++++ .../Dialog/KeyVerification/EmojiSas.qml | 50 +++++++++++ .../KeyVerification/KeyVerificationDialog.qml | 86 +++++++++++++++++++ .../Dialog/KeyVerification/Message.qml | 27 ++++++ .../KeyVerification/VerificationCanceled.qml | 70 +++++++++++++++ imports/NeoChat/Dialog/KeyVerification/qmldir | 7 ++ imports/NeoChat/Dialog/qmldir | 1 + imports/NeoChat/Page/RoomPage.qml | 12 +++ imports/NeoChat/Settings/DevicesPage.qml | 10 +++ qml/main.qml | 15 +++- res.qrc | 7 ++ src/controller.h | 4 + src/devicesmodel.cpp | 11 ++- src/devicesmodel.h | 12 +++ src/main.cpp | 8 ++ src/messageeventmodel.cpp | 12 +++ src/messageeventmodel.h | 1 + 19 files changed, 403 insertions(+), 7 deletions(-) create mode 100644 imports/NeoChat/Dialog/KeyVerification/EmojiItem.qml create mode 100644 imports/NeoChat/Dialog/KeyVerification/EmojiRow.qml create mode 100644 imports/NeoChat/Dialog/KeyVerification/EmojiSas.qml create mode 100644 imports/NeoChat/Dialog/KeyVerification/KeyVerificationDialog.qml create mode 100644 imports/NeoChat/Dialog/KeyVerification/Message.qml create mode 100644 imports/NeoChat/Dialog/KeyVerification/VerificationCanceled.qml create mode 100644 imports/NeoChat/Dialog/KeyVerification/qmldir diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b19dd508..3c9267841 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,12 +25,14 @@ include(FeatureSummary) include(ECMSetupVersion) include(KDEInstallDirs) include(ECMFindQmlModule) -include(KDEClangFormat) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMAddAppIcon) include(KDEGitCommitHooks) include(ECMCheckOutboundLicense) +if (NOT ANDROID) + include(KDEClangFormat) +endif() if(NEOCHAT_FLATPAK) include(cmake/Flatpak.cmake) @@ -137,11 +139,12 @@ add_subdirectory(src) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) -file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES src/*.cpp src/*.h) -kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) - -kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT) +if (NOT ANDROID) + file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES src/*.cpp src/*.h) + kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) + kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT) +endif() file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h *.qml) # CI installs dependency headers to _install and _build, which break the reuse check # Fixes the test by excluding this directory diff --git a/imports/NeoChat/Dialog/KeyVerification/EmojiItem.qml b/imports/NeoChat/Dialog/KeyVerification/EmojiItem.qml new file mode 100644 index 000000000..0c8d24910 --- /dev/null +++ b/imports/NeoChat/Dialog/KeyVerification/EmojiItem.qml @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2022 Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 +import QtQml 2.15 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.neochat 1.0 + +Column { + id: emojiItem + + property string emoji + property string description + + QQC2.Label { + id: emojiLabel + x: 0 + y: 0 + width: parent.width + height: parent.height * 0.75 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: emojiItem.emoji + font.family: "emoji" + font.pointSize: Kirigami.Theme.defaultFont.pointSize * 4 + } + QQC2.Label { + x: 0 + y: parent.height * 0.75 + width: parent.width + height: parent.height * 0.25 + text: emojiItem.description + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } +} diff --git a/imports/NeoChat/Dialog/KeyVerification/EmojiRow.qml b/imports/NeoChat/Dialog/KeyVerification/EmojiRow.qml new file mode 100644 index 000000000..4bda5f839 --- /dev/null +++ b/imports/NeoChat/Dialog/KeyVerification/EmojiRow.qml @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: 2022 Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 +import QtQml 2.15 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.neochat 1.0 + +Row { + id: emojiRow + + property alias model: repeater.model + anchors.horizontalCenter: parent.horizontalCenter + Repeater { + id: repeater + delegate: EmojiItem { + emoji: modelData.emoji + description: modelData.description + width: emojiRow.height + height: width + } + } +} diff --git a/imports/NeoChat/Dialog/KeyVerification/EmojiSas.qml b/imports/NeoChat/Dialog/KeyVerification/EmojiSas.qml new file mode 100644 index 000000000..b61450551 --- /dev/null +++ b/imports/NeoChat/Dialog/KeyVerification/EmojiSas.qml @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2022 Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 +import QtQml 2.15 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.neochat 1.0 + +Column { + id: emojiSas + + required property var model + + signal accept() + signal reject() + + visible: dialog.session.state === KeyVerificationSession.WAITINGFORVERIFICATION + anchors.centerIn: parent + spacing: Kirigami.Units.largeSpacing + QQC2.Label { + text: i18n("Confirm the emoji below are displayed on both devices, in the same order.") + } + EmojiRow { + anchors.horizontalCenter: parent.horizontalCenter + height: Kirigami.Units.gridUnit * 4 + model: emojiSas.model.slice(0, 4) + } + EmojiRow { + anchors.horizontalCenter: parent.horizontalCenter + height: Kirigami.Units.gridUnit * 4 + model: emojiSas.model.slice(4, 7) + } + Row { + anchors.horizontalCenter: parent.horizontalCenter + QQC2.Button { + anchors.bottom: parent.bottom + text: i18n("They match") + icon.name: "dialog-ok" + onClicked: emojiSas.accept() + } + QQC2.Button { + anchors.bottom: parent.bottom + text: i18n("They don't match") + icon.name: "dialog-cancel" + onClicked: emojiSas.reject() + } + } +} diff --git a/imports/NeoChat/Dialog/KeyVerification/KeyVerificationDialog.qml b/imports/NeoChat/Dialog/KeyVerification/KeyVerificationDialog.qml new file mode 100644 index 000000000..1e47ce3ac --- /dev/null +++ b/imports/NeoChat/Dialog/KeyVerification/KeyVerificationDialog.qml @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: 2022 Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 +import QtQuick.Layouts 1.15 +import QtQml 2.15 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.neochat 1.0 + +Kirigami.Page { + id: dialog + title: i18n("Session Verification") + + required property var session + + Item { + anchors.fill: parent + VerificationCanceled { + visible: dialog.session.state === KeyVerificationSession.CANCELED + anchors.centerIn: parent + reason: dialog.session.error + } + EmojiSas { + anchors.centerIn: parent + visible: dialog.session.state === KeyVerificationSession.WAITINGFORVERIFICATION + model: dialog.session.sasEmojis + onReject: dialog.session.cancelVerification(KeyVerificationSession.MISMATCHED_SAS) + onAccept: dialog.session.sendMac() + } + Message { + visible: dialog.session.state === KeyVerificationSession.WAITINGFORREADY + anchors.centerIn: parent + icon: "security-medium-symbolic" + text: i18n("Waiting for device to accept verification.") + } + Message { + visible: dialog.session.state === KeyVerificationSession.INCOMING + anchors.centerIn: parent + icon: "security-medium-symbolic" + text: i18n("Incoming key verification request from device **%1**", dialog.session.remoteDeviceId) + } + Message { + visible: dialog.session.state === KeyVerificationSession.WAITINGFORMAC + anchors.centerIn: parent + icon: "security-medium-symbolic" + text: i18n("Waiting for other party to verify.") + } + Kirigami.BasicListItem { + id: emojiVerification + text: "Emoji Verification" + visible: dialog.session.state === KeyVerificationSession.READY + subtitle: i18n("Compare a set of emoji on both devices") + onClicked: { + dialog.session.sendStartSas() + } + } + Message { + visible: dialog.session.state === KeyVerificationSession.DONE + anchors.centerIn: parent + text: i18n("Successfully verified device **%1**", dialog.session.remoteDeviceId) + icon: "security-high" + } + } + + footer: QQC2.ToolBar { + visible: dialog.session.state === KeyVerificationSession.INCOMING + QQC2.DialogButtonBox { + anchors.fill: parent + Item { Layout.fillWidth: true } + QQC2.Button { + text: i18n("Accept") + icon.name: "dialog-ok" + onClicked: dialog.session.sendReady() + QQC2.DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole + } + QQC2.Button { + text: i18n("Decline") + icon.name: "dialog-cancel" + onClicked: dialog.session.cancelVerification("m.user", "Declined") + QQC2.DialogButtonBox.buttonRole: DialogButtonBox.CancelRole + } + } + } +} diff --git a/imports/NeoChat/Dialog/KeyVerification/Message.qml b/imports/NeoChat/Dialog/KeyVerification/Message.qml new file mode 100644 index 000000000..35fcac8a8 --- /dev/null +++ b/imports/NeoChat/Dialog/KeyVerification/Message.qml @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2022 Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 +import QtQml 2.15 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.neochat 1.0 + +Column { + id: message + required property string icon + required property string text + + anchors.centerIn: parent + Kirigami.Icon { + width: Kirigami.Units.iconSizes.enormous + height: width + anchors.horizontalCenter: parent.horizontalCenter + source: message.icon + } + QQC2.Label { + text: message.text + textFormat: Text.MarkdownText + } +} diff --git a/imports/NeoChat/Dialog/KeyVerification/VerificationCanceled.qml b/imports/NeoChat/Dialog/KeyVerification/VerificationCanceled.qml new file mode 100644 index 000000000..2b6317fbb --- /dev/null +++ b/imports/NeoChat/Dialog/KeyVerification/VerificationCanceled.qml @@ -0,0 +1,70 @@ +// SPDX-FileCopyrightText: 2022 Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 +import QtQml 2.15 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.neochat 1.0 + +Message { + id: verificationCanceled + + required property int reason + + anchors.centerIn: parent + icon: "security-low" + text: { + switch(verificationCanceled.reason) { + case KeyVerificationSession.NONE: + return i18n("The session verification was canceled for unknown reason."); + case KeyVerificationSession.TIMEOUT: + return i18n("The session verification timed out."); + case KeyVerificationSession.REMOTE_TIMEOUT: + return i18n("The session verification timed out for remote party."); + case KeyVerificationSession.USER: + return i18n("You canceled the session verification."); + case KeyVerificationSession.REMOTE_USER: + return i18n("The remote party canceled the session verification."); + case KeyVerificationSession.UNEXPECTED_MESSAGE: + return i18n("The session verification was canceled because we received an unexpected message."); + case KeyVerificationSession.REMOTE_UNEXPECTED_MESSAGE: + return i18n("The remote party canceled the session verification because it received an unexpected message."); + case KeyVerificationSession.UNKNOWN_TRANSACTION: + return i18n("The session verification was canceled because it received a message for an unknown session."); + case KeyVerificationSession.REMOTE_UNKNOWN_TRANSACTION: + return i18n("The remote party canceled the session verification because it received a message for an unknown session."); + case KeyVerificationSession.UNKNOWN_METHOD: + return i18n("The session verification was canceled because NeoChat is unable to handle this verification method."); + case KeyVerificationSession.REMOTE_UNKNOWN_METHOD: + return i18n("The remote party canceled the session verification because it is unable to handle this verification method."); + case KeyVerificationSession.KEY_MISMATCH: + return i18n("The session verification was canceled because the keys are incorrect."); + case KeyVerificationSession.REMOTE_KEY_MISMATCH: + return i18n("The remote party canceled the session verification because the keys are incorrect."); + case KeyVerificationSession.USER_MISMATCH: + return i18n("The session verification was canceled because it verifies an unexpected user."); + case KeyVerificationSession.REMOTE_USER_MISMATCH: + return i18n("The remote party canceled the session verification because it verifies an unexpected user."); + case KeyVerificationSession.INVALID_MESSAGE: + return i18n("The session verification was canceled because we received an invalid message."); + case KeyVerificationSession.REMOTE_INVALID_MESSAGE: + return i18n("The remote party canceled the session verification because it received an invalid message."); + case KeyVerificationSession.SESSION_ACCEPTED: + return i18n("The session was accepted on a different device"); //TODO this should not be visible + case KeyVerificationSession.REMOTE_SESSION_ACCEPTED: + return i18n("The session was accepted on a different device"); //TODO neither should this + case KeyVerificationSession.MISMATCHED_COMMITMENT: + return i18n("The session verification was canceled because of a mismatched key."); + case KeyVerificationSession.REMOTE_MISMATCHED_COMMITMENT: + return i18n("The remote party canceled the session verification because of a mismatched key."); + case KeyVerificationSession.MISMATCHED_SAS: + return i18n("The session verification was canceled because the keys do not match."); + case KeyVerificationSession.REMOTE_MISMATCHED_SAS: + return i18n("The remote party canceled the session verification because the keys do not match."); + default: + return i18n("The session verification was canceled due to an unknown error."); + } + } +} diff --git a/imports/NeoChat/Dialog/KeyVerification/qmldir b/imports/NeoChat/Dialog/KeyVerification/qmldir new file mode 100644 index 000000000..5a583bb09 --- /dev/null +++ b/imports/NeoChat/Dialog/KeyVerification/qmldir @@ -0,0 +1,7 @@ +module NeoChat.Dialog.KeyVerification +KeyVerificationDialog 1.0 KeyVerificationDialog.qml +Message 1.0 Message.qml +VerificationCanceled 1.0 VerificationCanceled.qml +EmojiItem 1.0 EmojiItem.qml +EmojiRow 1.0 EmojiRow.qml +EmojiSas 1.0 EmojiSas.qml diff --git a/imports/NeoChat/Dialog/qmldir b/imports/NeoChat/Dialog/qmldir index 384ccfa5f..bf858091e 100644 --- a/imports/NeoChat/Dialog/qmldir +++ b/imports/NeoChat/Dialog/qmldir @@ -7,3 +7,4 @@ OpenFileDialog 1.0 OpenFileDialog.qml ImageClipboardDialog 1.0 ImageClipboardDialog.qml StartChatDialog 1.0 StartChatDialog.qml EmojiDialog 1.0 EmojiDialog.qml +KeyVerificationDialog 1.0 KeyVerificationDialog.qml diff --git a/imports/NeoChat/Page/RoomPage.qml b/imports/NeoChat/Page/RoomPage.qml index 915ecba8b..fb17b4c22 100644 --- a/imports/NeoChat/Page/RoomPage.qml +++ b/imports/NeoChat/Page/RoomPage.qml @@ -465,6 +465,18 @@ Kirigami.ScrollablePage { id: hoverHandler margin: Kirigami.Units.smallSpacing } + Kirigami.Icon { + source: "security-high" + width: height + height: parent.height + visible: hoverActions.event.verified + HoverHandler { + id: hover + } + QQC2.ToolTip.text: i18n("This message was sent from a verified device") + QQC2.ToolTip.visible: hover.hovered + QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay + } QQC2.Button { QQC2.ToolTip.text: i18n("React") diff --git a/imports/NeoChat/Settings/DevicesPage.qml b/imports/NeoChat/Settings/DevicesPage.qml index 645746bde..06183e338 100644 --- a/imports/NeoChat/Settings/DevicesPage.qml +++ b/imports/NeoChat/Settings/DevicesPage.qml @@ -41,6 +41,16 @@ Kirigami.ScrollablePage { } } } + Controls.ToolButton { + display: Controls.AbstractButton.IconOnly + action: Kirigami.Action { + text: i18n("Verify device") + iconName: "security-low-symbolic" + onTriggered: { + devices.connection.startKeyVerificationSession(model.id) + } + } + } Controls.ToolButton { display: Controls.AbstractButton.IconOnly action: Kirigami.Action { diff --git a/qml/main.qml b/qml/main.qml index 5a2df5d9a..e37cdc2a2 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -13,6 +13,7 @@ import NeoChat.Component 1.0 import NeoChat.Dialog 1.0 import NeoChat.Page 1.0 import NeoChat.Panel 1.0 +import NeoChat.Dialog.KeyVerification 1.0 Kirigami.ApplicationWindow { id: root @@ -106,7 +107,7 @@ Kirigami.ApplicationWindow { function onOpenRoomInNewWindow(room) { const secondayWindow = roomWindow.createObject(applicationWindow(), {currentRoom: room}); - secondayWindow.width = root.width - pageStack.get(0).width; + secondayWiroomWindowndow.width = root.width - pageStack.get(0).width; secondayWindow.show(); } @@ -367,11 +368,23 @@ Kirigami.ApplicationWindow { } } + Component { + id: keyVerificationDialogComponent + KeyVerificationDialog { } + } + Connections { target: Controller.activeConnection function onDirectChatAvailable(directChat) { RoomManager.enterRoom(Controller.activeConnection.room(directChat.id)); } + function onNewKeyVerificationSession(session) { + applicationWindow().pageStack.pushDialogLayer(keyVerificationDialogComponent, { + session: session, + }, { + title: i18nc("@title:window", "Session Verification") + }); + } } Kirigami.OverlaySheet { diff --git a/res.qrc b/res.qrc index d991fc2f4..56703afba 100644 --- a/res.qrc +++ b/res.qrc @@ -63,6 +63,13 @@ imports/NeoChat/Dialog/CreateRoomDialog.qml imports/NeoChat/Dialog/EmojiDialog.qml imports/NeoChat/Dialog/OpenFileDialog.qml + imports/NeoChat/Dialog/KeyVerification/KeyVerificationDialog.qml + imports/NeoChat/Dialog/KeyVerification/Message.qml + imports/NeoChat/Dialog/KeyVerification/EmojiItem.qml + imports/NeoChat/Dialog/KeyVerification/EmojiRow.qml + imports/NeoChat/Dialog/KeyVerification/EmojiSas.qml + imports/NeoChat/Dialog/KeyVerification/VerificationCanceled.qml + imports/NeoChat/Dialog/KeyVerification/qmldir imports/NeoChat/Menu/qmldir imports/NeoChat/Menu/GlobalMenu.qml imports/NeoChat/Menu/EditMenu.qml diff --git a/src/controller.h b/src/controller.h index a54f1f27a..c006e40dd 100644 --- a/src/controller.h +++ b/src/controller.h @@ -140,6 +140,10 @@ Q_SIGNALS: void userConsentRequired(QUrl url); void testConnectionResult(const QString &connection, bool usable); void isOnlineChanged(bool isOnline); + void keyVerificationRequest(int timeLeft, Connection *connection, const QString &transactionId, const QString &deviceId); + void keyVerificationStart(); + void keyVerificationAccept(const QString &commitment); + void keyVerificationKey(const QString &sas); public Q_SLOTS: void logout(Quotient::Connection *conn, bool serverSideLogout); diff --git a/src/devicesmodel.cpp b/src/devicesmodel.cpp index 42d7713c9..3f1adae2a 100644 --- a/src/devicesmodel.cpp +++ b/src/devicesmodel.cpp @@ -6,11 +6,15 @@ #include #include "controller.h" +#include DevicesModel::DevicesModel(QObject *parent) : QAbstractListModel(parent) { - connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &DevicesModel::fetchDevices); + connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [=]() { + DevicesModel::fetchDevices(); + Q_EMIT connectionChanged(); + }); fetchDevices(); } @@ -94,3 +98,8 @@ void DevicesModel::setName(int index, const QString &name) endResetModel(); }); } + +Connection *DevicesModel::connection() const +{ + return Controller::instance().activeConnection(); +} diff --git a/src/devicesmodel.h b/src/devicesmodel.h index 6d0f7a031..9438da7ae 100644 --- a/src/devicesmodel.h +++ b/src/devicesmodel.h @@ -9,10 +9,17 @@ using namespace Quotient; +namespace Quotient +{ +class Connection; +} + class DevicesModel : public QAbstractListModel { Q_OBJECT + Q_PROPERTY(Connection *connection READ connection NOTIFY connectionChanged) + public: enum Roles { Id, @@ -31,6 +38,11 @@ public: Q_INVOKABLE void logout(int index, const QString &password); Q_INVOKABLE void setName(int index, const QString &name); + Connection *connection() const; + +Q_SIGNALS: + void connectionChanged(); + private: void fetchDevices(); QVector m_devices; diff --git a/src/main.cpp b/src/main.cpp index b2b31b21f..64bcf1d10 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -78,6 +78,9 @@ #include "userlistmodel.h" #include "webshortcutmodel.h" #include "windowcontroller.h" +#ifdef QUOTIENT_07 +#include +#endif #ifdef HAVE_COLORSCHEME #include "colorschemer.h" #endif @@ -225,6 +228,11 @@ int main(int argc, char *argv[]) qRegisterMetaType("NeoChatUser*"); qRegisterMetaType("GetRoomEventsJob*"); qRegisterMetaType("QMimeType"); +#ifdef QUOTIENT_07 + qRegisterMetaType("KeyVerificationSession*"); + qmlRegisterUncreatableType("org.kde.neochat", 1, 0, "KeyVerificationSession", {}); + qRegisterMetaType>("QVector"); +#endif #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) qRegisterMetaTypeStreamOperators(); diff --git a/src/messageeventmodel.cpp b/src/messageeventmodel.cpp index 65c0001d4..808562649 100644 --- a/src/messageeventmodel.cpp +++ b/src/messageeventmodel.cpp @@ -55,6 +55,7 @@ QHash MessageEventModel::roleNames() const roles[FormattedBodyRole] = "formattedBody"; roles[AuthorIdRole] = "authorId"; roles[MediaUrlRole] = "mediaUrl"; + roles[VerifiedRole] = "verified"; return roles; } @@ -791,6 +792,17 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const return m_currentRoom->urlToDownload(evt.id()); } + if (role == VerifiedRole) { +#ifdef QUOTIENT_07 + if (evt.originalEvent()) { + auto encrypted = dynamic_cast(evt.originalEvent()); + Q_ASSERT(encrypted); + return m_currentRoom->connection()->isVerifiedSession(encrypted->sessionId()); + } + return false; +#endif + } + return {}; } diff --git a/src/messageeventmodel.h b/src/messageeventmodel.h index 6690255a1..928ddcd53 100644 --- a/src/messageeventmodel.h +++ b/src/messageeventmodel.h @@ -48,6 +48,7 @@ public: // For debugging EventResolvedTypeRole, AuthorIdRole, + VerifiedRole, LastRole, // Keep this last }; Q_ENUM(EventRoles)