fix(SendContactRequestModal): Implemented contact info request and loading UI (#10177)

This commit is contained in:
Igor Sirotin 2023-04-06 10:56:50 +03:00 committed by GitHub
parent 731846c54c
commit 7ebfcd0183
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 169 additions and 21 deletions

View File

@ -89,6 +89,10 @@ proc init*(self: Controller) =
var args = VerificationRequestArgs(e)
self.delegate.onVerificationRequestUpdatedOrAdded(args.verificationRequest)
self.events.on(SIGNAL_CONTACT_INFO_REQUEST_FINISHED) do(e: Args):
let args = ContactInfoRequestArgs(e)
self.delegate.onContactInfoRequestFinished(args.publicKey, args.ok)
proc getContacts*(self: Controller, group: ContactsGroup): seq[ContactsDto] =
return self.contactsService.getContactsByGroup(group)
@ -165,3 +169,5 @@ proc getReceivedVerificationRequests*(self: Controller): seq[VerificationRequest
proc getStatusForContactWithId*(self: Controller, publicKey: string): StatusUpdateDto =
return self.contactsService.getStatusForContactWithId(publicKey)
proc requestContactInfo*(self: Controller, publicKey: string) =
self.contactsService.requestContactInfo(publicKey)

View File

@ -123,4 +123,10 @@ method onVerificationRequestCanceled*(self: AccessInterface, publicKey: string)
raise newException(ValueError, "No implementation available")
method onVerificationRequestUpdatedOrAdded*(self: AccessInterface, VerificationRequest: VerificationRequest) {.base.} =
raise newException(ValueError, "No implementation available")
method requestContactInfo*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onContactInfoRequestFinished*(self: AccessInterface, publicKey: string, ok: bool) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -276,4 +276,10 @@ method onVerificationRequestUpdatedOrAdded*(self: Module, request: VerificationR
item.incomingVerificationStatus
)
return
self.view.receivedContactRequestsModel.addItem(item)
self.view.receivedContactRequestsModel.addItem(item)
method requestContactInfo*(self: Module, publicKey: string) =
self.controller.requestContactInfo(publicKey)
method onContactInfoRequestFinished*(self: Module, publicKey: string, ok: bool) =
self.view.onContactInfoRequestFinished(publicKey, ok)

View File

@ -105,6 +105,8 @@ QtObject:
read = getSentContactRequestsModel
notify = sentContactRequestsModelChanged
proc contactInfoRequestFinished(self: View, publicKey: string, ok: bool) {.signal.}
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
# proc receivedButRejectedContactRequestsModelChanged(self: View) {.signal.}
# proc getReceivedButRejectedContactRequestsModel(self: View): QVariant {.slot.} =
@ -186,3 +188,8 @@ QtObject:
proc acceptVerificationRequest*(self: View, publicKey: string, response: string) {.slot.} =
self.delegate.acceptVerificationRequest(publicKey, response)
proc requestContactInfo*(self: View, publicKey: string) {.slot.} =
self.delegate.requestContactInfo(publicKey)
proc onContactInfoRequestFinished*(self: View, publicKey: string, ok: bool) {.slot.} =
self.contactInfoRequestFinished(publicKey, ok)

View File

@ -5,6 +5,8 @@ include ../../common/json_utils
from ../../common/conversion import isCompressedPubKey
include ../../../app/core/tasks/common
import ../../../backend/contacts as status_go
#################################################
# Async lookup ENS contact
#################################################
@ -39,4 +41,25 @@ const lookupContactTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
"uuid": arg.uuid,
"reason": arg.reason
}
arg.finish(output)
arg.finish(output)
#################################################
# Async request contact info
#################################################
type
AsyncRequestContactInfoTaskArg = ref object of QObjectTaskArg
pubkey: string
const asyncRequestContactInfoTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncRequestContactInfoTaskArg](argEncoded)
try:
let response = status_go.requestContactInfo(arg.pubkey)
arg.finish(%* {
"publicKey": arg.pubkey,
"response": response,
})
except Exception as e:
arg.finish(%* {
"error": e.msg,
})

View File

@ -47,6 +47,10 @@ type
VerificationRequestArgs* = ref object of Args
verificationRequest*: VerificationRequest
ContactInfoRequestArgs* = ref object of Args
publicKey*: string
ok*: bool
# Signals which may be emitted by this service:
const SIGNAL_ENS_RESOLVED* = "ensResolved"
const SIGNAL_CONTACT_ADDED* = "contactAdded"
@ -69,6 +73,7 @@ const SIGNAL_CONTACT_VERIFICATION_DECLINED* = "contactVerificationRequestDecline
const SIGNAL_CONTACT_VERIFICATION_ACCEPTED* = "contactVerificationRequestAccepted"
const SIGNAL_CONTACT_VERIFICATION_ADDED* = "contactVerificationRequestAdded"
const SIGNAL_CONTACT_VERIFICATION_UPDATED* = "contactVerificationRequestUpdated"
const SIGNAL_CONTACT_INFO_REQUEST_FINISHED* = "contactInfoRequestFinished"
type
ContactsGroup* {.pure.} = enum
@ -761,3 +766,29 @@ QtObject:
self.activityCenterService.parseActivityCenterResponse(response)
except Exception as e:
error "error declining contact verification request", msg=e.msg
proc asyncContactInfoLoaded*(self: Service, pubkeyAndRpcResponse: string) {.slot.} =
let rpcResponseObj = pubkeyAndRpcResponse.parseJson
let publicKey = $rpcResponseObj{"publicKey"}
if (rpcResponseObj{"response"}{"error"}.kind != JNull):
let error = Json.decode($rpcResponseObj["response"]["error"], RpcError)
error "Error requesting contact info", msg = error.message, publicKey
self.events.emit(SIGNAL_CONTACT_INFO_REQUEST_FINISHED, ContactInfoRequestArgs(publicKey: publicKey, ok: false))
return
let contact = rpcResponseObj{"response"}{"result"}.toContactsDto()
self.saveContact(contact)
self.events.emit(SIGNAL_CONTACT_INFO_REQUEST_FINISHED, ContactInfoRequestArgs(publicKey: publicKey, ok: true))
proc requestContactInfo*(self: Service, pubkey: string) =
try:
let arg = AsyncRequestContactInfoTaskArg(
tptr: cast[ByteAddress](asyncRequestContactInfoTask),
vptr: cast[ByteAddress](self.vptr),
slot: "asyncContactInfoLoaded",
pubkey: pubkey,
)
self.threadpool.start(arg)
except Exception as e:
error "Error requesting contact info", msg = e.msg, pubkey

View File

@ -112,3 +112,6 @@ proc retractContactRequest*(pubkey: string): RpcResponse[JsonNode] {.raises: [Ex
"id": pubkey
}]
result = callPrivateRPC("retractContactRequest".prefix, payload)
proc requestContactInfo*(pubkey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("requestContactInfoFromMailserver".prefix, %*[pubkey])

View File

@ -122,4 +122,8 @@ QtObject {
function verifiedUntrustworthy(pubKey) {
root.contactsModule.verifiedUntrustworthy(pubKey);
}
function requestContactInfo(publicKey) {
root.contactsModule.requestContactInfo(publicKey)
}
}

View File

@ -216,6 +216,7 @@ QtObject {
id: sendIDRequestPopupComponent
SendContactRequestModal {
anchors.centerIn: parent
rootStore: root.rootStore
onAccepted: root.rootStore.profileSectionStore.contactsStore.sendVerificationRequest(userPublicKey, message)
onClosed: destroy()
}
@ -237,6 +238,7 @@ QtObject {
SendContactRequestModal {
anchors.centerIn: parent
rootStore: root.rootStore
onAccepted: root.rootStore.profileSectionStore.contactsStore.sendContactRequest(userPublicKey, message)
onClosed: destroy()
}

View File

@ -38,6 +38,7 @@ Item {
property bool emojiHashVisible: true
property bool editImageButtonVisible: false
property bool editButtonVisible: displayNamePlusIconsVisible
property bool loading: false
readonly property bool compact: root.imageSize === ProfileHeader.ImageSize.Compact
signal clicked()
@ -116,6 +117,7 @@ Item {
imageWidth: d.getSize(36, 64, 170)
imageHeight: imageWidth
ensVerified: root.userIsEnsVerified
loading: root.loading
}
StatusRoundButton {
@ -150,17 +152,36 @@ Item {
}
}
StyledText {
Item {
Layout.fillWidth: true
visible: root.displayNameVisible
text: root.displayName
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
maximumLineCount: 3
wrapMode: Text.Wrap
font {
bold: true
pixelSize: 17
implicitHeight: displayNameLabel.implicitHeight
StyledText {
id: displayNameLabel
width: parent.width
height: parent.height
text: root.displayName
visible: !root.loading
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
maximumLineCount: 3
wrapMode: Text.Wrap
font {
bold: true
pixelSize: 17
}
}
Loader {
anchors.centerIn: parent
height: parent.height
width: 100
visible: root.loading
active: visible
sourceComponent: LoadingComponent {
radius: 4
}
}
}
@ -169,6 +190,7 @@ Item {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
visible: root.displayNamePlusIconsVisible
StyledText {
objectName: "ProfileHeader_displayName"
Layout.maximumWidth: root.width - Style.current.xlPadding

View File

@ -20,6 +20,7 @@ Loader {
property bool interactive: true
property bool disabled: false
property bool ensVerified: false
property bool loading: false
property int colorId: Utils.colorIdForPubkey(pubkey)
property var colorHash: Utils.getColorHashAsJson(pubkey, ensVerified)
@ -39,6 +40,7 @@ Loader {
ringSettings {
ringSpecModel: root.showRing ? root.colorHash : undefined
}
loading: root.loading
Loader {
anchors.fill: parent

View File

@ -14,6 +14,8 @@ import StatusQ.Popups 0.1
StatusModal {
id: root
property var rootStore
property string userPublicKey: ""
property string userDisplayName: ""
property string userIcon: ""
@ -27,7 +29,22 @@ StatusModal {
width: 480
height: 548
header.title: qsTr("Send Contact Request to %1").arg(userDisplayName)
header.title: d.loadingContactDetails ? qsTr("Send Contact Request")
: qsTr("Send Contact Request to %1").arg(d.userDisplayName)
onAboutToShow: {
messageInput.input.edit.forceActiveFocus()
const contactDetails = Utils.getContactDetailsAsJson(userPublicKey, false)
if (contactDetails.displayName !== "") {
d.updateContactDetails(contactDetails)
return
}
root.rootStore.contactStore.requestContactInfo(root.userPublicKey)
d.loadingContactDetails = true
}
QtObject {
id: d
@ -36,10 +53,30 @@ StatusModal {
readonly property int minMsgLength: 1
readonly property int msgHeight: 152
readonly property int contentSpacing: Style.current.halfPadding
property bool loadingContactDetails: false
property string userDisplayName: ""
property string userIcon: ""
property bool userIsEnsVerified
function updateContactDetails(contactDetails) {
d.userDisplayName = contactDetails.displayName
d.userIcon = contactDetails.largeImage
d.userIsEnsVerified = contactDetails.ensVerified
}
}
onAboutToShow: {
messageInput.input.edit.forceActiveFocus()
Connections {
target: root.rootStore.contactStore.contactsModule
function onContactInfoRequestFinished(publicKey, ok) {
if (ok) {
const details = Utils.getContactDetailsAsJson(userPublicKey, false)
d.updateContactDetails(details)
}
d.loadingContactDetails = false
}
}
ColumnLayout {
@ -53,14 +90,15 @@ StatusModal {
ProfileHeader {
Layout.fillWidth: true
displayName: root.userDisplayName
displayName: d.userDisplayName
pubkey: root.userPublicKey
icon: root.userIcon
userIsEnsVerified: root.userIsEnsVerified
icon: d.userIcon
userIsEnsVerified: d.userIsEnsVerified
displayNameVisible: true
pubkeyVisible: true
imageSize: ProfileHeader.ImageSize.Middle
loading: d.loadingContactDetails
}
StatusInput {
@ -78,8 +116,6 @@ StatusModal {
errorMessage: Utils.getErrorMessage(messageInput.errors, qsTr("who are you"))
}
}
Item { Layout.fillHeight: true }
}
rightButtons: StatusButton {

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit db6c05a8e8645868c45b05664b3397a262f9c07c
Subproject commit fb36298e37ae2cfc7fa4d4c3abd61f313ad142ce