feat(MessageContextMenu): add option to verify identity in context menu

Fixes #6252
This commit is contained in:
Jonathan Rainville 2022-07-06 15:27:04 -04:00
parent 2fbc313e5a
commit 03780d4875
6 changed files with 122 additions and 127 deletions

View File

@ -23,6 +23,8 @@ StatusListItem {
height: visible ? implicitHeight : 0
title: container.name
property var contactsStore
property string name: "Jotaro Kujo"
property string publicKey: "0x04d8c07dd137bd1b73a6f51df148b4f77ddaa11209d36e43d8344c0a7d6db1cad6085f27cfb75dd3ae21d86ceffebe4cf8a35b9ce8d26baa19dc264efe6d8f221b"
property string iconSource: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
@ -42,8 +44,7 @@ StatusListItem {
property string contactText: ""
property bool contactTextClickable: false
signal openProfilePopup(string publicKey)
signal openChangeNicknamePopup(string publicKey)
signal openContactContextMenu(string publicKey, string name, string icon)
signal sendMessageActionTriggered(string publicKey)
signal showVerificationRequest(string publicKey)
signal contactRequestAccepted(string publicKey)
@ -139,61 +140,7 @@ StatusListItem {
icon.name: "more"
icon.color: Theme.palette.directColor1
onClicked: {
highlighted = true
contactContextMenu.popup(-contactContextMenu.width+menuButton.width, menuButton.height + 4)
}
StatusPopupMenu {
id: contactContextMenu
onClosed: {
menuButton.highlighted = false
}
ProfileHeader {
width: parent.width
displayName: container.name
pubkey: container.publicKey
icon: container.iconSource
}
Item {
height: 8
}
Separator {}
ViewProfileMenuItem {
icon.width: 16
icon.height: 16
onTriggered: {
container.openProfilePopup(container.publicKey)
menuButton.highlighted = false
}
}
SendMessageMenuItem {
icon.width: 16
icon.height: 16
onTriggered: {
container.sendMessageActionTriggered(container.publicKey)
menuButton.highlighted = false
}
enabled: container.isContact
}
StatusMenuItem {
text: qsTr("Rename")
icon.name: "edit_pencil"
icon.width: 16
icon.height: 16
onTriggered: {
container.openChangeNicknamePopup(container.publicKey)
menuButton.highlighted = false
}
enabled: !container.isBlocked
}
container.openContactContextMenu(container.publicKey, container.name, container.icon)
}
}
]

View File

@ -16,6 +16,7 @@ import "."
Item {
id: contactListRoot
property var contactsStore
property var contactsModel
property int panelUsage: Constants.contactsPanelUsage.unknownPosition
property bool scrollbarOn: false
@ -26,11 +27,10 @@ Item {
readonly property string lowerCaseSearchString: searchString.toLowerCase()
readonly property int count: contactsList.count
signal openContactContextMenu(string publicKey, string name, string icon)
signal contactClicked(string publicKey)
signal openProfilePopup(string publicKey)
signal sendMessageActionTriggered(string publicKey)
signal showVerificationRequest(string publicKey)
signal openChangeNicknamePopup(string publicKey)
signal contactRequestAccepted(string publicKey)
signal contactRequestRejected(string publicKey)
signal rejectionRemoved(string publicKey)
@ -108,6 +108,7 @@ Item {
ContactPanel {
id: panelDelegate
width: ListView.view.width
contactsStore: contactListRoot.contactsStore
name: model.displayName
publicKey: model.pubKey
iconSource: model.icon
@ -120,6 +121,9 @@ Item {
searchStr: contactListRoot.searchString
showSendMessageButton: isContact && !isBlocked
onOpenContactContextMenu: function (publicKey, name, icon) {
contactListRoot.openContactContextMenu(publicKey, name, icon)
}
showRejectContactRequestButton: {
if (contactListRoot.panelUsage === Constants.contactsPanelUsage.receivedContactRequest && !model.verificationRequestStatus) {
return true
@ -156,9 +160,7 @@ Item {
}
onClicked: contactListRoot.contactClicked(model.pubKey)
onOpenProfilePopup: contactListRoot.openProfilePopup(publicKey)
onSendMessageActionTriggered: contactListRoot.sendMessageActionTriggered(publicKey)
onOpenChangeNicknamePopup: contactListRoot.openChangeNicknamePopup(publicKey)
onContactRequestAccepted: contactListRoot.contactRequestAccepted(publicKey)
onContactRequestRejected: contactListRoot.contactRequestRejected(publicKey)
onRejectionRemoved: contactListRoot.rejectionRemoved(publicKey)

View File

@ -13,6 +13,7 @@ import shared.views 1.0
import shared.panels 1.0
import shared.popups 1.0
import shared.controls 1.0
import shared.views.chat 1.0
import "../stores"
import "../panels"
@ -36,9 +37,31 @@ SettingsContentBase {
}
]
function openContextMenu(publicKey, name, icon) {
contactContextMenu.selectedUserPublicKey = publicKey
contactContextMenu.selectedUserDisplayName = name
contactContextMenu.selectedUserIcon = icon
contactContextMenu.popup()
}
Item {
id: contentItem
MessageContextMenuView {
id: contactContextMenu
store: ({contactsStore: root.contactsStore})
isProfile: true
onOpenProfileClicked: function (pubkey, state) {
Global.openProfilePopup(pubkey, null, state)
}
onCreateOneToOneChat: function (communityId, chatId, ensName) {
root.contactsStore.joinPrivateChat(chatId)
}
}
SearchBox {
id: searchBox
anchors.left: parent.left
@ -101,17 +124,14 @@ SettingsContentBase {
title: qsTr("Identity Verified Contacts")
contactsModel: root.contactsStore.myContactsModel
searchString: searchBox.text
panelUsage: Constants.contactsPanelUsage.verifiedMutualContacts
onOpenProfilePopup: {
Global.openProfilePopup(publicKey)
onOpenContactContextMenu: function (publicKey, name, icon) {
root.openContextMenu(publicKey, name, icon)
}
contactsStore: root.contactsStore
panelUsage: Constants.contactsPanelUsage.verifiedMutualContacts
onSendMessageActionTriggered: {
root.contactsStore.joinPrivateChat(publicKey)
}
onOpenChangeNicknamePopup: {
Global.openProfilePopup(publicKey, null, "openNickname")
}
}
ContactsListPanel {
@ -123,18 +143,15 @@ SettingsContentBase {
title: qsTr("Contacts")
contactsModel: root.contactsStore.myContactsModel
searchString: searchBox.text
panelUsage: Constants.contactsPanelUsage.mutualContacts
onOpenProfilePopup: {
Global.openProfilePopup(publicKey)
contactsStore: root.contactsStore
onOpenContactContextMenu: function (publicKey, name, icon) {
root.openContextMenu(publicKey, name, icon)
}
panelUsage: Constants.contactsPanelUsage.mutualContacts
onSendMessageActionTriggered: {
root.contactsStore.joinPrivateChat(publicKey)
}
onOpenChangeNicknamePopup: {
Global.openProfilePopup(publicKey, null, "openNickname")
}
}
Item {
width: parent.width
@ -159,17 +176,13 @@ SettingsContentBase {
(contactsListHeight > (stackLayout.height - sentRequests.contactsListHeight))
title: qsTr("Received")
searchString: searchBox.text
contactsStore: root.contactsStore
onOpenContactContextMenu: function (publicKey, name, icon) {
root.openContextMenu(publicKey, name, icon)
}
contactsModel: root.contactsStore.receivedContactRequestsModel
panelUsage: Constants.contactsPanelUsage.receivedContactRequest
onOpenProfilePopup: {
Global.openProfilePopup(publicKey)
}
onOpenChangeNicknamePopup: {
Global.openProfilePopup(publicKey, null, "openNickname")
}
onContactRequestAccepted: {
root.contactsStore.acceptContactRequest(publicKey)
}
@ -205,16 +218,12 @@ SettingsContentBase {
(contactsListHeight > (stackLayout.height - receivedRequests.contactsListHeight))
title: qsTr("Sent")
searchString: searchBox.text
contactsStore: root.contactsStore
onOpenContactContextMenu: function (publicKey, name, icon) {
root.openContextMenu(publicKey, name, icon)
}
contactsModel: root.contactsStore.sentContactRequestsModel
panelUsage: Constants.contactsPanelUsage.sentContactRequest
onOpenProfilePopup: {
Global.openProfilePopup(publicKey)
}
onOpenChangeNicknamePopup: {
Global.openProfilePopup(publicKey, null, "openNickname")
}
}
}
@ -233,17 +242,13 @@ SettingsContentBase {
// clip: true
// title: qsTr("Received")
// searchString: searchBox.text
// contactsStore: root.contactsStore
// onOpenContactContextMenu: function (publicKey, name, icon) {
// root.openContextMenu(publicKey, name, icon)
// }
// contactsModel: root.contactsStore.receivedButRejectedContactRequestsModel
// panelUsage: Constants.contactsPanelUsage.rejectedReceivedContactRequest
// onOpenProfilePopup: {
// Global.openProfilePopup(publicKey)
// }
// onOpenChangeNicknamePopup: {
// Global.openProfilePopup(publicKey, null, true)
// }
// onRejectionRemoved: {
// root.contactsStore.removeContactRequestRejection(publicKey)
// }
@ -255,16 +260,12 @@ SettingsContentBase {
// clip: true
// title: qsTr("Sent")
// searchString: searchBox.text
// contactsStore: root.contactsStore
// onOpenContactContextMenu: function (publicKey, name, icon) {
// root.openContextMenu(publicKey, name, icon)
// }
// contactsModel: root.contactsStore.sentButRejectedContactRequestsModel
// panelUsage: Constants.contactsPanelUsage.rejectedSentContactRequest
// onOpenProfilePopup: {
// Global.openProfilePopup(publicKey)
// }
// onOpenChangeNicknamePopup: {
// Global.openProfilePopup(publicKey, null, true)
// }
// }
// Item {
@ -279,11 +280,12 @@ SettingsContentBase {
width: parent.width
height: (contactsListHeight+50)
searchString: searchBox.text
contactsStore: root.contactsStore
onOpenContactContextMenu: function (publicKey, name, icon) {
root.openContextMenu(publicKey, name, icon)
}
contactsModel: root.contactsStore.blockedContactsModel
panelUsage: Constants.contactsPanelUsage.blockedContacts
onOpenProfilePopup: {
Global.openProfilePopup(publicKey)
}
}
}

View File

@ -112,14 +112,16 @@ StatusModal {
showFooter = !isCurrentUser;
popup.open();
if (state == "openNickname") {
nicknamePopup.open();
} else if (state == "contactRequest") {
if (state === "openNickname") {
profileView.nicknamePopup.open();
} else if (state === "contactRequest") {
sendContactRequestModal.open()
} else if (state == "blockUser") {
} else if (state === "blockUser") {
blockUser();
} else if (state == "unblockUser") {
} else if (state === "unblockUser") {
unblockUser();
} else if (state === "verifyIdentity") {
showVerifyIdentitySection = true;
}
}
@ -409,7 +411,7 @@ StatusModal {
visible: showIdentityVerified || showIdentityVerifiedUntrustworthy
text: qsTr("Rename")
onClicked: {
nicknamePopup.open()
profileView.nicknamePopup.open()
}
},

View File

@ -72,6 +72,7 @@ Rectangle {
readonly property alias wizardAnimation: wizardAnimation
readonly property alias challengeTxt: challengeTxt
readonly property alias stepsListModel: stepsListModel
readonly property alias nicknamePopup: nicknamePopup
readonly property int animationDuration: 500

View File

@ -24,20 +24,21 @@ StatusPopupMenu {
property string myPublicKey: ""
property bool amIChatAdmin: false
property bool pinMessageAllowedForMembers: false
property string selectedUserPublicKey: ""
property string selectedUserDisplayName: ""
property string selectedUserIcon: ""
property int chatType: Constants.chatType.publicChat
property string messageId: ""
property string messageSenderId: ""
property int messageContentType: Constants.messageContentType.unknownContentType
property string selectedUserPublicKey: ""
property string selectedUserDisplayName: ""
property string selectedUserIcon: ""
property string imageSource: ""
property bool isProfile: false
property bool isRightClickOnImage: false
property bool pinnedPopup: false
property bool pinMessageAllowedForMembers: false
property bool isDebugEnabled: false
property bool isEmoji: false
property bool isSticker: false
@ -46,17 +47,45 @@ StatusPopupMenu {
property bool canPin: false
readonly property bool isMyMessage: {
return root.messageSenderId !== "" && root.messageSenderId == root.myPublicKey;
return root.messageSenderId !== "" && root.messageSenderId === root.myPublicKey;
}
readonly property bool isMe: {
return root.selectedUserPublicKey == root.store.contactsStore.myPublicKey;
return root.selectedUserPublicKey === root.store.contactsStore.myPublicKey;
}
readonly property bool isMyMutualContact: {
return root.selectedUserPublicKey !== "" && root.store.contactsStore.isMyMutualContact(root.selectedUserPublicKey);
readonly property var contactDetails: {
if (root.selectedUserPublicKey === "" || isMe) {
return {}
}
return Utils.getContactDetailsAsJson(root.selectedUserPublicKey);
}
readonly property bool isContact: {
return root.selectedUserPublicKey !== "" && !!contactDetails.isContact
}
readonly property bool isBlockedContact: d.contactDetails && d.contactDetails.isBlocked
readonly property bool isBlockedContact: {
return root.selectedUserPublicKey !== "" && !!contactDetails.isBlocked
}
readonly property int outgoingVerificationStatus: {
if (root.selectedUserPublicKey === "" || root.isMe || !root.isContact) {
return 0
}
return contactDetails.verificationStatus
}
readonly property bool hasPendingContactRequest: {
return root.selectedUserPublicKey !== "" && root.store.contactsStore.hasPendingContactRequest(root.selectedUserPublicKey);
return !root.isMe && root.selectedUserPublicKey !== "" &&
root.store.contactsStore.hasPendingContactRequest(root.selectedUserPublicKey);
}
readonly property bool hasReceivedVerificationRequestFrom: {
if (!root.selectedUserPublicKey || root.isMe || !root.isContact) {
return false
}
return root.store.contactsStore.hasReceivedVerificationRequestFrom(root.selectedUserPublicKey)
}
readonly property bool isVerificationRequestSent: {
if (!root.selectedUserPublicKey || root.isMe || !root.isContact) {
return false
}
return root.outgoingVerificationStatus !== Constants.verificationStatus.unverified
}
readonly property bool userTrustIsUnknown: d.contactDetails && d.contactDetails.trustStatus === Constants.trustStatus.unknown
@ -212,7 +241,7 @@ StatusPopupMenu {
SendMessageMenuItem {
id: sendMessageMenuItem
enabled: root.isProfile && root.isMyMutualContact && !root.isBlockedContact
enabled: root.isProfile && root.isContact && !root.isBlockedContact
onTriggered: {
root.createOneToOneChat("", root.selectedUserPublicKey, "")
root.close()
@ -220,7 +249,7 @@ StatusPopupMenu {
}
SendContactRequestMenuItem {
enabled: root.isProfile && !root.isMe && !root.isMyMutualContact
enabled: root.isProfile && !root.isMe && !root.isContact
&& !root.isBlockedContact && !root.hasPendingContactRequest
onTriggered: {
root.openProfileClicked(root.selectedUserPublicKey, "contactRequest")
@ -238,6 +267,18 @@ StatusPopupMenu {
}
}
StatusMenuItem {
text: qsTr("Verify Identity")
icon.name: "checkmark-circle"
enabled: root.isProfile && !root.isMe && root.isContact
&& !root.isBlockedContact && !root.isVerificationRequestSent
&& !root.hasReceivedVerificationRequestFrom
onTriggered: {
root.openProfileClicked(root.selectedUserPublicKey, "verifyIdentity")
root.close()
}
}
StatusMenuItem {
text: qsTr("Unblock User")
icon.name: "remove-circle"