feat(@desktop/wallet): Implementation of One Time & Recurrent tab in Buy Popup
fixes #14819
This commit is contained in:
parent
f62b6eb348
commit
c9641bb0b9
|
@ -0,0 +1,37 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import Storybook 1.0
|
||||
import Models 1.0
|
||||
|
||||
import AppLayouts.Wallet.popups 1.0
|
||||
|
||||
SplitView {
|
||||
id: root
|
||||
|
||||
orientation: Qt.Horizontal
|
||||
|
||||
PopupBackground {
|
||||
id: popupBg
|
||||
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
Button {
|
||||
id: reopenButton
|
||||
anchors.centerIn: parent
|
||||
text: "Reopen"
|
||||
enabled: !buySellModal.visible
|
||||
|
||||
onClicked: buySellModal.open()
|
||||
}
|
||||
|
||||
BuyCryptoModal {
|
||||
id: buySellModal
|
||||
visible: true
|
||||
onRampProvidersModel: OnRampProvidersModel{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// category: Popups
|
|
@ -0,0 +1,146 @@
|
|||
import QtQuick 2.15
|
||||
import QtTest 1.15
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import Models 1.0
|
||||
import utils 1.0
|
||||
|
||||
import AppLayouts.Wallet.popups 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: 600
|
||||
height: 800
|
||||
|
||||
OnRampProvidersModel{
|
||||
id: onRampProvidersModal
|
||||
}
|
||||
|
||||
Component {
|
||||
id: componentUnderTest
|
||||
BuyCryptoModal {
|
||||
onRampProvidersModel: onRampProvidersModal
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
SignalSpy {
|
||||
id: notificationSpy
|
||||
target: Global
|
||||
signalName: "openLinkWithConfirmation"
|
||||
}
|
||||
|
||||
TestCase {
|
||||
name: "BuyCryptoModal"
|
||||
when: windowShown
|
||||
|
||||
property BuyCryptoModal controlUnderTest: null
|
||||
|
||||
function init() {
|
||||
controlUnderTest = createTemporaryObject(componentUnderTest, root)
|
||||
}
|
||||
|
||||
function launchPopup() {
|
||||
verify(!!controlUnderTest)
|
||||
controlUnderTest.open()
|
||||
verify(!!controlUnderTest.opened)
|
||||
}
|
||||
|
||||
function test_launchAndCloseModal() {
|
||||
launchPopup()
|
||||
|
||||
// close popup
|
||||
controlUnderTest.close()
|
||||
verify(!controlUnderTest.opened)
|
||||
}
|
||||
|
||||
function test_ModalFooter() {
|
||||
// Launch modal
|
||||
launchPopup()
|
||||
|
||||
// check if footer has Done button and action on button clicked
|
||||
const footer = findChild(controlUnderTest, "footer")
|
||||
verify(!!footer)
|
||||
compare(footer.rightButtons.count, 1)
|
||||
compare(footer.rightButtons.get(0).text, qsTr("Done"))
|
||||
mouseClick(footer.rightButtons.get(0), Qt.LeftButton)
|
||||
|
||||
// popup should be closed
|
||||
verify(!controlUnderTest.opened)
|
||||
}
|
||||
|
||||
function test_modalContent() {
|
||||
// Launch modal
|
||||
launchPopup()
|
||||
|
||||
// find tab bar
|
||||
const tabBar = findChild(controlUnderTest, "tabBar")
|
||||
verify(!!tabBar)
|
||||
|
||||
// should have 2 items
|
||||
compare(tabBar.count, 2)
|
||||
|
||||
// current index set should be to 0
|
||||
compare(tabBar.currentIndex, 0)
|
||||
|
||||
// item 0 should have text "One time"
|
||||
compare(tabBar.itemAt(0).text, qsTr("One time"))
|
||||
|
||||
// item 1 should have text "Recurrent"
|
||||
compare(tabBar.itemAt(1).text, qsTr("Recurrent"))
|
||||
|
||||
// TODO: this will be implemnted under https://github.com/status-im/status-desktop/issues/14820
|
||||
// until then this list will be empty
|
||||
mouseClick(tabBar.itemAt(1), Qt.LeftButton)
|
||||
compare(tabBar.currentIndex, 1)
|
||||
|
||||
const providersList = findChild(controlUnderTest, "providersList")
|
||||
waitForRendering(providersList)
|
||||
verify(!!providersList)
|
||||
compare(providersList.count, 0)
|
||||
|
||||
// check data on 1st tab --------------------------------------------------------
|
||||
mouseClick(tabBar.itemAt(0), Qt.LeftButton)
|
||||
compare(tabBar.currentIndex, 0)
|
||||
|
||||
waitForRendering(providersList)
|
||||
verify(!!providersList)
|
||||
|
||||
// verify that 3 items are listed
|
||||
compare(providersList.count, 3)
|
||||
|
||||
// check if delegate contents are as expected
|
||||
for(let i =0; i< providersList.count; i++) {
|
||||
let delegateUnderTest = providersList.itemAtIndex(i)
|
||||
verify(!!delegateUnderTest)
|
||||
|
||||
compare(delegateUnderTest.title, onRampProvidersModal.get(i).name)
|
||||
compare(delegateUnderTest.subTitle, onRampProvidersModal.get(i).description)
|
||||
compare(delegateUnderTest.asset.name, onRampProvidersModal.get(i).logoUrl)
|
||||
|
||||
const feesText = findChild(delegateUnderTest, "feesText")
|
||||
verify(!!feesText)
|
||||
compare(feesText.text, onRampProvidersModal.get(i).fees)
|
||||
|
||||
const externalLinkIcon = findChild(delegateUnderTest, "externalLinkIcon")
|
||||
verify(!!externalLinkIcon)
|
||||
compare(externalLinkIcon.icon, "tiny/external")
|
||||
compare(externalLinkIcon.color, Theme.palette.baseColor1)
|
||||
|
||||
// Hover over the item and check hovered state
|
||||
mouseMove(delegateUnderTest, delegateUnderTest.width/2, delegateUnderTest.height/2)
|
||||
verify(delegateUnderTest.sensor.containsMouse)
|
||||
compare(externalLinkIcon.color, Theme.palette.directColor1)
|
||||
verify(delegateUnderTest.color, Theme.palette.baseColor2)
|
||||
}
|
||||
|
||||
// test mouse click
|
||||
tryCompare(notificationSpy, "count", 0)
|
||||
mouseClick(providersList.itemAtIndex(0))
|
||||
tryCompare(notificationSpy, "count", 1)
|
||||
compare(notificationSpy.signalArguments[0][0],onRampProvidersModal.get(0).siteUrl)
|
||||
compare(notificationSpy.signalArguments[0][1],onRampProvidersModal.get(0).hostname)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -82,4 +82,10 @@ QtObject {
|
|||
readonly property string ownerTokenInfo: "In order to Mint, Import and Airdrop community tokens, you first need to mint your Owner token which will give you permissions to access the token management features for your community."
|
||||
readonly property string airdropInfo: "You can Airdrop tokens to deserving Community members or to give individuals token-based permissions."
|
||||
}
|
||||
|
||||
readonly property QtObject onRampProviderImages: QtObject {
|
||||
readonly property string latamex: Style.png("onRampProviders/latamex")
|
||||
readonly property string moonPay: Style.png("onRampProviders/moonPay")
|
||||
readonly property string ramp: Style.png("onRampProviders/ramp")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
ListModel {
|
||||
readonly property var data: [
|
||||
{
|
||||
name: "Ramp",
|
||||
description: "Global crypto to fiat flow",
|
||||
fees: "0.49% - 2.9%",
|
||||
logoUrl: ModelsData.onRampProviderImages.ramp,
|
||||
siteUrl: "https://ramp.network/buy?hostApiKey=zrtf9u2uqebeyzcs37fu5857tktr3eg9w5tffove&swapAsset=DAI,ETH,USDC,USDT",
|
||||
hostname: "ramp.network",
|
||||
recurrentSiteURL: ""
|
||||
},
|
||||
{
|
||||
name: "MoonPay",
|
||||
description: "The new standard for fiat to crypto",
|
||||
fees: "1% - 4.5%",
|
||||
logoUrl: ModelsData.onRampProviderImages.moonPay,
|
||||
siteUrl: "https://buy.moonpay.com/?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR",
|
||||
hostname: "moonpay.com",
|
||||
recurrentSiteURL: "https://buy.moonpay.com/?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR",
|
||||
},
|
||||
{
|
||||
name: "Latamex",
|
||||
description: "Easily buy crypto in Argentina, Mexico, and Brazil",
|
||||
fees: "1% - 1.7%",
|
||||
logoUrl: ModelsData.onRampProviderImages.latamex,
|
||||
siteUrl: "https://latamex.com/",
|
||||
hostname: "latamex.com",
|
||||
recurrentSiteURL: "",
|
||||
}
|
||||
]
|
||||
|
||||
Component.onCompleted: append(data)
|
||||
}
|
|
@ -22,6 +22,7 @@ WalletTransactionsModel 1.0 WalletTransactionsModel.qml
|
|||
GroupedAccountsAssetsModel 1.0 GroupedAccountsAssetsModel.qml
|
||||
TokensBySymbolModel 1.0 TokensBySymbolModel.qml
|
||||
CommunitiesModel 1.0 CommunitiesModel.qml
|
||||
OnRampProvidersModel 1.0 OnRampProvidersModel.qml
|
||||
|
||||
singleton ModelsData 1.0 ModelsData.qml
|
||||
singleton NetworksModel 1.0 NetworksModel.qml
|
||||
|
|
|
@ -81,9 +81,7 @@ Rectangle {
|
|||
visible: !root.isCommunityOwnershipTransfer && !root.walletStore.showAllAccounts
|
||||
icon.name: "token"
|
||||
text: qsTr("Buy")
|
||||
onClicked: function () {
|
||||
Global.openPopup(buySellModal);
|
||||
}
|
||||
onClicked: Global.openBuyCryptoModalRequested()
|
||||
}
|
||||
|
||||
StatusFlatButton {
|
||||
|
@ -97,11 +95,6 @@ Rectangle {
|
|||
onClicked: root.launchSwapModal()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: buySellModal
|
||||
CryptoServicesModal {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQml.Models 2.14
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
StatusDialog {
|
||||
id: root
|
||||
|
||||
required property var onRampProvidersModel
|
||||
|
||||
padding: Style.current.xlPadding
|
||||
implicitWidth: 560
|
||||
implicitHeight: 436
|
||||
title: qsTr("Buy assets")
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 20
|
||||
|
||||
StatusSwitchTabBar {
|
||||
id: tabBar
|
||||
objectName: "tabBar"
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
StatusSwitchTabButton {
|
||||
text: qsTr("One time")
|
||||
}
|
||||
StatusSwitchTabButton {
|
||||
text: qsTr("Recurrent")
|
||||
}
|
||||
}
|
||||
|
||||
StatusListView {
|
||||
id: providersList
|
||||
objectName: "providersList"
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: !!root.onRampProvidersModel ? root.onRampProvidersModel : null
|
||||
// TODO: this temporary and changed under https://github.com/status-im/status-desktop/issues/14820
|
||||
// when recurrentSiteURL is available
|
||||
filters: ValueFilter {
|
||||
enabled: tabBar.currentIndex
|
||||
roleName: "name"
|
||||
value: ""
|
||||
}
|
||||
}
|
||||
delegate: StatusListItem {
|
||||
width: ListView.view.width
|
||||
title: name
|
||||
subTitle: description
|
||||
asset.name: logoUrl
|
||||
asset.isImage: true
|
||||
statusListItemSubTitle.maximumLineCount: 1
|
||||
statusListItemComponentsSlot.spacing: 8
|
||||
components: [
|
||||
StatusBaseText {
|
||||
objectName: "feesText"
|
||||
text: fees
|
||||
color: Theme.palette.baseColor1
|
||||
lineHeight: 24
|
||||
lineHeightMode: Text.FixedHeight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
},
|
||||
StatusIcon {
|
||||
objectName: "externalLinkIcon"
|
||||
icon: "tiny/external"
|
||||
color: sensor.containsMouse ? Theme.palette.directColor1: Theme.palette.baseColor1
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
let url = tabBar.currentIndex ? recurrentSiteURL : siteUrl
|
||||
Global.openLinkWithConfirmation(url, hostname)
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: StatusDialogFooter {
|
||||
objectName: "footer"
|
||||
rightButtons: ObjectModel {
|
||||
StatusButton {
|
||||
text: qsTr("Done")
|
||||
onClicked: root.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
|
||||
import utils 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import StatusQ.Popups 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core 0.1
|
||||
|
||||
import "../controls"
|
||||
import "../stores"
|
||||
|
||||
StatusModal {
|
||||
id: cryptoServicesPopupRoot
|
||||
|
||||
height: 400
|
||||
headerSettings.title: qsTr("Buy crypto")
|
||||
anchors.centerIn: parent
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
anchors.fill: parent
|
||||
sourceComponent: servicesComponent
|
||||
|
||||
Component {
|
||||
id: servicesComponent
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: Style.current.padding
|
||||
anchors.bottomMargin: Style.current.padding
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
StyledText {
|
||||
id: note
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Style.current.secondaryText
|
||||
text: qsTr("Choose a service you'd like to use to buy crypto")
|
||||
}
|
||||
|
||||
StatusListView {
|
||||
anchors.top: note.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.topMargin: Style.current.padding
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 394
|
||||
model: RootStore.cryptoRampServicesModel
|
||||
focus: true
|
||||
spacing: Style.current.padding
|
||||
|
||||
delegate: StatusListItem {
|
||||
width: parent.width
|
||||
title: name
|
||||
subTitle: description
|
||||
asset.name: logoUrl
|
||||
asset.isImage: true
|
||||
label: fees
|
||||
statusListItemSubTitle.maximumLineCount: 1
|
||||
components: [
|
||||
StatusIcon {
|
||||
icon: "next"
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
Global.openLink(siteUrl);
|
||||
cryptoServicesPopupRoot.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,3 +6,4 @@ ReceiveModal 1.0 ReceiveModal.qml
|
|||
AddEditSavedAddressPopup 1.0 AddEditSavedAddressPopup.qml
|
||||
RemoveSavedAddressPopup 1.0 RemoveSavedAddressPopup.qml
|
||||
SavedAddressActivityPopup 1.0 SavedAddressActivityPopup.qml
|
||||
BuyCryptoModal 1.0 BuyCryptoModal.qml
|
||||
|
|
|
@ -16,6 +16,7 @@ import AppLayouts.Profile.popups 1.0
|
|||
import AppLayouts.Communities.popups 1.0
|
||||
import AppLayouts.Communities.helpers 1.0
|
||||
import AppLayouts.Wallet.popups.swap 1.0
|
||||
import AppLayouts.Wallet.popups 1.0
|
||||
|
||||
import AppLayouts.Wallet.stores 1.0 as WalletStore
|
||||
import AppLayouts.Chat.stores 1.0 as ChatStore
|
||||
|
@ -91,6 +92,7 @@ QtObject {
|
|||
Global.openConfirmHideCollectiblePopup.connect(openConfirmHideCollectiblePopup)
|
||||
Global.openCommunityMemberMessagesPopupRequested.connect(openCommunityMemberMessagesPopup)
|
||||
Global.openSwapModalRequested.connect(openSwapModal)
|
||||
Global.openBuyCryptoModalRequested.connect(openBuyCryptoModal)
|
||||
}
|
||||
|
||||
property var currentPopup
|
||||
|
@ -390,6 +392,10 @@ QtObject {
|
|||
openPopup(swapModal, {swapInputParamsForm: parameters})
|
||||
}
|
||||
|
||||
function openBuyCryptoModal() {
|
||||
openPopup(buyCryptoModal)
|
||||
}
|
||||
|
||||
readonly property list<Component> _components: [
|
||||
Component {
|
||||
id: removeContactConfirmationDialog
|
||||
|
@ -1248,6 +1254,13 @@ QtObject {
|
|||
}
|
||||
onClosed: destroy()
|
||||
}
|
||||
},
|
||||
Component {
|
||||
id: buyCryptoModal
|
||||
BuyCryptoModal {
|
||||
onRampProvidersModel: WalletStore.RootStore.cryptoRampServicesModel
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -107,6 +107,9 @@ QtObject {
|
|||
// Swap
|
||||
signal openSwapModalRequested(var formDataParams)
|
||||
|
||||
// BuyCrypto
|
||||
signal openBuyCryptoModalRequested()
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// WalletConnect POC - to remove
|
||||
signal popupWalletConnect()
|
||||
|
|
Loading…
Reference in New Issue