feat(@desktop/wallet): Swap modal launch flows

fixes #14628
This commit is contained in:
Khushboo Mehta 2024-05-13 19:23:01 +02:00 committed by Khushboo-dev-cpp
parent 02a17b67ca
commit 81d7ca32b0
12 changed files with 280 additions and 17 deletions

View File

@ -0,0 +1,132 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Controls 0.1
import utils 1.0
import Storybook 1.0
import Models 1.0
import AppLayouts.Wallet.stores 1.0
import AppLayouts.Wallet.popups.swap 1.0
SplitView {
id: root
Logs { id: logs }
orientation: Qt.Horizontal
QtObject {
id: d
readonly property var tokenBySymbolModel: TokensBySymbolModel {}
}
PopupBackground {
id: popupBg
property var popupIntance: null
SplitView.fillWidth: true
SplitView.fillHeight: true
Button {
id: reopenButton
anchors.centerIn: parent
text: "Reopen"
enabled: !swapModal.visible
onClicked: swapModal.open()
}
SwapModal {
id: swapModal
visible: true
formData: SwapFormData {
selectedAccountIndex: accountComboBox.currentIndex
selectedNetworkChainId: {
if (NetworksModel.flatNetworks.count > 0) {
return ModelUtils.get(NetworksModel.flatNetworks, networksComboBox.currentIndex).chainId
}
return -1
}
fromTokensKey: {
if (d.tokenBySymbolModel.count > 0) {
return ModelUtils.get(d.tokenBySymbolModel, fromTokenComboBox.currentIndex).key
}
return ""
}
fromTokenAmount: swapInput.text
toTokenKey: {
if (d.tokenBySymbolModel.count > 0) {
return ModelUtils.get(d.tokenBySymbolModel, toTokenComboBox.currentIndex).key
}
return ""
}
}
}
}
Pane {
id: rightPanel
SplitView.minimumWidth: 300
SplitView.preferredWidth: 300
SplitView.minimumHeight: 300
ColumnLayout {
spacing: 10
StatusBaseText {
text:"Selected Account"
}
ComboBox {
id: accountComboBox
textRole: "name"
model: WalletSendAccountsModel {}
currentIndex: 0
}
StatusBaseText {
text: "Selected Network"
}
ComboBox {
id: networksComboBox
textRole: "chainName"
model: NetworksModel.flatNetworks
currentIndex: 0
}
StatusBaseText {
text: "From Token"
}
ComboBox {
id: fromTokenComboBox
textRole: "name"
model: d.tokenBySymbolModel
currentIndex: 0
}
StatusInput {
id: swapInput
Layout.preferredWidth: 100
label: "Token mount to swap"
text: "100"
}
StatusBaseText {
text: "To Token"
}
ComboBox {
id: toTokenComboBox
textRole: "name"
model: d.tokenBySymbolModel
currentIndex: 1
}
}
}
}
// category: Popups

View File

@ -14,6 +14,7 @@ import "panels"
import "views"
import "stores"
import "controls"
import "popups/swap"
Item {
id: root
@ -134,6 +135,15 @@ Item {
RootStore.backButtonName = ""
}
property SwapFormData swapFormData: SwapFormData {
selectedAccountIndex: RootStore.showAllAccounts ? 0 : leftTab.currentAccountIndex
selectedNetworkChainId: {
// Without this when we switch testnet mode, the correct network is not evaluated
RootStore.areTestNetworksEnabled
return StatusQUtils.ModelUtils.get(RootStore.filteredFlatModel, 0).chainId
}
}
function displayAllAddresses() {
RootStore.showSavedAddresses = false
RootStore.selectedAddress = ""
@ -203,6 +213,10 @@ Item {
changingPreferredChainsEnabled: true,
hasFloatingButtons: true
})
onLaunchSwapModal: {
d.swapFormData.fromTokensKey = tokensKey
Global.openSwapModalRequested(d.swapFormData)
}
}
}
@ -261,9 +275,9 @@ Item {
readonly property bool isCommunityCollectible: !!walletStore.currentViewedCollectible ? walletStore.currentViewedCollectible.communityId !== "" : false
readonly property bool isOwnerCommunityCollectible: isCommunityCollectible ? (walletStore.currentViewedCollectible.communityPrivilegesLevel === Constants.TokenPrivilegesLevel.Owner) : false
visible: !RootStore.showAllAccounts
visible: !RootStore.showAllAccounts || Global.featureFlags.swapEnabled
width: parent.width
height: RootStore.showAllAccounts ? implicitHeight : 61
height: visible ? 61: implicitHeight
walletStore: RootStore
networkConnectionStore: root.networkConnectionStore
isCommunityOwnershipTransfer: footer.isHoldingSelected && footer.isOwnerCommunityCollectible
@ -314,6 +328,13 @@ Item {
root.sendModalPopup.onlyAssets = true
root.sendModalPopup.open()
}
onLaunchSwapModal: {
d.swapFormData.fromTokensKey = ""
if(!!walletStore.currentViewedHoldingTokensKey && walletStore.currentViewedHoldingType === Constants.TokenType.ERC20) {
d.swapFormData.fromTokensKey = walletStore.currentViewedHoldingTokensKey
}
Global.openSwapModalRequested(d.swapFormData)
}
}
}

View File

@ -25,13 +25,16 @@ Rectangle {
signal launchShareAddressModal()
signal launchSendModal()
signal launchBridgeModal()
signal launchSwapModal()
color: Theme.palette.statusAppLayout.rightPanelBackgroundColor
QtObject {
id: d
readonly property bool isCollectibleViewed: !!walletStore.currentViewedCollectible
readonly property bool isCollectibleSoulbound: d.isCollectibleViewed && walletStore.currentViewedCollectible.soulbound
readonly property bool isCollectibleViewed: !!walletStore.currentViewedHoldingID &&
(walletStore.currentViewedHoldingType === Constants.TokenType.ERC721 ||
walletStore.currentViewedHoldingType === Constants.TokenType.ERC1155)
readonly property bool isCollectibleSoulbound: isCollectibleViewed && !!walletStore.currentViewedCollectible && walletStore.currentViewedCollectible.soulbound
}
StatusModalDivider {
@ -51,12 +54,13 @@ Rectangle {
interactive: !d.isCollectibleSoulbound && networkConnectionStore.sendBuyBridgeEnabled
onClicked: root.launchSendModal()
tooltip.text: d.isCollectibleSoulbound ? qsTr("Soulbound collectibles cannot be sent to another wallet") : networkConnectionStore.sendBuyBridgeToolTipText
visible: !walletStore.overview.isWatchOnlyAccount && walletStore.overview.canSend
visible: !walletStore.overview.isWatchOnlyAccount && walletStore.overview.canSend && !root.walletStore.showAllAccounts
}
StatusFlatButton {
icon.name: "receive"
text: qsTr("Receive")
visible: !root.walletStore.showAllAccounts
onClicked: function () {
launchShareAddressModal()
}
@ -65,16 +69,16 @@ Rectangle {
StatusFlatButton {
icon.name: "bridge"
text: qsTr("Bridge")
interactive: networkConnectionStore.sendBuyBridgeEnabled
interactive: !d.isCollectibleSoulbound && networkConnectionStore.sendBuyBridgeEnabled
onClicked: root.launchBridgeModal()
tooltip.text: networkConnectionStore.sendBuyBridgeToolTipText
visible: !walletStore.overview.isWatchOnlyAccount && !root.isCommunityOwnershipTransfer && walletStore.overview.canSend
tooltip.text: d.isCollectibleSoulbound ? qsTr("Soulbound collectibles cannot be bridged to another wallet") : networkConnectionStore.sendBuyBridgeToolTipText
visible: !walletStore.overview.isWatchOnlyAccount && !root.isCommunityOwnershipTransfer && walletStore.overview.canSend && !root.walletStore.showAllAccounts
}
StatusFlatButton {
id: buySellBtn
visible: !root.isCommunityOwnershipTransfer
visible: !root.isCommunityOwnershipTransfer && !root.walletStore.showAllAccounts
icon.name: "token"
text: qsTr("Buy")
onClicked: function () {
@ -85,12 +89,12 @@ Rectangle {
StatusFlatButton {
id: swap
visible: !d.isCollectibleSoulbound && networkConnectionStore.sendBuyBridgeEnabled && Global.featureFlags.swapEnabled
interactive: !d.isCollectibleSoulbound && networkConnectionStore.sendBuyBridgeEnabled
visible: Global.featureFlags.swapEnabled && !walletStore.overview.isWatchOnlyAccount
tooltip.text: d.isCollectibleSoulbound ? qsTr("Soulbound collectibles cannot be swapped") : networkConnectionStore.sendBuyBridgeToolTipText
icon.name: "swap"
text: qsTr("Swap")
onClicked: function () {
console.warn("TODO: launch swap modal...")
}
onClicked: root.launchSwapModal()
}
}

View File

@ -0,0 +1,15 @@
import QtQuick 2.13
import utils 1.0
/* This is used so that there is an easy way to fill in the data
needed to launch the Swap Modal with pre-filled requisites. */
QtObject {
id: root
property int selectedAccountIndex: 0
property int selectedNetworkChainId: -1
property string fromTokensKey: ""
property string fromTokenAmount: ""
property string toTokenKey: ""
}

View File

@ -0,0 +1,55 @@
import QtQuick 2.13
import QtQuick.Layouts 1.15
import utils 1.0
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups.Dialog 0.1
StatusDialog {
id: root
title: qsTr("Swap")
// This should be the only property which should be used when being launched from elsewhere
property SwapFormData formData: SwapFormData {}
bottomPadding: 16
padding: 0
background: StatusDialogBackground {
implicitHeight: 846
implicitWidth: 556
color: Theme.palette.baseColor3
}
contentItem: Column {
spacing: 5
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: "This area is a temporary placeholder"
font.bold: true
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: "Selected account index: %1".arg(formData.selectedAccountIndex)
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: "Selected network: %1".arg(formData.selectedNetworkChainId)
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: "Selected from token: %1".arg(formData.fromTokensKey)
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: "from token amount: %1".arg(formData.fromTokenAmount)
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: "Selected to token: %1".arg(formData.toTokenKey)
}
}
}

View File

@ -0,0 +1,2 @@
SwapModal 1.0 SwapModal.qml
SwapFormData 1.0 SwapFormData.qml

View File

@ -152,20 +152,26 @@ QtObject {
property var cryptoRampServicesModel: walletSectionBuySellCrypto.model
function resetCurrentViewedHolding(type) {
currentViewedHoldingTokensKey = ""
currentViewedHoldingID = ""
currentViewedHoldingType = type
}
function setCurrentViewedHoldingType(type) {
currentViewedHoldingTokensKey = ""
currentViewedHoldingID = ""
currentViewedHoldingType = type
}
function setCurrentViewedHolding(id, type) {
function setCurrentViewedHolding(id, tokensKey, type) {
currentViewedHoldingTokensKey = tokensKey
currentViewedHoldingID = id
currentViewedHoldingType = type
}
property string currentViewedHoldingTokensKey: ""
/* TODO: should get rid if this eventually, we shouldnt be using token symbols
everywhere. Adding a new one currentViewedHoldingTokensKey aboce to not impact send/bridge flows */
property string currentViewedHoldingID: ""
property int currentViewedHoldingType
readonly property var currentViewedCollectible: collectiblesStore.detailedCollectible

View File

@ -27,6 +27,7 @@ Rectangle {
id: root
objectName: "walletLeftTab"
property alias currentAccountIndex: walletAccountsListView.currentIndex
property var networkConnectionStore
property var selectAllAccounts: function(){}
property var changeSelectedAccount: function(){}

View File

@ -22,6 +22,7 @@ RightTabBaseView {
property alias currentTabIndex: walletTabBar.currentIndex
signal launchShareAddressModal()
signal launchSwapModal(string tokensKey)
function resetView() {
resetStack()
@ -152,7 +153,7 @@ RightTabBaseView {
filterVisible: filterButton.checked
onAssetClicked: {
assetDetailView.token = token
RootStore.setCurrentViewedHolding(token.symbol, Constants.TokenType.ERC20)
RootStore.setCurrentViewedHolding(token.symbol, token.tokensKey, Constants.TokenType.ERC20)
stack.currentIndex = 2
}
onSendRequested: (symbol) => {
@ -166,6 +167,7 @@ RightTabBaseView {
onSwitchToCommunityRequested: (communityId) => Global.switchToCommunity(communityId)
onManageTokensRequested: Global.changeAppSectionBySectionType(Constants.appSection.profile, Constants.settingsSubsection.wallet,
Constants.walletSettingsSubsection.manageAssets)
onLaunchSwapModal: root.launchSwapModal(tokensKey)
}
}
Component {
@ -178,7 +180,7 @@ RightTabBaseView {
filterVisible: filterButton.checked
onCollectibleClicked: {
RootStore.collectiblesStore.getDetailedCollectible(chainId, contractAddress, tokenId)
RootStore.setCurrentViewedHolding(uid, tokenType)
RootStore.setCurrentViewedHolding(uid, uid, tokenType)
d.detailedCollectibleActivityController.resetFilter()
d.detailedCollectibleActivityController.setFilterAddressesJson(JSON.stringify(RootStore.addressFilters.split(":")))
d.detailedCollectibleActivityController.setFilterChainsJson(JSON.stringify([chainId]), false)

View File

@ -15,6 +15,7 @@ import AppLayouts.Chat.popups 1.0
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.stores 1.0 as WalletStore
import AppLayouts.Chat.stores 1.0 as ChatStore
@ -89,6 +90,7 @@ QtObject {
Global.openConfirmHideAssetPopup.connect(openConfirmHideAssetPopup)
Global.openConfirmHideCollectiblePopup.connect(openConfirmHideCollectiblePopup)
Global.openCommunityMemberMessagesPopupRequested.connect(openCommunityMemberMessagesPopup)
Global.openSwapModalRequested.connect(openSwapModal)
}
property var currentPopup
@ -384,6 +386,10 @@ QtObject {
})
}
function openSwapModal(parameters) {
openPopup(swapModal, {formData: parameters})
}
readonly property list<Component> _components: [
Component {
id: removeContactConfirmationDialog
@ -1230,6 +1236,12 @@ QtObject {
CommunityMemberMessagesPopup {
onClosed: destroy()
}
},
Component {
id: swapModal
SwapModal {
onClosed: destroy()
}
}
]
}

View File

@ -43,6 +43,7 @@ ColumnLayout {
signal assetClicked(var token)
signal sendRequested(string symbol)
signal receiveRequested(string symbol)
signal launchSwapModal(string tokensKey)
signal switchToCommunityRequested(string communityId)
signal manageTokensRequested()
@ -300,7 +301,8 @@ ColumnLayout {
} else if (mouse.button === Qt.RightButton) {
Global.openMenu(tokenContextMenu, this,
{symbol: modelData.symbol, assetName: modelData.name, assetImage: symbolUrl,
communityId: modelData.communityId, communityName: modelData.communityName, communityImage: modelData.communityImage})
communityId: modelData.communityId, communityName: modelData.communityName,
communityImage: modelData.communityImage, tokensKey: modelData.tokensKey})
}
}
onSwitchToCommunityRequested: root.switchToCommunityRequested(communityId)
@ -318,6 +320,7 @@ ColumnLayout {
StatusMenu {
onClosed: destroy()
property string tokensKey
property string symbol
property string assetName
property string assetImage
@ -337,6 +340,13 @@ ColumnLayout {
text: qsTr("Receive")
onTriggered: root.receiveRequested(symbol)
}
StatusAction {
icon.name: "swap"
text: qsTr("Swap")
enabled: Global.featureFlags.swapEnabled && !root.overview.isWatchOnlyAccount
visibleOnDisabled: Global.featureFlags.swapEnabled
onTriggered: root.launchSwapModal(tokensKey)
}
StatusMenuSeparator {}
StatusAction {
icon.name: "settings"

View File

@ -104,6 +104,9 @@ QtObject {
signal openTestnetPopup()
// Swap
signal openSwapModalRequested(var formDataParams)
/////////////////////////////////////////////////////
// WalletConnect POC - to remove
signal popupWalletConnect()