refactor: refactor several popups to make them functional and add them to storybook

This commit is contained in:
Iuri Matias 2024-09-30 08:50:14 -04:00
parent 540634325d
commit 08ba75237f
9 changed files with 379 additions and 104 deletions

View File

@ -0,0 +1,138 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import shared.popups 1.0
import Models 1.0
import utils 1.0
import shared.status 1.0
SplitView {
id: root
Pane {
SplitView.fillWidth: true
SplitView.fillHeight: true
ColumnLayout {
anchors.fill: parent
spacing: 20
Item {
Layout.preferredHeight: 50
}
Button {
text: "Open Contact Verification Request Popup"
Layout.alignment: Qt.AlignHCenter
onClicked: contactVerificationRequestPopup.open()
}
Item {
Layout.preferredWidth: contactVerificationRequestPopup.implicitWidth
Layout.preferredHeight: contactVerificationRequestPopup.implicitHeight
Layout.alignment: Qt.AlignHCenter
ContactVerificationRequestPopup {
id: contactVerificationRequestPopup
visible: false
senderPublicKey: senderPublicKeyInput.text
challengeText: challengeTextInput.text
messageTimestamp: messageTimestampInput.value
onVerificationRefused: {
log("Verification request declined")
}
onResponseSent: {
log("Response sent: " + response)
}
}
}
}
}
Pane {
SplitView.minimumWidth: 300
SplitView.preferredWidth: 400
SplitView.fillHeight: true
ColumnLayout {
anchors.fill: parent
spacing: 16
Label {
text: "Contact Verification Request Popup Settings"
font.bold: true
font.pixelSize: 16
}
Label { text: "Sender Public Key" }
TextField {
id: senderPublicKeyInput
Layout.fillWidth: true
placeholderText: "Enter sender's public key"
}
Label { text: "Challenge Text" }
TextArea {
id: challengeTextInput
Layout.fillWidth: true
placeholderText: "Enter challenge text"
}
Label { text: "Message Timestamp" }
SpinBox {
id: messageTimestampInput
Layout.fillWidth: true
from: 0
to: 2147483647 // Max 32-bit integer
value: Date.now()
}
Item {
Layout.fillHeight: true
}
// Add logs section
ColumnLayout {
Layout.fillWidth: true
spacing: 8
Label {
text: "Logs"
font.bold: true
font.pixelSize: 16
}
ScrollView {
Layout.fillWidth: true
Layout.preferredHeight: 150
clip: true
TextArea {
id: logsTextArea
readOnly: true
wrapMode: TextEdit.Wrap
selectByMouse: true
}
}
Button {
text: "Clear Logs"
onClicked: logsTextArea.clear()
}
}
}
}
// Add log function
function log(message) {
var timestamp = new Date().toLocaleTimeString(Qt.locale(), "HH:mm:ss")
logsTextArea.append(timestamp + ": " + message)
}
}

View File

@ -45,11 +45,15 @@ SplitView {
verificationStatus: verificationStatusSelector.currentValue
verificationChallenge: challengeInput.text
verificationResponse: responseInput.text
verificationResponseDisplayName: nameInput.text
verificationResponseIcon: iconInput.text
verificationResponseDisplayName: verificationResponseNameInput.text
verificationResponseIcon: verificationResponseIconInput.text
verificationRequestedAt: requestedAtInput.text
verificationRepliedAt: repliedAtInput.text
ensVerified: ensVerifiedCheckBox.checked
pubKey: pubKeyInput.text
preferredName: preferredNameInput.text
name: nameInput.text
icon: iconInput.text
onVerificationRequestCanceled: {
log("Verification request canceled")
}
@ -122,6 +126,20 @@ SplitView {
placeholderText: "Enter response"
}
Label { text: "Verification Response Display Name" }
TextField {
id: verificationResponseNameInput
Layout.fillWidth: true
placeholderText: "Enter verification response display name"
}
Label { text: "Verification Response Icon" }
TextField {
id: verificationResponseIconInput
Layout.fillWidth: true
placeholderText: "Enter verification response icon"
}
Label { text: "Requested At" }
TextField {
id: requestedAtInput
@ -136,6 +154,20 @@ SplitView {
placeholderText: "Enter replied time"
}
Label { text: "Public Key" }
TextField {
id: pubKeyInput
Layout.fillWidth: true
placeholderText: "Enter public key"
}
Label { text: "Preferred Name" }
TextField {
id: preferredNameInput
Layout.fillWidth: true
placeholderText: "Enter preferred name"
}
CheckBox {
id: ensVerifiedCheckBox
text: "ENS Verified"

View File

@ -0,0 +1,136 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import shared.popups 1.0
import Models 1.0
import utils 1.0
import shared.status 1.0
SplitView {
id: root
Pane {
SplitView.fillWidth: true
SplitView.fillHeight: true
ColumnLayout {
anchors.fill: parent
spacing: 20
Item {
Layout.preferredHeight: 50
}
Button {
text: "Open Send Contact Request Modal"
Layout.alignment: Qt.AlignHCenter
onClicked: sendContactRequestModal.open()
}
Item {
Layout.preferredWidth: sendContactRequestModal.implicitWidth
Layout.preferredHeight: sendContactRequestModal.implicitHeight
Layout.alignment: Qt.AlignHCenter
SendContactRequestModal {
id: sendContactRequestModal
visible: false
labelText: labelTextInput.text
challengeText: challengeTextInput.text
buttonText: buttonTextInput.text
onAccepted: function(message) {
log("Contact request sent with message: " + message)
}
}
}
}
}
Pane {
SplitView.minimumWidth: 300
SplitView.preferredWidth: 400
SplitView.fillHeight: true
ColumnLayout {
anchors.fill: parent
spacing: 16
Label {
text: "Send Contact Request Modal Settings"
font.bold: true
font.pixelSize: 16
}
Label { text: "Label Text" }
TextField {
id: labelTextInput
Layout.fillWidth: true
text: qsTr("Why should they accept your contact request?")
placeholderText: "Enter label text"
}
Label { text: "Challenge Text" }
TextField {
id: challengeTextInput
Layout.fillWidth: true
text: qsTr("Write a short message telling them who you are...")
placeholderText: "Enter challenge text"
}
Label { text: "Button Text" }
TextField {
id: buttonTextInput
Layout.fillWidth: true
text: qsTr("Send contact request")
placeholderText: "Enter button text"
}
Item {
Layout.fillHeight: true
}
// Add logs section
ColumnLayout {
Layout.fillWidth: true
spacing: 8
Label {
text: "Logs"
font.bold: true
font.pixelSize: 16
}
ScrollView {
Layout.fillWidth: true
Layout.preferredHeight: 150
clip: true
TextArea {
id: logsTextArea
readOnly: true
wrapMode: TextEdit.Wrap
selectByMouse: true
}
}
Button {
text: "Clear Logs"
onClicked: logsTextArea.clear()
}
}
}
}
// Add log function
function log(message) {
var timestamp = new Date().toLocaleTimeString(Qt.locale(), "HH:mm:ss")
logsTextArea.append(timestamp + ": " + message)
}
}

View File

@ -281,7 +281,11 @@ QtObject {
largeImage: contactDetails.largeImage,
isContact: contactDetails.isContact,
trustStatus: contactDetails.trustStatus,
isBlocked: contactDetails.isBlocked
isBlocked: contactDetails.isBlocked,
pubKey: Global.userProfile.pubKey,
preferredName: Global.userProfile.preferredName,
name: Global.userProfile.name,
icon: Global.userProfile.icon
}
openPopup(contactOutgoingVerificationRequestPopupComponent, popupProperties, cb)
} catch (e) {
@ -291,7 +295,15 @@ QtObject {
function openIncomingIDRequestPopup(publicKey, contactDetails, cb) {
let details = contactDetails ?? Utils.getContactDetailsAsJson(publicKey)
openPopup(contactVerificationRequestPopupComponent, {publicKey, contactDetails: details})
openPopup(contactVerificationRequestPopupComponent, {
publicKey: publicKey,
senderPublicKey: request.from,
challengeText: request.challenge,
responseText: request.response,
messageTimestamp: request.requestedAt,
requestStatus: request.requestStatus
})
}
function openInviteFriendsToCommunityPopup(community, communitySectionModule, cb) {
@ -310,7 +322,16 @@ QtObject {
let details = contactDetails ?? Utils.getContactDetailsAsJson(publicKey, false)
const popupProperties = {
publicKey: publicKey,
contactDetails: details
// contactDetails: details
localNickname: details.localNickname,
name: details.name,
displayName: details.displayName,
alias: details.alias,
ensVerified: details.ensVerified,
onlineStatus: details.onlineStatus,
largeImage: details.largeImage,
isContact: details.isContact,
trustStatus: details.trustStatus,
}
openPopup(sendContactRequestPopupComponent, popupProperties, cb)
}
@ -322,7 +343,14 @@ QtObject {
console.warn("Popups.openReviewContactRequestPopup: not matching publicKey:", publicKey)
return
}
openPopup(reviewContactRequestPopupComponent, {publicKey, contactDetails, ...crDetails}, cb)
openPopup(reviewContactRequestPopupComponent, {
publicKey,
contactRequestId: crDetails.id,
fromAddress: crDetails.from,
clock: crDetails.requestedAt,
text: crDetails.challenge,
contactRequestState: crDetails.requestStatus
}, cb)
} catch (e) {
console.error("Popups.openReviewContactRequestPopup: error getting or parsing contact request data", e)
}
@ -512,13 +540,13 @@ QtObject {
Component {
id: contactVerificationRequestPopupComponent
ContactVerificationRequestPopup {
contactsStore: rootStore.contactStore
onResponseSent: (senderPublicKey, response) => {
contactsStore.acceptVerificationRequest(senderPublicKey, response)
id: contactVerificationRequestPopup
onResponseSent: (response) => {
contactsStore.acceptVerificationRequest(contactVerificationRequestPopup.senderPublicKey, response)
Global.displaySuccessToastMessage(qsTr("ID verification reply sent"))
}
onVerificationRefused: (senderPublicKey) => {
contactsStore.declineVerificationRequest(senderPublicKey)
onVerificationRefused: () => {
contactsStore.declineVerificationRequest(contactVerificationRequestPopup.senderPublicKey)
Global.displaySuccessToastMessage(qsTr("ID verification request declined"))
}
onClosed: destroy()
@ -551,8 +579,8 @@ QtObject {
Component {
id: sendIDRequestPopupComponent
SendContactRequestModal {
rootStore: root.rootStore
onAccepted: rootStore.contactStore.sendVerificationRequest(publicKey, message)
id: sendIDRequestPopup
onAccepted: rootStore.contactStore.sendVerificationRequest(sendIDRequestPopup.publicKey, sendIDRequestPopup.message)
onClosed: destroy()
}
},
@ -609,8 +637,8 @@ QtObject {
id: sendContactRequestPopupComponent
SendContactRequestModal {
rootStore: root.rootStore
onAccepted: rootStore.contactStore.sendContactRequest(publicKey, message)
id: sendContactRequestPopup
onAccepted: rootStore.contactStore.sendContactRequest(sendContactRequestPopup.publicKey, sendContactRequestPopup.message)
onClosed: destroy()
}
},

View File

@ -15,7 +15,6 @@ CommonContactDialog {
readonly property bool removeIDVerification: ctrlRemoveIDVerification.checked
readonly property bool removeContact: ctrlRemoveContact.checked
// New properties to replace contactDetails
property bool isContact: false
property int outgoingVerificationStatus: Constants.verificationStatus.untrustworthy
property int incomingVerificationStatus: Constants.verificationStatus.untrustworthy

View File

@ -15,51 +15,18 @@ import AppLayouts.Profile.stores 1.0 as ProfileStores
CommonContactDialog {
id: root
required property ProfileStores.ContactsStore contactsStore
property string senderPublicKey: ""
property string challengeText: ""
property string responseText: ""
property double messageTimestamp: 0
property double responseTimestamp: 0
signal verificationRefused(string senderPublicKey)
signal responseSent(string senderPublicKey, string response)
function updateVerificationDetails() {
try {
const request = root.contactsStore.getVerificationDetailsFromAsJson(root.publicKey)
if (request.requestStatus === Constants.verificationStatus.canceled) {
root.close()
}
d.senderPublicKey = request.from
d.challengeText = request.challenge
d.responseText = request.response
d.messageTimestamp = request.requestedAt
} catch (e) {
console.error("Error getting or parsing verification data", e)
}
}
readonly property var _con: Connections {
target: root.contactsStore.receivedContactRequestsModel ?? null
function onItemChanged(pubKey) {
if (pubKey === root.publicKey)
root.updateVerificationDetails()
}
}
readonly property var d: QtObject {
id: d
property string senderPublicKey
property string challengeText
property string responseText
property double messageTimestamp
property double responseTimestamp
}
signal verificationRefused()
signal responseSent(string response)
title: qsTr("Reply to ID verification request")
onAboutToShow: {
root.updateVerificationDetails()
verificationResponse.input.edit.forceActiveFocus()
}
@ -78,12 +45,12 @@ CommonContactDialog {
StatusTimeStampLabel {
Layout.fillWidth: true
timestamp: d.messageTimestamp
timestamp: root.messageTimestamp
}
StatusBaseText {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: d.challengeText
text: root.challengeText
}
}
}
@ -107,7 +74,7 @@ CommonContactDialog {
type: StatusBaseButton.Type.Danger
objectName: "refuseVerificationButton"
onClicked: {
root.verificationRefused(d.senderPublicKey)
root.verificationRefused()
root.close()
}
}
@ -117,9 +84,9 @@ CommonContactDialog {
objectName: "sendAnswerButton"
enabled: verificationResponse.text !== ""
onClicked: {
root.responseSent(d.senderPublicKey, SQUtils.StringUtils.escapeHtml(verificationResponse.text))
d.responseText = verificationResponse.text
d.responseTimestamp = Date.now()
root.responseSent(SQUtils.StringUtils.escapeHtml(verificationResponse.text))
root.responseText = verificationResponse.text
root.responseTimestamp = Date.now()
root.close()
}
}

View File

@ -12,7 +12,6 @@ import utils 1.0
CommonContactDialog {
id: root
// New properties to replace contactDetails, with default values
property int verificationStatus: Constants.verificationStatus.unverified
property int incomingVerificationStatus: Constants.verificationStatus.unverified
property bool isContact: false

View File

@ -21,13 +21,17 @@ CommonContactDialog {
property string verificationRequestedAt
property string verificationRepliedAt
property bool ensVerified
property string pubKey
property string preferredName
property string name
property string icon
readonly property bool hasReply: root.verificationResponse !== ""
signal verificationRequestCanceled()
signal untrustworthyVerified()
signal trustedVerified()
signal onLinkActivated()
signal linkActivated()
title: !hasReply ? qsTr("ID verification pending") : qsTr("Review ID verification reply")
@ -72,11 +76,11 @@ CommonContactDialog {
id: challengeMessage
timestamp: root.verificationRequestedAt
messageDetails.messageText: root.verificationChallenge
messageDetails.sender.id: Global.userProfile.pubKey
messageDetails.sender.displayName: Global.userProfile.name
messageDetails.sender.profileImage.name: Global.userProfile.icon
messageDetails.sender.id: root.pubKey
messageDetails.sender.displayName: root.name
messageDetails.sender.profileImage.name: root.icon
messageDetails.sender.profileImage.assetSettings.isImage: true
messageDetails.sender.profileImage.colorId: Utils.colorIdForPubkey(Global.userProfile.pubKey)
messageDetails.sender.profileImage.colorId: Utils.colorIdForPubkey(root.pubKey)
messageDetails.sender.profileImage.colorHash: Utils.getColorHashAsJson(Global.userProfile.pubKey, !!Global.userProfile.preferredName)
messageDetails.sender.isEnsVerified: !!Global.userProfile.preferredName
Layout.fillWidth: true
@ -107,6 +111,6 @@ CommonContactDialog {
wrapMode: Text.WordWrap
textFormat: Text.RichText
color: root.hasReply ? Theme.palette.directColor1 : Theme.palette.baseColor1
onLinkActivated: root.onLinkActivated()
onLinkActivated: root.linkActivated()
}
}

View File

@ -15,8 +15,6 @@ import AppLayouts.stores 1.0 as AppLayoutStores
CommonContactDialog {
id: root
property AppLayoutStores.RootStore rootStore
property string labelText: qsTr("Why should they accept your contact request?")
property string challengeText: qsTr("Write a short message telling them who you are...")
property string buttonText: qsTr("Send contact request")
@ -25,49 +23,23 @@ CommonContactDialog {
title: qsTr("Send contact request")
onAboutToShow: {
messageInput.input.edit.forceActiveFocus()
// (request) update from mailserver
if (d.userDisplayName === "") {
root.rootStore.contactStore.requestContactInfo(root.publicKey)
root.loadingContactDetails = true
}
}
readonly property var d: QtObject {
id: d
readonly property int maxMsgLength: 280
readonly property int minMsgLength: 1
readonly property int msgHeight: 152
}
readonly property var _conn: Connections {
target: root.rootStore.contactStore.contactsModule
function onContactInfoRequestFinished(publicKey, ok) {
if (publicKey !== root.publicKey)
return
if (ok)
root.contactDetails = Utils.getContactDetailsAsJson(root.publicKey, false)
root.loadingContactDetails = false
}
}
readonly property int maxMsgLength: 280
readonly property int minMsgLength: 1
readonly property int msgHeight: 152
StatusInput {
id: messageInput
input.edit.objectName: "ProfileSendContactRequestModal_sayWhoYouAreInput"
Layout.fillWidth: true
label: root.labelText
charLimit: d.maxMsgLength
charLimit: root.maxMsgLength
placeholderText: root.challengeText
input.multiline: true
minimumHeight: d.msgHeight
maximumHeight: d.msgHeight
minimumHeight: root.msgHeight
maximumHeight: root.msgHeight
input.verticalAlignment: TextEdit.AlignTop
validators: StatusMinLengthValidator {
minLength: d.minMsgLength
minLength: root.minMsgLength
errorMessage: Utils.getErrorMessage(messageInput.errors, qsTr("who are you"))
}
}