From a3c9012f4ac959e7a3fef21268c550c55f7d332a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Tinkl?= Date: Tue, 28 May 2024 19:39:41 +0200 Subject: [PATCH] feat: [UI - Swap] Create swap input component - new panel created: `SwapInputPanel` - some cleanups to the needed stores - created a SB page demonstrating the use of 2 panels and the `SwapExchangeButton` - created QML tests Fixes #14781 --- storybook/pages/AmountToSendPage.qml | 63 ++-- storybook/pages/SlippageSelectorPage.qml | 2 +- storybook/pages/SwapInputPanelPage.qml | 203 +++++++++++++ storybook/pages/SwapModalPage.qml | 2 +- storybook/pages/TokenListViewPage.qml | 4 +- storybook/qmlTests/main.cpp | 4 + .../qmlTests/tests/tst_StatusAmountInput.qml | 1 + .../qmlTests/tests/tst_SwapInputPanel.qml | 252 ++++++++++++++++ storybook/qmlTests/tests/tst_SwapModal.qml | 2 +- .../AppLayouts/Wallet/stores/SwapStore.qml | 2 +- .../AppLayouts/Wallet/stores/TokensStore.qml | 4 +- .../Wallet/stores/WalletAssetsStore.qml | 10 +- .../stubs/shared/stores/CurrenciesStore.qml | 7 + .../shared/stores/send/TransactionStore.qml | 8 +- .../src/StatusQ/Components/StatusListItem.qml | 5 +- .../StatusQ/Components/StatusListItemTag.qml | 1 - .../StatusQ/Controls/StatusAmountInput.qml | 24 +- .../src/StatusQ/Controls/StatusBaseInput.qml | 2 +- ui/StatusQ/src/StatusQ/Core/LocaleUtils.qml | 8 +- .../Wallet/controls/SwapExchangeButton.qml | 2 +- .../Wallet/panels/SwapInputPanel.qml | 277 ++++++++++++++++++ ui/app/AppLayouts/Wallet/panels/qmldir | 3 +- .../popups/swap/SwapInputParamsForm.qml | 6 +- .../Wallet/popups/swap/SwapModal.qml | 2 +- .../Wallet/popups/swap/SwapModalAdaptor.qml | 89 +++++- .../AppLayouts/Wallet/stores/TokensStore.qml | 18 +- ui/app/mainui/AppMain.qml | 1 + ui/imports/shared/popups/send/SendModal.qml | 9 +- .../send/controls/AmountInputWithCursor.qml | 1 - .../controls/TokenBalancePerChainDelegate.qml | 33 +-- .../send/panels/HoldingItemSelector.qml | 44 +-- .../popups/send/panels/HoldingSelector.qml | 47 +-- .../shared/popups/send/views/AmountToSend.qml | 103 ++++--- .../popups/send/views/TokenListView.qml | 8 +- ui/imports/shared/stores/CurrenciesStore.qml | 9 +- .../shared/stores/send/TransactionStore.qml | 16 +- 36 files changed, 1045 insertions(+), 227 deletions(-) create mode 100644 storybook/pages/SwapInputPanelPage.qml create mode 100644 storybook/qmlTests/tests/tst_SwapInputPanel.qml create mode 100644 ui/app/AppLayouts/Wallet/panels/SwapInputPanel.qml diff --git a/storybook/pages/AmountToSendPage.qml b/storybook/pages/AmountToSendPage.qml index 5be8d0afc6..8d3f7f6aee 100644 --- a/storybook/pages/AmountToSendPage.qml +++ b/storybook/pages/AmountToSendPage.qml @@ -38,7 +38,7 @@ SplitView { maxInputBalance: inputIsFiat ? root.maxCryptoBalance*amountToSendInput.selectedHolding.marketDetails.currencyPrice.amount : root.maxCryptoBalance - currentCurrency: "Fiat" + currentCurrency: "USD" formatCurrencyAmount: function(amount, symbol, options, locale) { const currencyAmount = { amount: amount, @@ -57,47 +57,42 @@ SplitView { LogsAndControlsPanel { id: logsAndControlsPanel - SplitView.minimumHeight: 100 + SplitView.minimumHeight: 250 logsView.logText: logs.logText - } - } - Pane { - SplitView.minimumWidth: 300 - SplitView.preferredWidth: 300 + ColumnLayout { + Label { + Layout.topMargin: 10 + Layout.fillWidth: true + text: "Max Crypto Balance" + } - ColumnLayout { - Label { - Layout.topMargin: 10 - Layout.fillWidth: true - text: "Max Crypto Balance" - } + TextField { + id: maxCryptoBalanceText + background: Rectangle { border.color: 'lightgrey' } + Layout.preferredWidth: 200 + text: "1000000" + } - TextField { - id: maxCryptoBalanceText - background: Rectangle { border.color: 'lightgrey' } - Layout.preferredWidth: 200 - text: "1000000" - } + Label { + Layout.topMargin: 10 + Layout.fillWidth: true + text: "Decimals" + } - Label { - Layout.topMargin: 10 - Layout.fillWidth: true - text: "Decimals" - } + TextField { + id: decimalsText + background: Rectangle { border.color: 'lightgrey' } + Layout.preferredWidth: 200 + text: "6" + } - TextField { - id: decimalsText - background: Rectangle { border.color: 'lightgrey' } - Layout.preferredWidth: 200 - text: "6" - } + CheckBox { + id: fiatInput - CheckBox { - id: fiatInput - - text: "Fiat input value" + text: "Fiat input value" + } } } } diff --git a/storybook/pages/SlippageSelectorPage.qml b/storybook/pages/SlippageSelectorPage.qml index a5a09f2390..eaa758c285 100644 --- a/storybook/pages/SlippageSelectorPage.qml +++ b/storybook/pages/SlippageSelectorPage.qml @@ -47,7 +47,7 @@ SplitView { ColumnLayout { Repeater { - model: [0.1, 0.5, 0.24, 0.8, 120.84] + model: [0, 0.1, 0.5, 0.24, 0.8, 120.84] Button { text: "set " + modelData diff --git a/storybook/pages/SwapInputPanelPage.qml b/storybook/pages/SwapInputPanelPage.qml new file mode 100644 index 0000000000..9707cfab0b --- /dev/null +++ b/storybook/pages/SwapInputPanelPage.qml @@ -0,0 +1,203 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import StatusQ 0.1 +import StatusQ.Core.Theme 0.1 + +import utils 1.0 + +import shared.stores 1.0 +import shared.stores.send 1.0 + +import AppLayouts.Wallet.stores 1.0 +import AppLayouts.Wallet.panels 1.0 +import AppLayouts.Wallet.controls 1.0 + +import AppLayouts.Wallet.popups.swap 1.0 + +import Models 1.0 +import Storybook 1.0 + +import SortFilterProxyModel 0.2 + +SplitView { + id: root + + Logs { id: logs } + + QtObject { + id: d + + readonly property SwapInputParamsForm swapInputParamsForm: SwapInputParamsForm { + fromTokensKey: ctrlFromTokensKey.text + fromTokenAmount: ctrlFromTokenAmount.text + toTokenKey: ctrlToTokenKey.text + toTokenAmount: ctrlToTokenAmount.text + } + + readonly property SwapModalAdaptor adaptor: SwapModalAdaptor { + swapStore: SwapStore { + readonly property var accounts: WalletAccountsModel {} + readonly property var flatNetworks: NetworksModel.flatNetworks + readonly property bool areTestNetworksEnabled: false + } + walletAssetsStore: WalletAssetsStore { + id: thisWalletAssetStore + walletTokensStore: TokensStore { + plainTokensBySymbolModel: TokensBySymbolModel {} + } + readonly property var baseGroupedAccountAssetModel: GroupedAccountsAssetsModel {} + assetsWithFilteredBalances: thisWalletAssetStore.groupedAccountsAssetsModel + } + currencyStore: CurrenciesStore {} + swapFormData: d.swapInputParamsForm + } + } + + Rectangle { + SplitView.fillWidth: true + SplitView.fillHeight: true + color: Theme.palette.baseColor3 + + Item { + width: 492 + height: payPanel.height + receivePanel.height + 4 + anchors.centerIn: parent + + SwapInputPanel { + id: payPanel + anchors { + left: parent.left + right: parent.right + top: parent.top + } + + currencyStore: d.adaptor.currencyStore + flatNetworksModel: d.adaptor.filteredFlatNetworksModel + processedAssetsModel: d.adaptor.processedAssetsModel + + tokenKey: d.swapInputParamsForm.fromTokensKey + tokenAmount: d.swapInputParamsForm.fromTokenAmount + + swapSide: SwapInputPanel.SwapSide.Pay + fiatInputInteractive: ctrlFiatInputInteractive.checked + swapExchangeButtonWidth: swapButton.width + loading: ctrlLoading.checked + } + + SwapInputPanel { + id: receivePanel + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + + currencyStore: d.adaptor.currencyStore + flatNetworksModel: d.adaptor.filteredFlatNetworksModel + processedAssetsModel: d.adaptor.processedAssetsModel + + tokenKey: d.swapInputParamsForm.toTokenKey + tokenAmount: d.swapInputParamsForm.toTokenAmount + + swapSide: SwapInputPanel.SwapSide.Receive + fiatInputInteractive: ctrlFiatInputInteractive.checked + swapExchangeButtonWidth: swapButton.width + loading: ctrlLoading.checked + } + + SwapExchangeButton { + id: swapButton + anchors.centerIn: parent + } + } + } + + LogsAndControlsPanel { + id: logsAndControlsPanel + + SplitView.minimumWidth: 250 + SplitView.preferredWidth: 250 + + logsView.logText: logs.logText + + ColumnLayout { + anchors.fill: parent + + RowLayout { + Layout.fillWidth: true + Label { + text: "Pay symbol:" + } + TextField { + Layout.fillWidth: true + id: ctrlFromTokensKey + } + } + RowLayout { + Layout.fillWidth: true + Label { + text: "Pay amount:" + } + TextField { + Layout.fillWidth: true + id: ctrlFromTokenAmount + } + } + RowLayout { + Layout.fillWidth: true + Label { + text: "Receive symbol:" + } + TextField { + Layout.fillWidth: true + id: ctrlToTokenKey + text: "STT" + } + } + RowLayout { + Layout.fillWidth: true + Label { + text: "Receive amount:" + } + TextField { + Layout.fillWidth: true + id: ctrlToTokenAmount + } + } + Switch { + id: ctrlFiatInputInteractive + text: "Fiat input interactive" + checked: false + } + Switch { + id: ctrlLoading + text: "Loading" + } + + Label { + Layout.fillWidth: true + font.weight: Font.Medium + text: "Pay: