feat(Profile flow) Mark as untrusted

- add new popup for marking a person as untrusted
- optionally display checkboxes to remove ID verification or the contact
- emit toasts

Fixes #13520
This commit is contained in:
Lukáš Tinkl 2024-02-16 18:34:09 +01:00 committed by Lukáš Tinkl
parent 2e6af7aa51
commit 4a3eb4ce18
8 changed files with 112 additions and 12 deletions

View File

@ -139,6 +139,16 @@ SplitView {
function sendVerificationRequest(publicKey, challenge) {
logs.logEvent("rootStore::contactStore::sendVerificationRequest", ["publicKey", "challenge"], arguments)
}
function markUntrustworthy(publicKey) {
logs.logEvent("rootStore::contactStore::markUntrustworthy", ["publicKey"], arguments)
ctrlTrustStatus.currentIndex = ctrlTrustStatus.indexOfValue(Constants.trustStatus.untrustworthy)
}
function removeContact(publicKey) {
logs.logEvent("rootStore::contactStore::removeContact", ["publicKey"], arguments)
ctrlContactRequestState.currentIndex = ctrlContactRequestState.indexOfValue(Constants.ContactRequestState.None)
}
}
}
communityTokensStore: CommunityTokensStore {}
@ -222,6 +232,7 @@ SplitView {
function removeTrustStatus(publicKey) {
logs.logEvent("contactsStore::removeTrustStatus", ["publicKey"], arguments)
ctrlTrustStatus.currentIndex = ctrlTrustStatus.indexOfValue(Constants.trustStatus.unknown)
}
function verifiedUntrustworthy(publicKey) {

View File

@ -106,6 +106,7 @@ QtObject {
function cancelVerificationRequest(pubKey) {
root.contactsModule.cancelVerificationRequest(pubKey);
Global.displaySuccessToastMessage(qsTr("ID verification request cancelled"))
}
function declineVerificationRequest(pubKey) {

View File

@ -56,6 +56,7 @@ QtObject {
Global.openImagePopup.connect(openImagePopup)
Global.openProfilePopupRequested.connect(openProfilePopup)
Global.openNicknamePopupRequested.connect(openNicknamePopup)
Global.markAsUntrustedRequested.connect(openMarkAsUntrustedPopup)
Global.blockContactRequested.connect(openBlockContactPopup)
Global.unblockContactRequested.connect(openUnblockContactPopup)
Global.openChangeProfilePicPopup.connect(openChangeProfilePicPopup)
@ -136,6 +137,10 @@ QtObject {
openPopup(nicknamePopupComponent, {publicKey, contactDetails})
}
function openMarkAsUntrustedPopup(publicKey: string, contactDetails) {
openPopup(markAsUntrustedComponent, {publicKey, contactDetails})
}
function openBlockContactPopup(publicKey: string, contactName: string) {
openPopup(blockContactConfirmationComponent, {contactName: contactName, contactAddress: publicKey})
}
@ -511,12 +516,31 @@ QtObject {
NicknamePopup {
onEditDone: {
if (nickname !== newNickname) {
rootStore.contactStore.changeContactNickname(publicKey, newNickname, originalDisplayName, !!nickname)
rootStore.contactStore.changeContactNickname(publicKey, newNickname, optionalDisplayName, !!nickname)
}
close()
}
onRemoveNicknameRequested: {
rootStore.contactStore.changeContactNickname(publicKey, "", originalDisplayName, true)
rootStore.contactStore.changeContactNickname(publicKey, "", optionalDisplayName, true)
close()
}
onClosed: destroy()
}
},
Component {
id: markAsUntrustedComponent
MarkAsUntrustedPopup {
onAccepted: {
rootStore.contactStore.markUntrustworthy(publicKey)
if (removeIDVerification)
rootStore.contactStore.cancelVerificationRequest(publicKey)
if (removeContact) {
rootStore.contactStore.removeContact(publicKey)
Global.displaySuccessToastMessage(qsTr("%1 removed from contacts and marked as untrusted").arg(mainDisplayName))
} else {
Global.displayToastMessage(qsTr("%1 marked as untrusted").arg(mainDisplayName))
}
close()
}
onClosed: destroy()

View File

@ -0,0 +1,63 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQml.Models 2.15
import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import utils 1.0
import shared.controls 1.0
CommonContactDialog {
id: root
readonly property bool removeIDVerification: ctrlRemoveIDVerification.checked
readonly property bool removeContact: ctrlRemoveContact.checked
title: qsTr("Mark as untrusted")
readonly property var d: QtObject {
id: d
readonly property int outgoingVerificationStatus: contactDetails.verificationStatus
readonly property int incomingVerificationStatus: contactDetails.incomingVerificationStatus
readonly property bool isVerificationRequestReceived: incomingVerificationStatus === Constants.verificationStatus.verifying ||
incomingVerificationStatus === Constants.verificationStatus.verified
readonly property bool isTrusted: outgoingVerificationStatus === Constants.verificationStatus.trusted ||
incomingVerificationStatus === Constants.verificationStatus.trusted
}
StatusBaseText {
Layout.fillWidth: true
Layout.bottomMargin: Style.current.halfPadding
text: qsTr("%1 will be marked as untrusted. This mark will only be visible to you.").arg(mainDisplayName)
wrapMode: Text.WordWrap
}
StatusCheckBox {
id: ctrlRemoveIDVerification
visible: contactDetails.isContact && !d.isTrusted && d.isVerificationRequestReceived
checked: visible
enabled: false
text: qsTr("Remove ID verification")
}
StatusCheckBox {
id: ctrlRemoveContact
visible: contactDetails.isContact
text: qsTr("Remove contact")
}
rightButtons: ObjectModel {
StatusFlatButton {
text: qsTr("Cancel")
onClicked: root.close()
}
StatusButton {
type: StatusBaseButton.Type.Danger
text: qsTr("Mark as untrusted")
onClicked: root.accepted()
}
}
}

View File

@ -27,3 +27,4 @@ UserAgreementPopup 1.0 UserAgreementPopup.qml
AlertPopup 1.0 AlertPopup.qml
ConfirmExternalLinkPopup 1.0 ConfirmExternalLinkPopup.qml
CommunityAssetsInfoPopup 1.0 CommunityAssetsInfoPopup.qml
MarkAsUntrustedPopup 1.0 MarkAsUntrustedPopup.qml

View File

@ -332,6 +332,10 @@ Pane {
if (d.isBlocked)
return btnUnblockUserComponent
// accept incoming CR
if (d.contactRequestState === Constants.ContactRequestState.Received)
return btnAcceptContactRequestComponent
// block user
if (d.contactDetails.trustStatus === Constants.trustStatus.untrustworthy)
return btnBlockUserComponent
@ -345,7 +349,7 @@ Pane {
case Constants.ContactRequestState.Sent:
return txtPendingContactRequestComponent
case Constants.ContactRequestState.Received:
return btnAcceptContactRequestComponent
break // handled above
case Constants.ContactRequestState.Mutual: {
if (d.incomingVerificationStatus === Constants.verificationStatus.declined) {
return btnBlockUserComponent
@ -451,13 +455,9 @@ Pane {
text: qsTr("Mark as untrusted")
icon.name: "warning"
type: StatusAction.Type.Danger
enabled: d.contactDetails.trustStatus === Constants.trustStatus.unknown && !d.isBlocked
enabled: d.contactDetails.trustStatus !== Constants.trustStatus.untrustworthy && !d.isBlocked
onTriggered: {
if (d.isContact && !d.isTrusted && d.isVerificationRequestReceived)
root.contactsStore.verifiedUntrustworthy(root.publicKey)
else
root.contactsStore.markUntrustworthy(root.publicKey)
d.reload()
Global.markAsUntrustedRequested(root.publicKey, d.contactDetails)
}
}
StatusAction {
@ -467,7 +467,6 @@ Pane {
enabled: d.contactDetails.trustStatus === Constants.trustStatus.untrustworthy && !d.isBlocked
onTriggered: {
root.contactsStore.removeTrustStatus(root.publicKey)
d.reload()
}
}
StatusAction {

View File

@ -222,8 +222,8 @@ StatusMenu {
text: qsTr("Mark as untrusted")
icon.name: "warning"
type: StatusAction.Type.Danger
enabled: !root.isMe && root.userTrustIsUnknown && !root.isBridgedAccount && !root.isBlockedContact
onTriggered: root.store.contactsStore.markUntrustworthy(root.selectedUserPublicKey)
enabled: !root.isMe && !root.userIsUntrustworthy && !root.isBridgedAccount && !root.isBlockedContact
onTriggered: Global.markAsUntrustedRequested(root.selectedUserPublicKey, root.contactDetails)
}
StatusAction {

View File

@ -40,6 +40,7 @@ QtObject {
signal openActivityCenterPopupRequested()
signal openSendIDRequestPopup(string publicKey, var contactDetails, var cb)
signal openContactRequestPopup(string publicKey, var contactDetails, var cb)
signal markAsUntrustedRequested(string publicKey, var contactDetails)
signal removeContactRequested(string displayName, string publicKey)
signal openInviteFriendsToCommunityPopup(var community, var communitySectionModule, var cb)
signal openIncomingIDRequestPopup(string publicKey, var cb)