wip: chat request payment card
This commit is contained in:
parent
300545a3b0
commit
df348629c4
|
@ -17,6 +17,9 @@ SplitView {
|
|||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property var exampleAlbum: [ModelsData.banners.coinbase, ModelsData.icons.status]
|
||||
readonly property var requestPaymentModel: RequestPaymentModel {}
|
||||
|
||||
readonly property var messagesModel: ListModel {
|
||||
ListElement {
|
||||
timestamp: 1656937930123
|
||||
|
@ -152,6 +155,28 @@ SplitView {
|
|||
trustIndicator: StatusContactVerificationIcons.TrustedType.None
|
||||
outgoingStatus: StatusMessage.OutgoingStatus.Delivered
|
||||
}
|
||||
ListElement {
|
||||
timestamp: 1667937830123
|
||||
senderId: "zq123456790"
|
||||
senderDisplayName: "Alice"
|
||||
contentType: StatusMessage.ContentType.Image
|
||||
message: "This message contains images"
|
||||
isContact: true
|
||||
isAReply: false
|
||||
trustIndicator: StatusContactVerificationIcons.TrustedType.None
|
||||
outgoingStatus: StatusMessage.OutgoingStatus.Delivered
|
||||
}
|
||||
ListElement {
|
||||
timestamp: 1667937830123
|
||||
senderId: "zq123456790"
|
||||
senderDisplayName: "Alice"
|
||||
contentType: StatusMessage.ContentType.Attachment
|
||||
message: "This message contains attachments"
|
||||
isContact: true
|
||||
isAReply: false
|
||||
trustIndicator: StatusContactVerificationIcons.TrustedType.None
|
||||
outgoingStatus: StatusMessage.OutgoingStatus.Delivered
|
||||
}
|
||||
}
|
||||
readonly property var colorHash: ListModel {
|
||||
ListElement { colorId: 13; segmentLength: 5 }
|
||||
|
@ -202,6 +227,11 @@ SplitView {
|
|||
colorId: index
|
||||
colorHash: d.colorHash
|
||||
}
|
||||
album: model.contentType === StatusMessage.ContentType.Image
|
||||
|| model.contentType === StatusMessage.ContentType.Attachment ? d.exampleAlbum : []
|
||||
albumCount: model.contentType === StatusMessage.ContentType.Image
|
||||
|| model.contentType === StatusMessage.ContentType.Attachment ? d.exampleAlbum.length : 0
|
||||
requestPaymentModel: model.contentType === StatusMessage.ContentType.Attachment ? d.requestPaymentModel : null
|
||||
}
|
||||
|
||||
replyDetails {
|
||||
|
@ -222,6 +252,8 @@ SplitView {
|
|||
onReplyMessageClicked: logs.logEvent("StatusMessage::replyMessageClicked")
|
||||
onResendClicked: logs.logEvent("StatusMessage::resendClicked")
|
||||
onLinkActivated: logs.logEvent("StatusMessage::linkActivated" + link)
|
||||
onRequestPaymentClicked: logs.logEvent("StatusMessage::requestPaymentActivated")
|
||||
onImageClicked: logs.logEvent("StatusMessage::imageClicked")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ Item {
|
|||
property StatusMessage controlUnderTest: null
|
||||
|
||||
TestCase {
|
||||
name: "TokenSelectorView"
|
||||
name: "StatusMessage"
|
||||
when: windowShown
|
||||
|
||||
function init() {
|
||||
|
@ -86,5 +86,70 @@ Item {
|
|||
|
||||
compare(actualLinkCount, data.validAddressEnsCount, "TextEdit should contain a link %1".arg(data.messageText))
|
||||
}
|
||||
|
||||
function test_attachment_empty() {
|
||||
verify(!!controlUnderTest)
|
||||
controlUnderTest.messageDetails.contentType = StatusMessage.ContentType.Attachment
|
||||
controlUnderTest.messageDetails.messageText = ""
|
||||
waitForRendering(controlUnderTest)
|
||||
|
||||
const statusTextMessage = findChild(controlUnderTest, "StatusMessage_textMessage")
|
||||
verify(!statusTextMessage)
|
||||
const imageAlbum = findChild(controlUnderTest, "StatusMessage_imageAlbum")
|
||||
verify(!!imageAlbum)
|
||||
compare(imageAlbum.albumCount, 0)
|
||||
const image = findChild(imageAlbum, "album_image_loader_0")
|
||||
verify(!image)
|
||||
const requestPaymentItem = findChild(controlUnderTest, "StatusMessage_requestPaymentDelegate_0")
|
||||
verify(!requestPaymentItem)
|
||||
}
|
||||
|
||||
function test_attachment_only_text() {
|
||||
verify(!!controlUnderTest)
|
||||
controlUnderTest.messageDetails.contentType = StatusMessage.ContentType.Attachment
|
||||
controlUnderTest.messageDetails.messageText = "test message"
|
||||
waitForRendering(controlUnderTest)
|
||||
|
||||
const statusTextMessage = findChild(controlUnderTest, "StatusMessage_textMessage")
|
||||
verify(!!statusTextMessage)
|
||||
verify(statusTextMessage.textField.text.indexOf("test message") > 0)
|
||||
const imageAlbum = findChild(controlUnderTest, "StatusMessage_imageAlbum")
|
||||
verify(!!imageAlbum)
|
||||
compare(imageAlbum.albumCount, 0)
|
||||
const image = findChild(imageAlbum, "album_image_loader_0")
|
||||
verify(!image)
|
||||
const requestPaymentItem = findChild(controlUnderTest, "StatusMessage_requestPaymentDelegate_0")
|
||||
verify(!requestPaymentItem)
|
||||
}
|
||||
|
||||
function test_attachment_multiple_attachments() {
|
||||
verify(!!controlUnderTest)
|
||||
controlUnderTest.messageDetails.contentType = StatusMessage.ContentType.Attachment
|
||||
controlUnderTest.messageDetails.messageText = "test message with attachments"
|
||||
controlUnderTest.messageDetails.album = [ "image0", "image1", "image2" ]
|
||||
controlUnderTest.messageDetails.albumCount = 3
|
||||
controlUnderTest.messageDetails.requestPaymentModel = [
|
||||
{amount: "0.1", currency: "ETH", address: "0x1234567890abcdef1234567890abcdef12345678", chainId: 1},
|
||||
{amount: "0.2", currency: "DAI", address: "0xAbCdEf1234567890abcdef1234567890AbCdEf12", chainId: 10},
|
||||
]
|
||||
waitForRendering(controlUnderTest)
|
||||
|
||||
const statusTextMessage = findChild(controlUnderTest, "StatusMessage_textMessage")
|
||||
verify(!!statusTextMessage)
|
||||
verify(statusTextMessage.textField.text.indexOf("test message with attachments") > 0)
|
||||
const imageAlbum = findChild(controlUnderTest, "StatusMessage_imageAlbum")
|
||||
verify(!!imageAlbum)
|
||||
compare(imageAlbum.albumCount, 3)
|
||||
for (let i = 0 ; i < 3 ; i++) {
|
||||
const image = findChild(imageAlbum, "album_image_loader_"+i)
|
||||
verify(!!image)
|
||||
}
|
||||
const requestPaymentItem0 = findChild(controlUnderTest, "StatusMessage_requestPaymentDelegate_0")
|
||||
verify(!!requestPaymentItem0)
|
||||
const requestPaymentItem1 = findChild(controlUnderTest, "StatusMessage_requestPaymentDelegate_1")
|
||||
verify(!!requestPaymentItem1)
|
||||
const requestPaymentItem2 = findChild(controlUnderTest, "StatusMessage_requestPaymentDelegate_2")
|
||||
verify(!requestPaymentItem2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import StatusQ.Core.Theme 0.1
|
|||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import shared.controls.chat 1.0
|
||||
|
||||
import "./private/statusMessage"
|
||||
|
||||
Control {
|
||||
|
@ -26,7 +28,8 @@ Control {
|
|||
SystemMessageMutualEventSent = 15,
|
||||
SystemMessageMutualEventAccepted = 16,
|
||||
SystemMessageMutualEventRemoved = 17,
|
||||
BridgeMessage = 18
|
||||
BridgeMessage = 18,
|
||||
Attachment = 19
|
||||
}
|
||||
|
||||
enum OutgoingStatus {
|
||||
|
@ -89,6 +92,7 @@ Control {
|
|||
signal addReactionClicked(var sender, var mouse)
|
||||
signal toggleReactionClicked(int emojiId)
|
||||
signal imageClicked(var image, var mouse, var imageSource)
|
||||
signal requestPaymentClicked(var symbol, var amount, var address, var chainId)
|
||||
signal stickerClicked()
|
||||
signal resendClicked()
|
||||
|
||||
|
@ -299,7 +303,7 @@ Control {
|
|||
}
|
||||
}
|
||||
Loader {
|
||||
active: root.messageDetails.contentType === StatusMessage.ContentType.Image && !editMode
|
||||
active: root.messageDetails.contentType === StatusMessage.ContentType.Image && !editMode
|
||||
visible: active
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
@ -312,6 +316,7 @@ Control {
|
|||
anchors.right: parent.right
|
||||
visible: active
|
||||
sourceComponent: StatusTextMessage {
|
||||
objectName: "StatusMessage_textMessage"
|
||||
messageDetails: root.messageDetails
|
||||
isEdited: root.isEdited
|
||||
allowShowMore: !root.isInPinnedPopup
|
||||
|
@ -326,6 +331,7 @@ Control {
|
|||
Loader {
|
||||
active: true
|
||||
sourceComponent: StatusMessageImageAlbum {
|
||||
objectName: "StatusMessage_imageAlbum"
|
||||
width: messageLayout.width
|
||||
album: root.messageDetails.albumCount > 0 ? root.messageDetails.album : [root.messageDetails.messageContent]
|
||||
albumCount: root.messageDetails.albumCount > 0 ? root.messageDetails.albumCount : 1
|
||||
|
@ -337,6 +343,68 @@ Control {
|
|||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: root.messageDetails.contentType === StatusMessage.ContentType.Attachment && !editMode
|
||||
visible: active
|
||||
Layout.fillWidth: true
|
||||
|
||||
sourceComponent: Column {
|
||||
id: attachmentsColumn
|
||||
spacing: 8
|
||||
Loader {
|
||||
active: root.messageDetails.messageText !== ""
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
visible: active
|
||||
sourceComponent: StatusTextMessage {
|
||||
objectName: "StatusMessage_textMessage"
|
||||
messageDetails: root.messageDetails
|
||||
isEdited: root.isEdited
|
||||
allowShowMore: !root.isInPinnedPopup
|
||||
textField.anchors.rightMargin: root.isInPinnedPopup ? Theme.xlPadding : 0 // margin for the "Unpin" floating button
|
||||
highlightedLink: root.highlightedLink
|
||||
onLinkActivated: {
|
||||
root.linkActivated(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flow {
|
||||
width: messageLayout.width
|
||||
height: childrenRect.height + Theme.smallPadding
|
||||
Loader {
|
||||
active: true
|
||||
sourceComponent: StatusMessageImageAlbum {
|
||||
objectName: "StatusMessage_imageAlbum"
|
||||
album: root.messageDetails.albumCount > 0 ? root.messageDetails.album : [root.messageDetails.messageContent]
|
||||
albumCount: root.messageDetails.albumCount > 0 ? root.messageDetails.albumCount : 0
|
||||
imageWidth: Math.min(messageLayout.width / root.messageDetails.albumCount - 9 * (root.messageDetails.albumCount - 1), 144)
|
||||
shapeType: StatusImageMessage.ShapeType.LEFT_ROUNDED
|
||||
onImageClicked: root.imageClicked(image, mouse, imageSource)
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
active: true
|
||||
sourceComponent: RowLayout {
|
||||
Repeater {
|
||||
model: root.messageDetails.requestPaymentModel
|
||||
delegate: RequestPaymentCardDelegate {
|
||||
objectName: "StatusMessage_requestPaymentDelegate_" + model.index
|
||||
required property var model
|
||||
amount: model.amount
|
||||
symbol: model.symbol
|
||||
address: model.address
|
||||
senderName: root.messageDetails.sender.displayName
|
||||
senderImageAssetSettings: root.messageDetails.sender.profileImage.assetSettings
|
||||
onClicked: root.requestPaymentClicked(model.symbol, model.amount, model.address, model.chainId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: root.messageAttachments && !editMode
|
||||
visible: active
|
||||
|
|
|
@ -15,4 +15,5 @@ QtObject {
|
|||
property bool messageDeleted: false
|
||||
property var album: []
|
||||
property int albumCount: 0
|
||||
property var requestPaymentModel: null
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ RowLayout {
|
|||
|
||||
delegate: Loader {
|
||||
active: true
|
||||
objectName: "album_image_loader_" + index
|
||||
readonly property bool imageLoaded: index < root.album.length
|
||||
readonly property string imagePath: imageLoaded ? root.album[index] : ""
|
||||
sourceComponent: imageLoaded ? imageComponent : imagePlaceholderComponent
|
||||
|
|
|
@ -8043,6 +8043,7 @@
|
|||
<file>assets/png/chat/chat@2x.png</file>
|
||||
<file>assets/png/chat/chat@3x.png</file>
|
||||
<file>assets/png/chat/wave.png</file>
|
||||
<file>assets/png/chat/request_payment_banner.png</file>
|
||||
<file>assets/png/keycard/authenticate.png</file>
|
||||
<file>assets/png/keycard/biometrics-fail.png</file>
|
||||
<file>assets/png/keycard/biometrics-success.png</file>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
|
@ -0,0 +1,133 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Window 2.15
|
||||
import StatusQ.Core 0.1
|
||||
|
||||
import QtGraphicalEffects 1.15
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
CalloutCard {
|
||||
id: root
|
||||
|
||||
required property string amount
|
||||
required property string symbol
|
||||
required property string address
|
||||
|
||||
property string senderName
|
||||
property var senderImageAssetSettings
|
||||
|
||||
property bool highlight: false
|
||||
|
||||
signal clicked(var mouse)
|
||||
|
||||
implicitHeight: 187
|
||||
implicitWidth: 305 + 2 * borderWidth
|
||||
borderWidth: 2
|
||||
hoverEnabled: true
|
||||
dropShadow: d.highlight
|
||||
borderColor: d.highlight ? Theme.palette.background : Theme.palette.border
|
||||
|
||||
padding: 12
|
||||
|
||||
Behavior on borderColor {
|
||||
ColorAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property real bannerImageMargins: 1 / Screen.devicePixelRatio // image size isn't pixel perfect..
|
||||
property bool highlight: root.highlight || root.hovered
|
||||
property string bannerImageSource: ""
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 4
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
radius: 8
|
||||
color: Theme.palette.primaryColor3
|
||||
clip: true
|
||||
border.width: 1
|
||||
border.color: Theme.palette.primaryColor2
|
||||
|
||||
StatusImage {
|
||||
anchors.fill: parent
|
||||
asynchronous: true
|
||||
source: Theme.png("chat/request_payment_banner")
|
||||
}
|
||||
|
||||
Row {
|
||||
id: iconRow
|
||||
spacing: -8
|
||||
anchors.centerIn: parent
|
||||
StatusRoundedImage {
|
||||
id: symbolImage
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image.source: Constants.tokenIcon(root.symbol)
|
||||
width: 44
|
||||
height: width
|
||||
image.layer.enabled: true
|
||||
image.layer.effect: OpacityMask {
|
||||
id: mask
|
||||
invert: true
|
||||
|
||||
maskSource: Item {
|
||||
width: mask.width + 2
|
||||
height: mask.height + 2
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: symbolImage.width + iconRow.spacing - 2
|
||||
|
||||
width: parent.width
|
||||
height: width
|
||||
radius: width / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusSmartIdenticon {
|
||||
width: symbolImage.width
|
||||
height: symbolImage.height
|
||||
asset: root.senderImageAssetSettings
|
||||
name: root.senderName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 4
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
text: qsTr("Send %1 %2 to %3").arg(root.amount).arg(root.symbol).arg(Utils.compactAddress(root.address.toLowerCase(), 4))
|
||||
font.pixelSize: Theme.additionalTextSize
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
font.pixelSize: Theme.tertiaryTextFontSize
|
||||
color: Theme.palette.baseColor1
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: qsTr("Requested by %1").arg(root.senderName)
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: root
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: root.clicked(mouse)
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ LinkPreviewCard 1.0 LinkPreviewCard.qml
|
|||
LinkPreviewMiniCard 1.0 LinkPreviewMiniCard.qml
|
||||
LinkPreviewSettingsCard 1.0 LinkPreviewSettingsCard.qml
|
||||
LinkPreviewSettingsCardMenu 1.0 LinkPreviewSettingsCardMenu.qml
|
||||
RequestPaymentCardDelegate 1.0 RequestPaymentCardDelegate.qml
|
||||
RequestPaymentMiniCardDelegate 1.0 RequestPaymentMiniCardDelegate.qml
|
||||
MessageMouseArea 1.0 MessageMouseArea.qml
|
||||
MessageReactionsRow 1.0 MessageReactionsRow.qml
|
||||
|
|
|
@ -350,6 +350,8 @@ Loader {
|
|||
return StatusMessage.ContentType.SystemMessageMutualEventAccepted;
|
||||
case Constants.messageContentType.systemMessageMutualEventRemoved:
|
||||
return StatusMessage.ContentType.SystemMessageMutualEventRemoved;
|
||||
case Constants.messageContentType.attachmentType:
|
||||
return StatusMessage.ContentType.Attachment;
|
||||
case Constants.messageContentType.fetchMoreMessagesButton:
|
||||
case Constants.messageContentType.chatIdentifier:
|
||||
case Constants.messageContentType.unknownContentType:
|
||||
|
|
|
@ -476,6 +476,7 @@ QtObject {
|
|||
readonly property int systemMessageMutualEventAccepted: 16
|
||||
readonly property int systemMessageMutualEventRemoved: 17
|
||||
readonly property int bridgeMessageType: 18
|
||||
readonly property int attachmentType: 19
|
||||
}
|
||||
|
||||
readonly property QtObject messageModelRoles: QtObject {
|
||||
|
|
Loading…
Reference in New Issue