Implement device verification
This commit is contained in:
@@ -25,12 +25,14 @@ include(FeatureSummary)
|
|||||||
include(ECMSetupVersion)
|
include(ECMSetupVersion)
|
||||||
include(KDEInstallDirs)
|
include(KDEInstallDirs)
|
||||||
include(ECMFindQmlModule)
|
include(ECMFindQmlModule)
|
||||||
include(KDEClangFormat)
|
|
||||||
include(KDECMakeSettings)
|
include(KDECMakeSettings)
|
||||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||||
include(ECMAddAppIcon)
|
include(ECMAddAppIcon)
|
||||||
include(KDEGitCommitHooks)
|
include(KDEGitCommitHooks)
|
||||||
include(ECMCheckOutboundLicense)
|
include(ECMCheckOutboundLicense)
|
||||||
|
if (NOT ANDROID)
|
||||||
|
include(KDEClangFormat)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NEOCHAT_FLATPAK)
|
if(NEOCHAT_FLATPAK)
|
||||||
include(cmake/Flatpak.cmake)
|
include(cmake/Flatpak.cmake)
|
||||||
@@ -137,11 +139,12 @@ add_subdirectory(src)
|
|||||||
|
|
||||||
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||||
|
|
||||||
file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES src/*.cpp src/*.h)
|
if (NOT ANDROID)
|
||||||
kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES})
|
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)
|
|
||||||
|
|
||||||
|
kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
|
||||||
|
endif()
|
||||||
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h *.qml)
|
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h *.qml)
|
||||||
# CI installs dependency headers to _install and _build, which break the reuse check
|
# CI installs dependency headers to _install and _build, which break the reuse check
|
||||||
# Fixes the test by excluding this directory
|
# Fixes the test by excluding this directory
|
||||||
|
|||||||
39
imports/NeoChat/Dialog/KeyVerification/EmojiItem.qml
Normal file
39
imports/NeoChat/Dialog/KeyVerification/EmojiItem.qml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
25
imports/NeoChat/Dialog/KeyVerification/EmojiRow.qml
Normal file
25
imports/NeoChat/Dialog/KeyVerification/EmojiRow.qml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
imports/NeoChat/Dialog/KeyVerification/EmojiSas.qml
Normal file
50
imports/NeoChat/Dialog/KeyVerification/EmojiSas.qml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
||||||
|
// 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
imports/NeoChat/Dialog/KeyVerification/Message.qml
Normal file
27
imports/NeoChat/Dialog/KeyVerification/Message.qml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
||||||
|
// 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
imports/NeoChat/Dialog/KeyVerification/qmldir
Normal file
7
imports/NeoChat/Dialog/KeyVerification/qmldir
Normal file
@@ -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
|
||||||
@@ -7,3 +7,4 @@ OpenFileDialog 1.0 OpenFileDialog.qml
|
|||||||
ImageClipboardDialog 1.0 ImageClipboardDialog.qml
|
ImageClipboardDialog 1.0 ImageClipboardDialog.qml
|
||||||
StartChatDialog 1.0 StartChatDialog.qml
|
StartChatDialog 1.0 StartChatDialog.qml
|
||||||
EmojiDialog 1.0 EmojiDialog.qml
|
EmojiDialog 1.0 EmojiDialog.qml
|
||||||
|
KeyVerificationDialog 1.0 KeyVerificationDialog.qml
|
||||||
|
|||||||
@@ -465,6 +465,18 @@ Kirigami.ScrollablePage {
|
|||||||
id: hoverHandler
|
id: hoverHandler
|
||||||
margin: Kirigami.Units.smallSpacing
|
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.Button {
|
||||||
QQC2.ToolTip.text: i18n("React")
|
QQC2.ToolTip.text: i18n("React")
|
||||||
|
|||||||
@@ -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 {
|
Controls.ToolButton {
|
||||||
display: Controls.AbstractButton.IconOnly
|
display: Controls.AbstractButton.IconOnly
|
||||||
action: Kirigami.Action {
|
action: Kirigami.Action {
|
||||||
|
|||||||
15
qml/main.qml
15
qml/main.qml
@@ -13,6 +13,7 @@ import NeoChat.Component 1.0
|
|||||||
import NeoChat.Dialog 1.0
|
import NeoChat.Dialog 1.0
|
||||||
import NeoChat.Page 1.0
|
import NeoChat.Page 1.0
|
||||||
import NeoChat.Panel 1.0
|
import NeoChat.Panel 1.0
|
||||||
|
import NeoChat.Dialog.KeyVerification 1.0
|
||||||
|
|
||||||
Kirigami.ApplicationWindow {
|
Kirigami.ApplicationWindow {
|
||||||
id: root
|
id: root
|
||||||
@@ -106,7 +107,7 @@ Kirigami.ApplicationWindow {
|
|||||||
|
|
||||||
function onOpenRoomInNewWindow(room) {
|
function onOpenRoomInNewWindow(room) {
|
||||||
const secondayWindow = roomWindow.createObject(applicationWindow(), {currentRoom: 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();
|
secondayWindow.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,11 +368,23 @@ Kirigami.ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: keyVerificationDialogComponent
|
||||||
|
KeyVerificationDialog { }
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: Controller.activeConnection
|
target: Controller.activeConnection
|
||||||
function onDirectChatAvailable(directChat) {
|
function onDirectChatAvailable(directChat) {
|
||||||
RoomManager.enterRoom(Controller.activeConnection.room(directChat.id));
|
RoomManager.enterRoom(Controller.activeConnection.room(directChat.id));
|
||||||
}
|
}
|
||||||
|
function onNewKeyVerificationSession(session) {
|
||||||
|
applicationWindow().pageStack.pushDialogLayer(keyVerificationDialogComponent, {
|
||||||
|
session: session,
|
||||||
|
}, {
|
||||||
|
title: i18nc("@title:window", "Session Verification")
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Kirigami.OverlaySheet {
|
Kirigami.OverlaySheet {
|
||||||
|
|||||||
7
res.qrc
7
res.qrc
@@ -63,6 +63,13 @@
|
|||||||
<file>imports/NeoChat/Dialog/CreateRoomDialog.qml</file>
|
<file>imports/NeoChat/Dialog/CreateRoomDialog.qml</file>
|
||||||
<file>imports/NeoChat/Dialog/EmojiDialog.qml</file>
|
<file>imports/NeoChat/Dialog/EmojiDialog.qml</file>
|
||||||
<file>imports/NeoChat/Dialog/OpenFileDialog.qml</file>
|
<file>imports/NeoChat/Dialog/OpenFileDialog.qml</file>
|
||||||
|
<file>imports/NeoChat/Dialog/KeyVerification/KeyVerificationDialog.qml</file>
|
||||||
|
<file>imports/NeoChat/Dialog/KeyVerification/Message.qml</file>
|
||||||
|
<file>imports/NeoChat/Dialog/KeyVerification/EmojiItem.qml</file>
|
||||||
|
<file>imports/NeoChat/Dialog/KeyVerification/EmojiRow.qml</file>
|
||||||
|
<file>imports/NeoChat/Dialog/KeyVerification/EmojiSas.qml</file>
|
||||||
|
<file>imports/NeoChat/Dialog/KeyVerification/VerificationCanceled.qml</file>
|
||||||
|
<file>imports/NeoChat/Dialog/KeyVerification/qmldir</file>
|
||||||
<file>imports/NeoChat/Menu/qmldir</file>
|
<file>imports/NeoChat/Menu/qmldir</file>
|
||||||
<file>imports/NeoChat/Menu/GlobalMenu.qml</file>
|
<file>imports/NeoChat/Menu/GlobalMenu.qml</file>
|
||||||
<file>imports/NeoChat/Menu/EditMenu.qml</file>
|
<file>imports/NeoChat/Menu/EditMenu.qml</file>
|
||||||
|
|||||||
@@ -140,6 +140,10 @@ Q_SIGNALS:
|
|||||||
void userConsentRequired(QUrl url);
|
void userConsentRequired(QUrl url);
|
||||||
void testConnectionResult(const QString &connection, bool usable);
|
void testConnectionResult(const QString &connection, bool usable);
|
||||||
void isOnlineChanged(bool isOnline);
|
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:
|
public Q_SLOTS:
|
||||||
void logout(Quotient::Connection *conn, bool serverSideLogout);
|
void logout(Quotient::Connection *conn, bool serverSideLogout);
|
||||||
|
|||||||
@@ -6,11 +6,15 @@
|
|||||||
#include <csapi/device_management.h>
|
#include <csapi/device_management.h>
|
||||||
|
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
|
#include <connection.h>
|
||||||
|
|
||||||
DevicesModel::DevicesModel(QObject *parent)
|
DevicesModel::DevicesModel(QObject *parent)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &DevicesModel::fetchDevices);
|
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [=]() {
|
||||||
|
DevicesModel::fetchDevices();
|
||||||
|
Q_EMIT connectionChanged();
|
||||||
|
});
|
||||||
|
|
||||||
fetchDevices();
|
fetchDevices();
|
||||||
}
|
}
|
||||||
@@ -94,3 +98,8 @@ void DevicesModel::setName(int index, const QString &name)
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connection *DevicesModel::connection() const
|
||||||
|
{
|
||||||
|
return Controller::instance().activeConnection();
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,10 +9,17 @@
|
|||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
|
|
||||||
|
namespace Quotient
|
||||||
|
{
|
||||||
|
class Connection;
|
||||||
|
}
|
||||||
|
|
||||||
class DevicesModel : public QAbstractListModel
|
class DevicesModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(Connection *connection READ connection NOTIFY connectionChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
Id,
|
Id,
|
||||||
@@ -31,6 +38,11 @@ public:
|
|||||||
Q_INVOKABLE void logout(int index, const QString &password);
|
Q_INVOKABLE void logout(int index, const QString &password);
|
||||||
Q_INVOKABLE void setName(int index, const QString &name);
|
Q_INVOKABLE void setName(int index, const QString &name);
|
||||||
|
|
||||||
|
Connection *connection() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void connectionChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void fetchDevices();
|
void fetchDevices();
|
||||||
QVector<Quotient::Device> m_devices;
|
QVector<Quotient::Device> m_devices;
|
||||||
|
|||||||
@@ -78,6 +78,9 @@
|
|||||||
#include "userlistmodel.h"
|
#include "userlistmodel.h"
|
||||||
#include "webshortcutmodel.h"
|
#include "webshortcutmodel.h"
|
||||||
#include "windowcontroller.h"
|
#include "windowcontroller.h"
|
||||||
|
#ifdef QUOTIENT_07
|
||||||
|
#include <keyverificationsession.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_COLORSCHEME
|
#ifdef HAVE_COLORSCHEME
|
||||||
#include "colorschemer.h"
|
#include "colorschemer.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -225,6 +228,11 @@ int main(int argc, char *argv[])
|
|||||||
qRegisterMetaType<NeoChatUser *>("NeoChatUser*");
|
qRegisterMetaType<NeoChatUser *>("NeoChatUser*");
|
||||||
qRegisterMetaType<GetRoomEventsJob *>("GetRoomEventsJob*");
|
qRegisterMetaType<GetRoomEventsJob *>("GetRoomEventsJob*");
|
||||||
qRegisterMetaType<QMimeType>("QMimeType");
|
qRegisterMetaType<QMimeType>("QMimeType");
|
||||||
|
#ifdef QUOTIENT_07
|
||||||
|
qRegisterMetaType<KeyVerificationSession *>("KeyVerificationSession*");
|
||||||
|
qmlRegisterUncreatableType<KeyVerificationSession>("org.kde.neochat", 1, 0, "KeyVerificationSession", {});
|
||||||
|
qRegisterMetaType<QVector<EmojiEntry>>("QVector<EmojiEntry>");
|
||||||
|
#endif
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||||
qRegisterMetaTypeStreamOperators<Emoji>();
|
qRegisterMetaTypeStreamOperators<Emoji>();
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ QHash<int, QByteArray> MessageEventModel::roleNames() const
|
|||||||
roles[FormattedBodyRole] = "formattedBody";
|
roles[FormattedBodyRole] = "formattedBody";
|
||||||
roles[AuthorIdRole] = "authorId";
|
roles[AuthorIdRole] = "authorId";
|
||||||
roles[MediaUrlRole] = "mediaUrl";
|
roles[MediaUrlRole] = "mediaUrl";
|
||||||
|
roles[VerifiedRole] = "verified";
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -791,6 +792,17 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
return m_currentRoom->urlToDownload(evt.id());
|
return m_currentRoom->urlToDownload(evt.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (role == VerifiedRole) {
|
||||||
|
#ifdef QUOTIENT_07
|
||||||
|
if (evt.originalEvent()) {
|
||||||
|
auto encrypted = dynamic_cast<const EncryptedEvent *>(evt.originalEvent());
|
||||||
|
Q_ASSERT(encrypted);
|
||||||
|
return m_currentRoom->connection()->isVerifiedSession(encrypted->sessionId());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public:
|
|||||||
// For debugging
|
// For debugging
|
||||||
EventResolvedTypeRole,
|
EventResolvedTypeRole,
|
||||||
AuthorIdRole,
|
AuthorIdRole,
|
||||||
|
VerifiedRole,
|
||||||
LastRole, // Keep this last
|
LastRole, // Keep this last
|
||||||
};
|
};
|
||||||
Q_ENUM(EventRoles)
|
Q_ENUM(EventRoles)
|
||||||
|
|||||||
Reference in New Issue
Block a user