feat(Profile flow): Respond to/review an incoming CR

- implement the new "Reviewing contact request" popup & flow
- adjust storybook

Fixes #13519
This commit is contained in:
Lukáš Tinkl 2024-02-29 22:01:33 +01:00 committed by Lukáš Tinkl
parent babedf4272
commit d12490ab18
8 changed files with 126 additions and 26 deletions

View File

@ -148,6 +148,22 @@ SplitView {
ctrlContactRequestState.currentIndex = ctrlContactRequestState.indexOfValue(Constants.ContactRequestState.Sent)
}
function acceptContactRequest(publicKey, contactRequestId) {
logs.logEvent("rootStore::contactStore::acceptContactRequest", ["publicKey, contactRequestId"], arguments)
ctrlContactRequestState.currentIndex = ctrlContactRequestState.indexOfValue(Constants.ContactRequestState.Mutual)
}
function getLatestContactRequestForContactAsJson(pubKey) {
logs.logEvent("rootStore::contactStore::getLatestContactRequestForContactAsJson", ["pubKey"], arguments)
return {
id: "123456789",
from: pubKey,
clock: Date.now(),
text: "Hey Jo, its Alex here, we met at devcon last week!",
contactRequestState: Constants.ContactRequestState.Received
}
}
function sendVerificationRequest(publicKey, challenge) {
logs.logEvent("rootStore::contactStore::sendVerificationRequest", ["publicKey", "challenge"], arguments)
ctrlVerificationStatus.currentIndex = ctrlVerificationStatus.indexOfValue(Constants.verificationStatus.verifying)

View File

@ -53,6 +53,7 @@ QtObject {
Global.openIncomingIDRequestPopup.connect(openIncomingIDRequestPopup)
Global.openInviteFriendsToCommunityPopup.connect(openInviteFriendsToCommunityPopup)
Global.openContactRequestPopup.connect(openContactRequestPopup)
Global.openReviewContactRequestPopup.connect(openReviewContactRequestPopup)
Global.openChooseBrowserPopup.connect(openChooseBrowserPopup)
Global.openDownloadModalRequested.connect(openDownloadModal)
Global.openImagePopup.connect(openImagePopup)
@ -222,6 +223,19 @@ QtObject {
openPopup(sendContactRequestPopupComponent, popupProperties, cb)
}
function openReviewContactRequestPopup(publicKey, contactDetails, cb) {
try {
const crDetails = rootStore.contactStore.getLatestContactRequestForContactAsJson(publicKey)
if (crDetails.from !== publicKey) {
console.warn("Popups.openReviewContactRequestPopup: not matching publicKey:", publicKey)
return
}
openPopup(reviewContactRequestPopupComponent, {publicKey, contactDetails, crDetails}, cb)
} catch (e) {
console.error("Popups.openReviewContactRequestPopup: error getting or parsing contact request data", e)
}
}
function openPinnedMessagesPopup(store, messageStore, pinnedMessagesModel, messageToPin, chatId) {
openPopup(pinnedMessagesPopup, {
store: store,
@ -467,6 +481,23 @@ QtObject {
}
},
Component {
id: reviewContactRequestPopupComponent
ReviewContactRequestPopup {
onAccepted: {
rootStore.contactStore.acceptContactRequest(publicKey, contactRequestId)
Global.displaySuccessToastMessage(qsTr("Contact request accepted"))
close()
}
onDiscarded: {
rootStore.contactStore.dismissContactRequest(publicKey, contactRequestId)
Global.displaySuccessToastMessage(qsTr("Contact request ignored"))
close()
}
onClosed: destroy()
}
},
Component {
id: backupSeedModalComponent
BackupSeedModal {

View File

@ -8,8 +8,6 @@ import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as SQUtils
import shared.views.chat 1.0
import utils 1.0
CommonContactDialog {

View File

@ -0,0 +1,61 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQml.Models 2.15
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1
import utils 1.0
CommonContactDialog {
id: root
// expected roles: id, from, clock, text, contactRequestState
required property var crDetails
signal accepted(string contactRequestId)
signal discarded(string contactRequestId)
title: qsTr("Review contact request")
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: msgColumn.implicitHeight + msgColumn.anchors.topMargin + msgColumn.anchors.bottomMargin
color: "transparent"
border.width: 1
border.color: Theme.palette.baseColor2
radius: Style.current.radius
ColumnLayout {
id: msgColumn
anchors.fill: parent
anchors.margins: Style.current.padding
StatusTimeStampLabel {
Layout.maximumWidth: parent.width
timestamp: crDetails.clock
}
StatusBaseText {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: crDetails.text
}
}
}
rightButtons: ObjectModel {
StatusFlatButton {
text: qsTr("Ignore")
objectName: "ignoreButton"
onClicked: root.discarded(crDetails.id ?? "")
}
StatusButton {
text: qsTr("Accept")
type: StatusBaseButton.Type.Success
objectName: "acceptButton"
onClicked: root.accepted(crDetails.id ?? "")
}
}
}

View File

@ -31,3 +31,4 @@ MarkAsUntrustedPopup 1.0 MarkAsUntrustedPopup.qml
RemoveContactPopup 1.0 RemoveContactPopup.qml
MarkAsIDVerifiedDialog 1.0 MarkAsIDVerifiedDialog.qml
RemoveIDVerificationDialog 1.0 RemoveIDVerificationDialog.qml
ReviewContactRequestPopup 1.0 ReviewContactRequestPopup.qml

View File

@ -143,29 +143,14 @@ Pane {
}
}
// TODO a popup here instead of buttons
Component {
id: btnAcceptContactRequestComponent
ColumnLayout {
spacing: Style.current.halfPadding
StatusBaseText {
color: Theme.palette.baseColor1
font.pixelSize: 13
StatusButton {
objectName: "profileDialog_reviewContactRequestButton"
size: StatusButton.Size.Small
text: qsTr("Review contact request")
}
AcceptRejectOptionsButtonsPanel {
menuButton.visible: false
onAcceptClicked: {
root.contactsStore.acceptContactRequest(root.publicKey, "")
d.reload()
}
onDeclineClicked: {
root.contactsStore.dismissContactRequest(root.publicKey)
d.reload()
}
}
onClicked: Global.openReviewContactRequestPopup(root.publicKey, d.contactDetails,
popup => popup.closed.connect(d.reload))
}
}
@ -175,7 +160,8 @@ Pane {
objectName: "profileDialog_sendContactRequestButton"
size: StatusButton.Size.Small
text: qsTr("Send contact request")
onClicked: Global.openContactRequestPopup(root.publicKey, d.contactDetails, null)
onClicked: Global.openContactRequestPopup(root.publicKey, d.contactDetails,
popup => popup.closed.connect(d.reload))
}
}

View File

@ -52,7 +52,7 @@ StatusMenu {
}
readonly property bool hasPendingContactRequest: {
return !root.isMe && root.selectedUserPublicKey !== "" &&
root.store.contactsStore.hasPendingContactRequest(root.selectedUserPublicKey);
contactDetails.contactRequestState === Constants.ContactRequestState.Received
}
readonly property bool hasActiveReceivedVerificationRequestFrom: {
if (!root.selectedUserPublicKey || root.isMe || !root.isContact) {
@ -127,7 +127,13 @@ StatusMenu {
}
}
// TODO Review contact request popup
StatusAction {
text: qsTr("Review contact request")
objectName: "reviewContactRequest_StatusItem"
icon.name: "add-contact"
enabled: !root.isMe && !root.isContact && !root.isBridgedAccount && !root.isBlockedContact && root.hasPendingContactRequest
onTriggered: Global.openReviewContactRequestPopup(root.selectedUserPublicKey, root.contactDetails, null)
}
SendMessageMenuItem {
id: sendMessageMenuItem

View File

@ -42,6 +42,7 @@ QtObject {
signal openMarkAsIDVerifiedPopup(string publicKey, var contactDetails, var cb)
signal openRemoveIDVerificationDialog(string publicKey, var contactDetails, var cb)
signal openContactRequestPopup(string publicKey, var contactDetails, var cb)
signal openReviewContactRequestPopup(string publicKey, var contactDetails, var cb)
signal markAsUntrustedRequested(string publicKey, var contactDetails)
signal removeContactRequested(string publicKey, var contactDetails)
signal openInviteFriendsToCommunityPopup(var community, var communitySectionModule, var cb)