Feat/request payment cards 16737 (#16740)

* feat: Payment Request cards

* feat: Card fixes
This commit is contained in:
Cuteivist 2024-12-03 09:36:04 +01:00 committed by GitHub
parent 9490dbb57e
commit 7998b0640f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 492 additions and 9 deletions

View File

@ -32,6 +32,7 @@ SplitView {
width: parent.width
imagePreviewArray: ["https://picsum.photos/200/300?random=1", "https://picsum.photos/200/300?random=1"]
linkPreviewModel: showLinkPreviewSettings ? emptyModel : mockedLinkPreviewModel
paymentRequestModel: mockedPaymentRequestModel
showLinkPreviewSettings: !linkPreviewEnabledSwitch.checked
visible: hasContent
@ -82,6 +83,10 @@ SplitView {
LinkPreviewModel {
id: mockedLinkPreviewModel
}
PaymentRequestModel {
id: mockedPaymentRequestModel
}
}
// category: Panels

View File

@ -13,6 +13,10 @@ SplitView {
id: mockedLinkPreviewModel
}
PaymentRequestModel {
id: mockedPaymentRequestModel
}
Pane {
id: messageViewWrapper
SplitView.fillWidth: true
@ -27,6 +31,10 @@ SplitView {
playAnimations: true
linkPreviewModel: mockedLinkPreviewModel
gifLinks: [ "https://media.tenor.com/qN_ytiwLh24AAAAC/cold.gif" ]
paymentRequestModel: mockedPaymentRequestModel
areTestNetworksEnabled: false
senderName: "Alice"
gifUnfurlingEnabled: false
canAskToUnfurlGifs: true
@ -70,6 +78,11 @@ SplitView {
checked: linksMessageView.isOnline
onToggled: linksMessageView.isOnline = !linksMessageView.isOnline
}
CheckBox {
text: qsTr("Testnet enabled")
checked: linksMessageView.areTestNetworksEnabled
onToggled: linksMessageView.areTestNetworksEnabled = !linksMessageView.areTestNetworksEnabled
}
}
}
}

View File

@ -17,6 +17,8 @@ SplitView {
QtObject {
id: d
readonly property var exampleAlbum: [ModelsData.banners.coinbase, ModelsData.icons.status]
readonly property var messagesModel: ListModel {
ListElement {
timestamp: 1656937930123
@ -152,6 +154,17 @@ 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
}
}
readonly property var colorHash: ListModel {
ListElement { colorId: 13; segmentLength: 5 }
@ -202,6 +215,8 @@ SplitView {
colorId: index
colorHash: d.colorHash
}
album: model.contentType === StatusMessage.ContentType.Image ? d.exampleAlbum : []
albumCount: model.contentType === StatusMessage.ContentType.Image ? d.exampleAlbum.length : 0
}
replyDetails {
@ -222,6 +237,7 @@ SplitView {
onReplyMessageClicked: logs.logEvent("StatusMessage::replyMessageClicked")
onResendClicked: logs.logEvent("StatusMessage::resendClicked")
onLinkActivated: logs.logEvent("StatusMessage::linkActivated" + link)
onImageClicked: logs.logEvent("StatusMessage::imageClicked")
}
}
}

View File

@ -35,7 +35,7 @@ Item {
property StatusMessage controlUnderTest: null
TestCase {
name: "TokenSelectorView"
name: "StatusMessage"
when: windowShown
function init() {

View File

@ -0,0 +1,18 @@
import QtQuick 2.15
ListModel {
id: root
ListElement {
symbol: "WBTC"
amount: "0.00017"
address: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240"
chainId: 1 // main
}
ListElement {
symbol: "ETH"
amount: "12345.6789"
address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8881"
chainId: 10 // Opti
}
}

View File

@ -23,6 +23,7 @@ TokensBySymbolModel 1.0 TokensBySymbolModel.qml
CommunitiesModel 1.0 CommunitiesModel.qml
OnRampProvidersModel 1.0 OnRampProvidersModel.qml
SwapTransactionRoutes 1.0 SwapTransactionRoutes.qml
PaymentRequestModel 1.0 PaymentRequestModel.qml
singleton ModelsData 1.0 ModelsData.qml
singleton NetworksModel 1.0 NetworksModel.qml

View File

@ -49,6 +49,7 @@ Control {
property string messageAttachments: ""
property var reactionIcons: []
property var linkPreviewModel
property var paymentRequestModel
property var gifLinks
property string messageId: ""
@ -312,6 +313,7 @@ Control {
anchors.right: parent.right
visible: active
sourceComponent: StatusTextMessage {
objectName: "StatusMessage_textMessage"
messageDetails: root.messageDetails
isEdited: root.isEdited
allowShowMore: !root.isInPinnedPopup
@ -326,6 +328,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
@ -375,7 +378,8 @@ Control {
Layout.preferredHeight: implicitHeight
active: !root.editMode &&
((!!root.linkPreviewModel && root.linkPreviewModel.count > 0)
|| (!!root.gifLinks && root.gifLinks.length > 0))
|| (!!root.gifLinks && root.gifLinks.length > 0)
|| (!!root.paymentRequestModel && root.paymentRequestModel.ModelCount.count > 0))
visible: active
}
Loader {

View File

@ -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

View File

@ -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

View File

@ -200,6 +200,14 @@ Item {
// Call later to make sure activeUsersStore and activeMessagesStore bindings are updated
Qt.callLater(d.restoreInputState, preservedText)
}
function formatBalance(amount, symbol) {
let asset = ModelUtils.getByKey(WalletStore.RootStore.tokensStore.flatTokensModel, "symbol", symbol)
if (!asset)
return "0"
const num = AmountsArithmetic.toNumber(amount, asset.decimals)
return root.rootStore.currencyStore.formatCurrencyAmount(num, symbol, {noSynbol: true})
}
}
EmptyChatPanel {
@ -238,11 +246,13 @@ Item {
utilsStore: root.utilsStore
rootStore: root.rootStore
contactsStore: root.contactsStore
formatBalance: d.formatBalance
emojiPopup: root.emojiPopup
stickersPopup: root.stickersPopup
stickersLoaded: root.stickersLoaded
isBlocked: model.blocked
sendViaPersonalChatEnabled: root.sendViaPersonalChatEnabled
areTestNetworksEnabled: root.areTestNetworksEnabled
onOpenStickerPackPopup: {
root.openStickerPackPopup(stickerPackId)
}
@ -294,6 +304,8 @@ Item {
sharedStore: root.sharedRootStore
linkPreviewModel: !!d.activeChatContentModule ? d.activeChatContentModule.inputAreaModule.linkPreviewModel : null
paymentRequestModel: !!d.activeChatContentModule ? d.activeChatContentModule.inputAreaModule.paymentRequestModel : null
formatBalance: d.formatBalance
urlsList: d.urlsList
askToEnableLinkPreview: {
if(!d.activeChatContentModule || !d.activeChatContentModule.inputAreaModule || !d.activeChatContentModule.inputAreaModule.preservedProperties)
@ -391,6 +403,7 @@ Item {
d.activeChatContentModule.inputAreaModule.setLinkPreviewEnabledForCurrentMessage(false)
}
onDismissLinkPreview: (index) => d.activeChatContentModule.inputAreaModule.removeLinkPreviewData(index)
onRemovePaymentRequestPreview: (index) => d.activeChatContentModule.inputAreaModule.removePaymentRequestPreviewData(index)
}
ChatPermissionQualificationPanel {

View File

@ -38,8 +38,10 @@ ColumnLayout {
property ContactsStore contactsStore
property string chatId
property int chatType: Constants.chatType.unknown
property var formatBalance
readonly property alias chatMessagesLoader: chatMessagesLoader
property bool areTestNetworksEnabled
property var emojiPopup
property var stickersPopup
@ -94,6 +96,7 @@ ColumnLayout {
rootStore: root.rootStore
contactsStore: root.contactsStore
messageStore: root.messageStore
formatBalance: root.formatBalance
emojiPopup: root.emojiPopup
stickersPopup: root.stickersPopup
usersStore: root.usersStore
@ -103,6 +106,7 @@ ColumnLayout {
isChatBlocked: root.isBlocked || !root.isUserAllowedToSendMessage
channelEmoji: !chatContentModule ? "" : (chatContentModule.chatDetails.emoji || "")
sendViaPersonalChatEnabled: root.sendViaPersonalChatEnabled
areTestNetworksEnabled: root.areTestNetworksEnabled
onShowReplyArea: (messageId, senderId) => {
root.showReplyArea(messageId)
}

View File

@ -39,9 +39,11 @@ Item {
property UsersStore usersStore
property ContactsStore contactsStore
property string channelEmoji
property var formatBalance
property var emojiPopup
property var stickersPopup
property bool areTestNetworksEnabled
property string chatId: ""
property bool stickersLoaded: false
@ -283,10 +285,12 @@ Item {
stickersPopup: root.stickersPopup
chatLogView: ListView.view
chatContentModule: root.chatContentModule
formatBalance: root.formatBalance
isChatBlocked: root.isChatBlocked
sendViaPersonalChatEnabled: root.sendViaPersonalChatEnabled
areTestNetworksEnabled: root.areTestNetworksEnabled
chatId: root.chatId
messageId: model.id
@ -326,6 +330,7 @@ Item {
deletedByContactColorHash: model.deletedByContactColorHash
linkPreviewModel: model.linkPreviewModel
links: model.links
paymentRequestModel: model.paymentRequestModel
messageAttachments: model.messageAttachments
transactionParams: model.transactionParameters
hasMention: model.mentioned

View File

@ -708,6 +708,21 @@ Item {
sendModal.open(address)
}
function onPaymentRequestClicked(receiverAddress: string, symbol: string, amount: string, chainId: int) {
if (!!symbol) {
sendModal.preSelectedHoldingID = symbol
sendModal.preSelectedHoldingType = Constants.TokenType.ERC20
}
if (!!amount) {
sendModal.preDefinedRawAmountToSend = amount
}
if (!!chainId) {
sendModal.preSelectedChainId = chainId
}
sendModal.open(receiverAddress)
}
function onSwitchToCommunity(communityId: string) {
appMain.communitiesStore.setActiveCommunity(communityId)
}
@ -1875,6 +1890,7 @@ Item {
property int preSelectedHoldingType: Constants.TokenType.Unknown
property int preSelectedSendType: Constants.SendType.Unknown
property string preDefinedAmountToSend
property string preDefinedRawAmountToSend
property int preSelectedChainId: 0
property bool onlyAssets: false
@ -1903,6 +1919,7 @@ Item {
sendModal.preSelectedAccountAddress = ""
sendModal.preSelectedRecipient = undefined
sendModal.preDefinedAmountToSend = ""
sendModal.preDefinedRawAmountToSend = ""
sendModal.preSelectedChainId = 0
sendModal.stickersPackId = ""
@ -1929,6 +1946,9 @@ Item {
if (sendModal.preDefinedAmountToSend != "") {
item.preDefinedAmountToSend = sendModal.preDefinedAmountToSend
}
if (sendModal.preDefinedRawAmountToSend != "") {
item.preDefinedRawAmountToSend = sendModal.preDefinedRawAmountToSend
}
if (!!sendModal.preSelectedChainId) {
item.preSelectedChainId = sendModal.preSelectedChainId
}

View File

@ -32,15 +32,25 @@ Control {
*/
required property var linkPreviewModel
required property bool showLinkPreviewSettings
/*
Expected roles:
string symbol
string amount
*/
required property var paymentRequestModel
property var formatBalance: null
readonly property alias hoveredUrl: d.hoveredUrl
readonly property bool hasContent: imagePreviewArray.length > 0 || showLinkPreviewSettings || linkPreviewRepeater.count > 0
readonly property bool hasContent: imagePreviewArray.length > 0 || showLinkPreviewSettings || linkPreviewRepeater.count > 0 || paymentRequestRepeater.count > 0
signal imageRemoved(int index)
signal imageClicked(var chatImage)
signal linkReload(string link)
signal linkClicked(string link)
signal removePaymentRequestPreview(int index)
signal enableLinkPreview()
signal enableLinkPreviewForThisMessage()
signal disableLinkPreview()
@ -96,6 +106,21 @@ Control {
onImageRemoved: root.imageRemoved(index)
visible: !!imagePreviewArray && imagePreviewArray.length > 0
}
Repeater {
id: paymentRequestRepeater
model: root.paymentRequestModel
delegate: PaymentRequestMiniCardDelegate {
required property var model
amount: {
if (!root.formatBalance)
return model.amount
return root.formatBalance(model.amount, model.symbol)
}
symbol: model.symbol
onClose: root.removePaymentRequestPreview(model.index)
}
}
Repeater {
id: linkPreviewRepeater
model: d.filteredModel

View File

@ -0,0 +1,112 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import utils 1.0
CalloutCard {
id: root
required property string amount
required property string symbol
readonly property bool containsMouse: mouseArea.hovered || closeButton.hovered
signal close()
implicitWidth:260
implicitHeight: 64
verticalPadding: 15
horizontalPadding: 12
borderColor: Theme.palette.directColor7
backgroundColor: root.containsMouse ? Theme.palette.directColor7 : Theme.palette.background
contentItem: Item {
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
RowLayout {
id: layout
anchors.fill: parent
spacing: 16
StatusRoundIcon {
id: favIcon
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.preferredWidth: 36
Layout.preferredHeight: 36
asset.width: 24
asset.height: 24
asset.bgColor: Theme.palette.directColor7
asset.bgHeight: 36
asset.bgWidth: 36
asset.color: Theme.palette.primaryColor1
asset.name: Theme.svg("send")
StatusSmartIdenticon {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.right
asset.width: 16
asset.height: 16
asset.bgColor: root.containsMouse ? Theme.palette.transparent : Theme.palette.background
asset.bgHeight: 20
asset.bgWidth: 20
asset.isImage: true
asset.name: Constants.tokenIcon(root.symbol)
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
StatusBaseText {
Layout.fillWidth: true
Layout.fillHeight: true
text: qsTr("Payment request")
font.pixelSize: Theme.additionalTextSize
font.weight: Font.Medium
}
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
StatusBaseText {
Layout.maximumWidth: parent.width * 0.8
Layout.fillHeight: true
font.pixelSize: Theme.tertiaryTextFontSize
color: Theme.palette.baseColor1
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
text: root.amount
}
StatusBaseText {
Layout.fillHeight: true
font.pixelSize: Theme.tertiaryTextFontSize
color: Theme.palette.baseColor1
verticalAlignment: Text.AlignVCenter
text: root.symbol
}
}
}
StatusFlatButton {
id: closeButton
icon.name: "close"
size: StatusBaseButton.Size.Small
hoverColor: Theme.palette.directColor8
textColor: Theme.palette.directColor1
onClicked: root.close()
}
}
}
HoverHandler {
id: mouseArea
target: background
cursorShape: Qt.PointingHandCursor
}
}

View File

@ -10,6 +10,7 @@ LinkPreviewCard 1.0 LinkPreviewCard.qml
LinkPreviewMiniCard 1.0 LinkPreviewMiniCard.qml
LinkPreviewSettingsCard 1.0 LinkPreviewSettingsCard.qml
LinkPreviewSettingsCardMenu 1.0 LinkPreviewSettingsCardMenu.qml
PaymentRequestMiniCardDelegate 1.0 PaymentRequestMiniCardDelegate.qml
MessageMouseArea 1.0 MessageMouseArea.qml
MessageReactionsRow 1.0 MessageReactionsRow.qml
ProfileHeader 1.0 ProfileHeader.qml

View File

@ -0,0 +1,155 @@
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 StatusQ.Controls 0.1
import shared.controls.chat 1.0
import utils 1.0
CalloutCard {
id: root
required property string amount
required property string symbol
required property string address
required property bool areTestNetworksEnabled
property string senderName
property string senderThumbnailImage
property int senderColorId
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
readonly property bool highlight: (root.highlight || root.hovered) && isAvailable
readonly property bool isAvailable: !root.areTestNetworksEnabled
}
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.width: symbolImage.width
asset.height: symbolImage.height
asset.isImage: !!root.senderThumbnailImage
asset.name: root.senderThumbnailImage
asset.isLetterIdenticon: root.senderThumbnailImage === ""
asset.color: Theme.palette.userCustomizationColors[root.senderColorId]
asset.charactersLen: 2
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)
}
}
StatusToolTip {
text: qsTr("Not available in the testnet mode")
visible: !d.isAvailable && root.hovered
y: -height
}
MouseArea {
id: ma
anchors.fill: root
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (!d.isAvailable)
return
root.clicked(mouse)
}
}
}

View File

@ -2,4 +2,5 @@ ContactListItemDelegate 1.0 ContactListItemDelegate.qml
LinkPreviewCardDelegate 1.0 LinkPreviewCardDelegate.qml
LinkPreviewGifDelegate 1.0 LinkPreviewGifDelegate.qml
LinkPreviewMiniCardDelegate 1.0 LinkPreviewMiniCardDelegate.qml
PaymentRequestCardDelegate 1.0 PaymentRequestCardDelegate.qml
InfoCard 1.0 InfoCard.qml

View File

@ -41,6 +41,7 @@ StatusDialog {
property alias preSelectedRecipientType: recipientInputLoader.selectedRecipientType
property string preDefinedAmountToSend
property string preDefinedRawAmountToSend
property int preSelectedChainId: 0
property string stickersPackId
@ -99,8 +100,8 @@ StatusDialog {
return Constants.NoError
}
readonly property double maxFiatBalance: isSelectedHoldingValidAsset ? selectedHolding.currencyBalance : 0
readonly property double maxCryptoBalance: isSelectedHoldingValidAsset ? selectedHolding.currentBalance : 0
readonly property double maxFiatBalance: isSelectedHoldingValidAsset && !!selectedHolding.currencyBalance ? selectedHolding.currencyBalance : 0
readonly property double maxCryptoBalance: isSelectedHoldingValidAsset && !!selectedHolding.currencyBalance ? selectedHolding.currentBalance : 0
readonly property double maxInputBalance: amountToSend.fiatMode ? maxFiatBalance : maxCryptoBalance
readonly property string tokenSymbol: !!d.selectedHolding && !!d.selectedHolding.symbol ? d.selectedHolding.symbol: ""
@ -234,13 +235,24 @@ StatusDialog {
if (popup.preSelectedHoldingType === Constants.TokenType.Native
|| popup.preSelectedHoldingType === Constants.TokenType.ERC20) {
const entry = SQUtils.ModelUtils.getByKey(
let iconSource = ""
let entry = SQUtils.ModelUtils.getByKey(
assetsAdaptor.outputAssetsModel, "tokensKey",
popup.preSelectedHoldingID)
if (entry) {
iconSource = entry.iconSource
} else {
entry = SQUtils.ModelUtils.getByKey(
popup.store.walletAssetStore.renamedTokensBySymbolModel, "tokensKey",
popup.preSelectedHoldingID)
iconSource = Constants.tokenIcon(entry.symbol)
}
d.selectedHoldingType = Constants.TokenType.ERC20
d.selectedHolding = entry
holdingSelector.setSelection(entry.symbol, entry.iconSource,
holdingSelector.setSelection(entry.symbol, iconSource,
popup.preSelectedHoldingID)
holdingSelector.selectedItem = entry
} else {
@ -260,6 +272,7 @@ StatusDialog {
holdingSelector.currentTab = TokenSelectorPanel.Tabs.Collectibles
}
}
if(!!popup.preDefinedAmountToSend) {
// TODO: At this stage the number should not be localized. However
// in many places when initializing popup the number is provided
@ -267,9 +280,12 @@ StatusDialog {
// number consistently. Only the displaying component should apply
// final localized formatting.
const delocalized = popup.preDefinedAmountToSend.replace(LocaleUtils.userInputLocale.decimalPoint, ".")
amountToSend.setValue(delocalized)
}
if (!!popup.preDefinedRawAmountToSend) {
amountToSend.setRawValue(popup.preDefinedRawAmountToSend)
}
if (!!popup.preSelectedChainId) {
popup.preDefinedAmountToSend = popup.preDefinedAmountToSend.replace(Qt.locale().decimalPoint, '.')

View File

@ -107,6 +107,22 @@ Control {
textField.text = d.localize(trimmed)
}
function setRawValue(valueString) {
if (!valueString)
valueString = "0"
if (d.fiatMode) {
setValue(valueString)
return
}
const divisor = SQUtils.AmountsArithmetic.fromExponent(root.multiplierIndex)
const stringNumber = SQUtils.AmountsArithmetic.div(SQUtils.AmountsArithmetic.fromString(valueString), divisor).toFixed(root.multiplierIndex)
const trimmed = d.removeDecimalTrailingZeros(stringNumber)
textField.text = d.localize(trimmed)
}
function clear() {
textField.clear()
}

View File

@ -37,6 +37,7 @@ Rectangle {
signal disableLinkPreview()
signal dismissLinkPreviewSettings()
signal dismissLinkPreview(int index)
signal removePaymentRequestPreview(int index)
property var usersModel
property SharedStores.RootStore sharedStore
@ -67,6 +68,9 @@ Rectangle {
property var fileUrlsAndSources: []
property var linkPreviewModel: null
property var paymentRequestModel: null
property var formatBalance: null
property var urlsList: []
@ -1224,6 +1228,8 @@ Rectangle {
topPadding: 12
imagePreviewArray: control.fileUrlsAndSources
linkPreviewModel: control.linkPreviewModel
paymentRequestModel: control.paymentRequestModel
formatBalance: control.formatBalance
showLinkPreviewSettings: control.askToEnableLinkPreview
onImageRemoved: (index) => {
//Just do a copy and replace the whole thing because it's a plain JS array and thre's no signal when a single item is removed
@ -1242,6 +1248,7 @@ Rectangle {
onDisableLinkPreview: () => control.disableLinkPreview()
onDismissLinkPreviewSettings: () => control.dismissLinkPreviewSettings()
onDismissLinkPreview: (index) => control.dismissLinkPreview(index)
onRemovePaymentRequestPreview: (index) => control.removePaymentRequestPreview(index)
}
RowLayout {

View File

@ -6,6 +6,7 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Utils 0.1 as SQUtils
import shared.controls 1.0
import shared.panels 1.0
@ -25,15 +26,26 @@ Flow {
required property var linkPreviewModel
required property var gifLinks
required property var paymentRequestModel
required property bool gifUnfurlingEnabled
required property bool canAskToUnfurlGifs
required property bool areTestNetworksEnabled
property var formatBalance: null
property string senderName
property string senderThumbnailImage
property int senderColorId
readonly property alias hoveredLink: linksRepeater.hoveredUrl
property string highlightLink: ""
signal imageClicked(var image, var mouse, string imageSource, string url)
signal openContextMenu(var item, string url, string domain)
signal setNeverAskAboutUnfurlingAgain(bool neverAskAgain)
signal paymentRequestClicked(int index)
function resetLocalAskAboutUnfurling() {
d.localAskAboutUnfurling = true
@ -56,9 +68,30 @@ Flow {
sourceComponent: enableLinkComponent
}
Repeater {
id: paymentRequestRepeater
model: root.paymentRequestModel
delegate: PaymentRequestCardDelegate {
required property var model
objectName: "PaymentRequestDelegate_" + model.index
areTestNetworksEnabled: root.areTestNetworksEnabled
amount: {
if (!root.formatBalance)
return model.amount
return root.formatBalance(model.amount, model.symbol)
}
symbol: model.symbol
address: model.receiver
senderName: root.senderName
senderThumbnailImage: root.senderThumbnailImage
senderColorId: root.senderColorId
onClicked: root.paymentRequestClicked(model.index)
}
}
Repeater {
id: tempRepeater
visible: root.canAskToUnfurlGifs
visible: root.cankToUnfurlGifs
model: root.gifUnfurlingEnabled ? gifLinks : []
delegate: LinkPreviewGifDelegate {

View File

@ -70,9 +70,11 @@ Loader {
property string messagePinnedBy: ""
property var reactionsModel: []
property var linkPreviewModel
property var paymentRequestModel
property string messageAttachments: ""
property var transactionParams
property var emojiReactionsModel
property var formatBalance
// These 2 properties can be dropped when the new unfurling flow supports GIFs
property var links
@ -137,6 +139,8 @@ Loader {
property bool sendViaPersonalChatEnabled
property bool areTestNetworksEnabled
property bool stickersLoaded: false
property string sticker
property int stickerPack: -1
@ -720,6 +724,7 @@ Loader {
resendError: root.resendError
reactionsModel: root.reactionsModel
linkPreviewModel: root.linkPreviewModel
paymentRequestModel: root.paymentRequestModel
gifLinks: root.gifLinks
showHeader: root.shouldRepeatHeader || dateGroupLabel.visible || isAReply ||
@ -973,9 +978,15 @@ Loader {
linkPreviewModel: root.linkPreviewModel
gifLinks: root.gifLinks
senderName: root.senderDisplayName
senderThumbnailImage: root.senderIcon || ""
senderColorId: Utils.colorIdForPubkey(root.senderId)
paymentRequestModel: root.paymentRequestModel
playAnimations: root.Window.active && root.messageStore.isChatActive
isOnline: root.rootStore.mainModuleInst.isOnline
highlightLink: delegate.hoveredLink
areTestNetworksEnabled: root.areTestNetworksEnabled
formatBalance: root.formatBalance
onImageClicked: (image, mouse, imageSource, url) => {
d.onImageClicked(image, mouse, imageSource, url)
}
@ -986,6 +997,10 @@ Loader {
gifUnfurlingEnabled: root.sharedRootStore.gifUnfurlingEnabled
canAskToUnfurlGifs: !root.sharedRootStore.neverAskAboutUnfurlingAgain
onSetNeverAskAboutUnfurlingAgain: root.sharedRootStore.setNeverAskAboutUnfurlingAgain(neverAskAgain)
onPaymentRequestClicked: (index) => {
const request = StatusQUtils.ModelUtils.get(paymentRequestModel, index)
Global.paymentRequestClicked(request.receiver, request.symbol, request.amount, request.chainId)
}
Component.onCompleted: {
root.messageStore.messageModule.forceLinkPreviewsLocalData(root.messageId)

View File

@ -70,6 +70,7 @@ QtObject {
signal appSectionBySectionTypeChanged(int sectionType, int subsection, int subSubsection, var data)
signal openSendModal(string address)
signal paymentRequestClicked(string receiverAddress, string symbol, string amount, int chainId)
signal switchToCommunity(string communityId)
signal switchToCommunitySettings(string communityId)
signal switchToCommunityChannelsView(string communityId)