From 0d369129d5c8d4e8fd7384b6b44912c10e14027a Mon Sep 17 00:00:00 2001 From: Khushboo Mehta Date: Fri, 27 Jan 2023 18:46:42 +0530 Subject: [PATCH] feat(@desktop/wallet): Implement loading state for Send/Bridge Modal fixes #9107 --- ui/StatusQ/sandbox/pages/StatusCardPage.qml | 10 ++++++ .../src/StatusQ/Components/StatusCard.qml | 34 +++++++++++++++++-- .../shared/controls/BalanceExceeded.qml | 22 ++++++------ ui/imports/shared/controls/GasValidator.qml | 19 ++++++----- ui/imports/shared/popups/SendModal.qml | 16 ++++++--- ui/imports/shared/stores/TransactionStore.qml | 20 ++++++++--- ui/imports/shared/views/FeesView.qml | 1 + .../shared/views/NetworkCardsComponent.qml | 5 +-- .../views/NetworksSimpleRoutingView.qml | 18 +++++----- 9 files changed, 105 insertions(+), 40 deletions(-) diff --git a/ui/StatusQ/sandbox/pages/StatusCardPage.qml b/ui/StatusQ/sandbox/pages/StatusCardPage.qml index 5a29ddf0bf..46bfd7f300 100644 --- a/ui/StatusQ/sandbox/pages/StatusCardPage.qml +++ b/ui/StatusQ/sandbox/pages/StatusCardPage.qml @@ -64,6 +64,16 @@ Item { card.advancedMode = checked } } + + + StatusCheckBox { + Layout.alignment: Qt.AlignVCenter + text: "loading" + font.family: Theme.palette.monoFont.name + onClicked: { + card.loading = checked + } + } } Rectangle { diff --git a/ui/StatusQ/src/StatusQ/Components/StatusCard.qml b/ui/StatusQ/src/StatusQ/Components/StatusCard.qml index ec9b463cf4..5a999b6005 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusCard.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusCard.qml @@ -158,6 +158,11 @@ Rectangle { This property holds the max value in the advanced input that can be entered by the user */ property real maxAdvancedValue + /*! + \qmlproperty real StatusCard::loading + This property holds id the card is in loading state + */ + property bool loading: false /*! \qmlsignal StatusCard::clicked This signal is emitted when the card is clicked @@ -332,6 +337,13 @@ Rectangle { } } } + Loader { + id: loadingComponent + Layout.preferredHeight: active ? 32 : 0 + Layout.fillWidth: true + active: false + sourceComponent: LoadingComponent { radius: 4 } + } StatusBaseText { id: tertiaryText Layout.maximumWidth: layout.width @@ -424,7 +436,11 @@ Rectangle { } PropertyChanges { target: basicInput - visible: !advancedMode + visible: !advancedMode && !(root.loading && !disabled) + } + PropertyChanges { + target: loadingComponent + active: root.loading && !advancedMode && !disabled } }, State { @@ -493,7 +509,11 @@ Rectangle { } PropertyChanges { target: basicInput - visible: !advancedMode + visible: !advancedMode && !(root.loading && !disabled) + } + PropertyChanges { + target: loadingComponent + active: root.loading && !advancedMode && !disabled } }, State { @@ -562,7 +582,11 @@ Rectangle { } PropertyChanges { target: basicInput - visible: !advancedMode + visible: !advancedMode && !(root.loading && !disabled) + } + PropertyChanges { + target: loadingComponent + active: root.loading && !advancedMode && !disabled } }, State { @@ -631,5 +655,9 @@ Rectangle { target: basicInput visible: true } + PropertyChanges { + target: loadingComponent + active: false + } } ]} diff --git a/ui/imports/shared/controls/BalanceExceeded.qml b/ui/imports/shared/controls/BalanceExceeded.qml index adc660ab82..91ff9300d5 100644 --- a/ui/imports/shared/controls/BalanceExceeded.qml +++ b/ui/imports/shared/controls/BalanceExceeded.qml @@ -14,7 +14,7 @@ ColumnLayout { id: balancedExceededError property double amountToSend: 0 - property bool isLoading: true + property bool isLoading: false property int errorType: Constants.NoError visible: balancedExceededError.errorType !== Constants.NoError || isLoading @@ -27,13 +27,6 @@ ColumnLayout { color: Theme.palette.dangerColor1 visible: !isLoading } - StatusLoadingIndicator { - Layout.preferredHeight: 24 - Layout.preferredWidth: 24 - Layout.alignment: Qt.AlignHCenter - color: Theme.palette.baseColor1 - visible: isLoading - } StatusBaseText { Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter @@ -41,8 +34,17 @@ ColumnLayout { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter color: Theme.palette.dangerColor1 - text: isLoading ? qsTr("Calculating fees") : balancedExceededError.errorType === Constants.SendAmountExceedsBalance ? - qsTr("Balance exceeded") : balancedExceededError.errorType === Constants.NoRoute ? qsTr("No route found") : "" + text: balancedExceededError.errorType === Constants.SendAmountExceedsBalance ? qsTr("Balance exceeded") : + balancedExceededError.errorType === Constants.NoRoute ? qsTr("No route found") : "" wrapMode: Text.WordWrap + visible: !isLoading + } + Loader { + id: loadingComponent + Layout.alignment: Qt.AlignLeft + Layout.preferredHeight: 32 + Layout.fillWidth: true + active: isLoading + sourceComponent: LoadingComponent { radius: 4 } } } diff --git a/ui/imports/shared/controls/GasValidator.qml b/ui/imports/shared/controls/GasValidator.qml index b4290e0f82..9e1a3ace73 100644 --- a/ui/imports/shared/controls/GasValidator.qml +++ b/ui/imports/shared/controls/GasValidator.qml @@ -32,22 +32,23 @@ Column { color: Theme.palette.dangerColor1 visible: !d.isValid && !isLoading } - StatusLoadingIndicator { - anchors.horizontalCenter: parent.horizontalCenter - width: 24 - height: 24 - color: Theme.palette.baseColor1 - visible: isLoading && d.isValid - } StyledText { id: txtValidationError anchors.horizontalCenter: parent.horizontalCenter - text: isLoading ? qsTr("Calculating fees"): errorType === Constants.SendAmountExceedsBalance ? - qsTr("Balance exceeded") : qsTr("No route found") + text: errorType === Constants.SendAmountExceedsBalance ? + qsTr("Balance exceeded") : qsTr("No route found") verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pixelSize: 13 height: 18 color: Style.current.danger + visible: !isLoading + } + Loader { + id: loadingComponent + height: 32 + width: root.width - Style.current.xlPadding + active: isLoading && d.isValid + sourceComponent: LoadingComponent { radius: 4 } } } diff --git a/ui/imports/shared/popups/SendModal.qml b/ui/imports/shared/popups/SendModal.qml index a45b6e9402..4e7aa48347 100644 --- a/ui/imports/shared/popups/SendModal.qml +++ b/ui/imports/shared/popups/SendModal.qml @@ -124,12 +124,17 @@ StatusDialog { color: Theme.palette.baseColor3 } + onIsLoadingChanged: if(isLoading) bestRoutes = [] + onSelectedAccountChanged: popup.recalculateRoutesAndFees() onOpened: { if(!isBridgeTx) { store.setDefaultPreferredDisabledChains() } + else { + store.setAllNetworksAsPreferredChains() + } amountToSendInput.input.input.edit.forceActiveFocus() @@ -284,7 +289,7 @@ StatusDialog { id: amountToReceive Layout.alignment: Qt.AlignRight Layout.fillWidth:true - visible: popup.bestRoutes !== undefined && popup.bestRoutes.length > 0 + visible: popup.bestRoutes !== undefined && popup.bestRoutes.length > 0 && !!amountToSendInput.input.text && amountToSendInput.input.valid store: popup.store isLoading: popup.isLoading selectedAsset: assetSelector.selectedAsset @@ -377,12 +382,14 @@ StatusDialog { icon.color: Theme.palette.baseColor1 backgroundHoverColor: "transparent" onClicked: { + popup.isLoading = true recipientSelector.input.edit.clear() d.waitTimer.restart() } } } Keys.onReleased: { + popup.isLoading = true d.waitTimer.restart() if(!d.isAddressValid) { isPending = true @@ -412,6 +419,7 @@ StatusDialog { store: popup.store onContactSelected: { recipientSelector.input.text = address + popup.isLoading = true d.waitTimer.restart() } visible: !d.recipientReady && !isBridgeTx && !!assetSelector.selectedAsset @@ -431,7 +439,7 @@ StatusDialog { requiredGasInEth: d.totalFeesInEth selectedAsset: assetSelector.selectedAsset onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees() - visible: d.recipientReady && !!assetSelector.selectedAsset + visible: d.recipientReady && !!assetSelector.selectedAsset && !!amountToSendInput.input.text errorType: d.errorType isLoading: popup.isLoading bestRoutes: popup.bestRoutes @@ -445,7 +453,7 @@ StatusDialog { anchors.right: parent.right anchors.leftMargin: Style.current.bigPadding anchors.rightMargin: Style.current.bigPadding - visible: d.recipientReady && !!assetSelector.selectedAsset && networkSelector.advancedOrCustomMode + visible: d.recipientReady && !!assetSelector.selectedAsset && networkSelector.advancedOrCustomMode && !!amountToSendInput.input.text selectedTokenSymbol: assetSelector.selectedAsset ? assetSelector.selectedAsset.symbol: "" isLoading: popup.isLoading bestRoutes: popup.bestRoutes @@ -463,7 +471,7 @@ StatusDialog { maxFiatFees: popup.isLoading ? "..." : LocaleUtils.currencyAmountToLocaleString(d.totalFeesInFiat) totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate pending: d.isPendingTx || popup.isLoading - visible: d.recipientReady && amountToSendInput.cryptoValueToSend && amountToSendInput.cryptoValueToSend.amount > 0 && !d.errorMode + visible: d.recipientReady && !!amountToSendInput.cryptoValueToSend && amountToSendInput.cryptoValueToSend.amount > 0 && !d.errorMode && !!amountToSendInput.input.text && amountToSendInput.input.valid onNextButtonClicked: popup.sendTransaction() } diff --git a/ui/imports/shared/stores/TransactionStore.qml b/ui/imports/shared/stores/TransactionStore.qml index c534a87064..192045c9a5 100644 --- a/ui/imports/shared/stores/TransactionStore.qml +++ b/ui/imports/shared/stores/TransactionStore.qml @@ -117,6 +117,16 @@ QtObject { addUnpreferredChainsToDisabledChains() } + function setAllNetworksAsPreferredChains() { + var preferredChains = [] + for(var i = 0; i < allNetworks.count; i++) { + let chainId = allNetworks.rowData(i, "chainId") * 1 + if(!preferredChainIds.includes(chainId)) { + preferredChainIds.push(chainId) + } + } + } + function resetTxStoreProperties() { disabledChainIdsFromList = [] disabledChainIdsToList = [] @@ -182,10 +192,12 @@ QtObject { } } - if(!chainFound && !isBridgeTx) - addPreferredChains([getMainnetChainId()], showUnpreferredNetworks) - else - addPreferredChains(tempPreferredChains, showUnpreferredNetworks) + if(!isBridgeTx) { + if(!chainFound) + addPreferredChains([getMainnetChainId()], showUnpreferredNetworks) + else + addPreferredChains(tempPreferredChains, showUnpreferredNetworks) + } editedText +="

" return { diff --git a/ui/imports/shared/views/FeesView.qml b/ui/imports/shared/views/FeesView.qml index 1eae13df74..d5978b5d9e 100644 --- a/ui/imports/shared/views/FeesView.qml +++ b/ui/imports/shared/views/FeesView.qml @@ -43,6 +43,7 @@ Rectangle { Column { Layout.alignment: Qt.AlignTop | Qt.AlignHCenter Layout.preferredWidth: root.width - feesIcon.width - Style.current.xlPadding + spacing: isLoading ? 4 : 0 Item { width: parent.width height: childrenRect.height diff --git a/ui/imports/shared/views/NetworkCardsComponent.qml b/ui/imports/shared/views/NetworkCardsComponent.qml index 606985a8d6..0b0f930b9a 100644 --- a/ui/imports/shared/views/NetworkCardsComponent.qml +++ b/ui/imports/shared/views/NetworkCardsComponent.qml @@ -145,8 +145,8 @@ Item { Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter amountToSend: root.amountToSend ? root.amountToSend.amount : 0.0 - isLoading: root.isLoading errorType: root.errorType + visible: root.errorType === Constants.NoRoute } ColumnLayout { id: toNetworksLayout @@ -157,7 +157,7 @@ Item { Layout.maximumWidth: 100 font.pixelSize: 10 color: Theme.palette.baseColor1 - text: StatusQUtils.Utils.elideText(selectedAccount.address, 6, 4).toUpperCase() + text: !!selectedAccount ? StatusQUtils.Utils.elideText(selectedAccount.address, 6, 4).toUpperCase() : "" elide: Text.ElideMiddle } Repeater { @@ -182,6 +182,7 @@ Item { enableText: qsTr("Enable") disabled: store.disabledChainIdsToList.includes(model.chainId) clickable: root.interactive + loading: root.isLoading onClicked: { store.addRemoveDisabledToChain(model.chainId, disabled) // only recalculate if the a best route was disabled diff --git a/ui/imports/shared/views/NetworksSimpleRoutingView.qml b/ui/imports/shared/views/NetworksSimpleRoutingView.qml index 35b9a27565..806c42aa20 100644 --- a/ui/imports/shared/views/NetworksSimpleRoutingView.qml +++ b/ui/imports/shared/views/NetworksSimpleRoutingView.qml @@ -38,6 +38,7 @@ RowLayout { ColumnLayout { Layout.alignment: Qt.AlignTop Layout.preferredWidth: root.width + spacing: 4 StatusBaseText { Layout.maximumWidth: 410 font.pixelSize: 15 @@ -56,14 +57,14 @@ RowLayout { } ScrollView { Layout.fillWidth: true - Layout.preferredHeight: row.height + 10 - Layout.topMargin: Style.current.bigPadding + Layout.preferredHeight: visible ? row.height + 10 : 0 + Layout.topMargin: Style.current.smallPadding contentWidth: row.width contentHeight: row.height + 10 ScrollBar.vertical.policy: ScrollBar.AlwaysOff ScrollBar.horizontal.policy: ScrollBar.AsNeeded clip: true - visible: !root.isLoading ? root.isBridgeTx ? true : root.errorType === Constants.NoError : false + visible: root.isBridgeTx ? true : !root.isLoading ? root.errorType === Constants.NoError : false Column { id: row spacing: Style.current.padding @@ -78,10 +79,10 @@ RowLayout { BalanceExceeded { Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Style.current.bigPadding + Layout.topMargin: Style.current.smallPadding amountToSend: root.amountToSend ? root.amountToSend.amount : 0.0 - isLoading: root.isLoading errorType: root.errorType + isLoading: root.isLoading && !root.isBridgeTx } } @@ -126,7 +127,7 @@ RowLayout { objectName: chainName leftPadding: 5 rightPadding: 5 - implicitWidth: 150 + implicitWidth: 410 title: chainName property bool tokenBalanceOnChainValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined property var tokenBalanceOnChain: tokenBalanceOnChainValid ? root.store.getTokenBalanceOnChain(selectedAccount, chainId, selectedAsset.symbol) : undefined @@ -136,11 +137,12 @@ RowLayout { asset.height: 32 asset.name: Style.svg("tiny/" + iconUrl) asset.isImage: true + border.color: gasRectangle.checked ? Theme.palette.primaryColor2 : "transparent" color: { if (sensor.containsMouse || highlighted || gasRectangle.checked) { - return Theme.palette.baseColor2 + return Theme.palette.statusListItem.backgroundColor } - return Theme.palette.statusListItem.backgroundColor + return Theme.palette.baseColor2 } onClicked: gasRectangle.toggle() }