feat(@desktop/wallet): Implement loading state for Send/Bridge Modal

fixes #9107
This commit is contained in:
Khushboo Mehta 2023-01-27 18:46:42 +05:30 committed by Anthony Laibe
parent 8ba10ce6b0
commit 0d369129d5
9 changed files with 105 additions and 40 deletions

View File

@ -64,6 +64,16 @@ Item {
card.advancedMode = checked card.advancedMode = checked
} }
} }
StatusCheckBox {
Layout.alignment: Qt.AlignVCenter
text: "loading"
font.family: Theme.palette.monoFont.name
onClicked: {
card.loading = checked
}
}
} }
Rectangle { Rectangle {

View File

@ -158,6 +158,11 @@ Rectangle {
This property holds the max value in the advanced input that can be entered by the user This property holds the max value in the advanced input that can be entered by the user
*/ */
property real maxAdvancedValue property real maxAdvancedValue
/*!
\qmlproperty real StatusCard::loading
This property holds id the card is in loading state
*/
property bool loading: false
/*! /*!
\qmlsignal StatusCard::clicked \qmlsignal StatusCard::clicked
This signal is emitted when the card is 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 { StatusBaseText {
id: tertiaryText id: tertiaryText
Layout.maximumWidth: layout.width Layout.maximumWidth: layout.width
@ -424,7 +436,11 @@ Rectangle {
} }
PropertyChanges { PropertyChanges {
target: basicInput target: basicInput
visible: !advancedMode visible: !advancedMode && !(root.loading && !disabled)
}
PropertyChanges {
target: loadingComponent
active: root.loading && !advancedMode && !disabled
} }
}, },
State { State {
@ -493,7 +509,11 @@ Rectangle {
} }
PropertyChanges { PropertyChanges {
target: basicInput target: basicInput
visible: !advancedMode visible: !advancedMode && !(root.loading && !disabled)
}
PropertyChanges {
target: loadingComponent
active: root.loading && !advancedMode && !disabled
} }
}, },
State { State {
@ -562,7 +582,11 @@ Rectangle {
} }
PropertyChanges { PropertyChanges {
target: basicInput target: basicInput
visible: !advancedMode visible: !advancedMode && !(root.loading && !disabled)
}
PropertyChanges {
target: loadingComponent
active: root.loading && !advancedMode && !disabled
} }
}, },
State { State {
@ -631,5 +655,9 @@ Rectangle {
target: basicInput target: basicInput
visible: true visible: true
} }
PropertyChanges {
target: loadingComponent
active: false
}
} }
]} ]}

View File

@ -14,7 +14,7 @@ ColumnLayout {
id: balancedExceededError id: balancedExceededError
property double amountToSend: 0 property double amountToSend: 0
property bool isLoading: true property bool isLoading: false
property int errorType: Constants.NoError property int errorType: Constants.NoError
visible: balancedExceededError.errorType !== Constants.NoError || isLoading visible: balancedExceededError.errorType !== Constants.NoError || isLoading
@ -27,13 +27,6 @@ ColumnLayout {
color: Theme.palette.dangerColor1 color: Theme.palette.dangerColor1
visible: !isLoading visible: !isLoading
} }
StatusLoadingIndicator {
Layout.preferredHeight: 24
Layout.preferredWidth: 24
Layout.alignment: Qt.AlignHCenter
color: Theme.palette.baseColor1
visible: isLoading
}
StatusBaseText { StatusBaseText {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
@ -41,8 +34,17 @@ ColumnLayout {
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
color: Theme.palette.dangerColor1 color: Theme.palette.dangerColor1
text: isLoading ? qsTr("Calculating fees") : balancedExceededError.errorType === Constants.SendAmountExceedsBalance ? text: balancedExceededError.errorType === Constants.SendAmountExceedsBalance ? qsTr("Balance exceeded") :
qsTr("Balance exceeded") : balancedExceededError.errorType === Constants.NoRoute ? qsTr("No route found") : "" balancedExceededError.errorType === Constants.NoRoute ? qsTr("No route found") : ""
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
visible: !isLoading
}
Loader {
id: loadingComponent
Layout.alignment: Qt.AlignLeft
Layout.preferredHeight: 32
Layout.fillWidth: true
active: isLoading
sourceComponent: LoadingComponent { radius: 4 }
} }
} }

View File

@ -32,22 +32,23 @@ Column {
color: Theme.palette.dangerColor1 color: Theme.palette.dangerColor1
visible: !d.isValid && !isLoading visible: !d.isValid && !isLoading
} }
StatusLoadingIndicator {
anchors.horizontalCenter: parent.horizontalCenter
width: 24
height: 24
color: Theme.palette.baseColor1
visible: isLoading && d.isValid
}
StyledText { StyledText {
id: txtValidationError id: txtValidationError
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: isLoading ? qsTr("Calculating fees"): errorType === Constants.SendAmountExceedsBalance ? text: errorType === Constants.SendAmountExceedsBalance ?
qsTr("Balance exceeded") : qsTr("No route found") qsTr("Balance exceeded") : qsTr("No route found")
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
font.pixelSize: 13 font.pixelSize: 13
height: 18 height: 18
color: Style.current.danger 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 }
} }
} }

View File

@ -124,12 +124,17 @@ StatusDialog {
color: Theme.palette.baseColor3 color: Theme.palette.baseColor3
} }
onIsLoadingChanged: if(isLoading) bestRoutes = []
onSelectedAccountChanged: popup.recalculateRoutesAndFees() onSelectedAccountChanged: popup.recalculateRoutesAndFees()
onOpened: { onOpened: {
if(!isBridgeTx) { if(!isBridgeTx) {
store.setDefaultPreferredDisabledChains() store.setDefaultPreferredDisabledChains()
} }
else {
store.setAllNetworksAsPreferredChains()
}
amountToSendInput.input.input.edit.forceActiveFocus() amountToSendInput.input.input.edit.forceActiveFocus()
@ -284,7 +289,7 @@ StatusDialog {
id: amountToReceive id: amountToReceive
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
Layout.fillWidth:true 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 store: popup.store
isLoading: popup.isLoading isLoading: popup.isLoading
selectedAsset: assetSelector.selectedAsset selectedAsset: assetSelector.selectedAsset
@ -377,12 +382,14 @@ StatusDialog {
icon.color: Theme.palette.baseColor1 icon.color: Theme.palette.baseColor1
backgroundHoverColor: "transparent" backgroundHoverColor: "transparent"
onClicked: { onClicked: {
popup.isLoading = true
recipientSelector.input.edit.clear() recipientSelector.input.edit.clear()
d.waitTimer.restart() d.waitTimer.restart()
} }
} }
} }
Keys.onReleased: { Keys.onReleased: {
popup.isLoading = true
d.waitTimer.restart() d.waitTimer.restart()
if(!d.isAddressValid) { if(!d.isAddressValid) {
isPending = true isPending = true
@ -412,6 +419,7 @@ StatusDialog {
store: popup.store store: popup.store
onContactSelected: { onContactSelected: {
recipientSelector.input.text = address recipientSelector.input.text = address
popup.isLoading = true
d.waitTimer.restart() d.waitTimer.restart()
} }
visible: !d.recipientReady && !isBridgeTx && !!assetSelector.selectedAsset visible: !d.recipientReady && !isBridgeTx && !!assetSelector.selectedAsset
@ -431,7 +439,7 @@ StatusDialog {
requiredGasInEth: d.totalFeesInEth requiredGasInEth: d.totalFeesInEth
selectedAsset: assetSelector.selectedAsset selectedAsset: assetSelector.selectedAsset
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees() onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
visible: d.recipientReady && !!assetSelector.selectedAsset visible: d.recipientReady && !!assetSelector.selectedAsset && !!amountToSendInput.input.text
errorType: d.errorType errorType: d.errorType
isLoading: popup.isLoading isLoading: popup.isLoading
bestRoutes: popup.bestRoutes bestRoutes: popup.bestRoutes
@ -445,7 +453,7 @@ StatusDialog {
anchors.right: parent.right anchors.right: parent.right
anchors.leftMargin: Style.current.bigPadding anchors.leftMargin: Style.current.bigPadding
anchors.rightMargin: 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: "" selectedTokenSymbol: assetSelector.selectedAsset ? assetSelector.selectedAsset.symbol: ""
isLoading: popup.isLoading isLoading: popup.isLoading
bestRoutes: popup.bestRoutes bestRoutes: popup.bestRoutes
@ -463,7 +471,7 @@ StatusDialog {
maxFiatFees: popup.isLoading ? "..." : LocaleUtils.currencyAmountToLocaleString(d.totalFeesInFiat) maxFiatFees: popup.isLoading ? "..." : LocaleUtils.currencyAmountToLocaleString(d.totalFeesInFiat)
totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate
pending: d.isPendingTx || popup.isLoading 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() onNextButtonClicked: popup.sendTransaction()
} }

View File

@ -117,6 +117,16 @@ QtObject {
addUnpreferredChainsToDisabledChains() 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() { function resetTxStoreProperties() {
disabledChainIdsFromList = [] disabledChainIdsFromList = []
disabledChainIdsToList = [] disabledChainIdsToList = []
@ -182,10 +192,12 @@ QtObject {
} }
} }
if(!chainFound && !isBridgeTx) if(!isBridgeTx) {
addPreferredChains([getMainnetChainId()], showUnpreferredNetworks) if(!chainFound)
else addPreferredChains([getMainnetChainId()], showUnpreferredNetworks)
addPreferredChains(tempPreferredChains, showUnpreferredNetworks) else
addPreferredChains(tempPreferredChains, showUnpreferredNetworks)
}
editedText +="</a></p>" editedText +="</a></p>"
return { return {

View File

@ -43,6 +43,7 @@ Rectangle {
Column { Column {
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
Layout.preferredWidth: root.width - feesIcon.width - Style.current.xlPadding Layout.preferredWidth: root.width - feesIcon.width - Style.current.xlPadding
spacing: isLoading ? 4 : 0
Item { Item {
width: parent.width width: parent.width
height: childrenRect.height height: childrenRect.height

View File

@ -145,8 +145,8 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
amountToSend: root.amountToSend ? root.amountToSend.amount : 0.0 amountToSend: root.amountToSend ? root.amountToSend.amount : 0.0
isLoading: root.isLoading
errorType: root.errorType errorType: root.errorType
visible: root.errorType === Constants.NoRoute
} }
ColumnLayout { ColumnLayout {
id: toNetworksLayout id: toNetworksLayout
@ -157,7 +157,7 @@ Item {
Layout.maximumWidth: 100 Layout.maximumWidth: 100
font.pixelSize: 10 font.pixelSize: 10
color: Theme.palette.baseColor1 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 elide: Text.ElideMiddle
} }
Repeater { Repeater {
@ -182,6 +182,7 @@ Item {
enableText: qsTr("Enable") enableText: qsTr("Enable")
disabled: store.disabledChainIdsToList.includes(model.chainId) disabled: store.disabledChainIdsToList.includes(model.chainId)
clickable: root.interactive clickable: root.interactive
loading: root.isLoading
onClicked: { onClicked: {
store.addRemoveDisabledToChain(model.chainId, disabled) store.addRemoveDisabledToChain(model.chainId, disabled)
// only recalculate if the a best route was disabled // only recalculate if the a best route was disabled

View File

@ -38,6 +38,7 @@ RowLayout {
ColumnLayout { ColumnLayout {
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
Layout.preferredWidth: root.width Layout.preferredWidth: root.width
spacing: 4
StatusBaseText { StatusBaseText {
Layout.maximumWidth: 410 Layout.maximumWidth: 410
font.pixelSize: 15 font.pixelSize: 15
@ -56,14 +57,14 @@ RowLayout {
} }
ScrollView { ScrollView {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: row.height + 10 Layout.preferredHeight: visible ? row.height + 10 : 0
Layout.topMargin: Style.current.bigPadding Layout.topMargin: Style.current.smallPadding
contentWidth: row.width contentWidth: row.width
contentHeight: row.height + 10 contentHeight: row.height + 10
ScrollBar.vertical.policy: ScrollBar.AlwaysOff ScrollBar.vertical.policy: ScrollBar.AlwaysOff
ScrollBar.horizontal.policy: ScrollBar.AsNeeded ScrollBar.horizontal.policy: ScrollBar.AsNeeded
clip: true 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 { Column {
id: row id: row
spacing: Style.current.padding spacing: Style.current.padding
@ -78,10 +79,10 @@ RowLayout {
BalanceExceeded { BalanceExceeded {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Style.current.bigPadding Layout.topMargin: Style.current.smallPadding
amountToSend: root.amountToSend ? root.amountToSend.amount : 0.0 amountToSend: root.amountToSend ? root.amountToSend.amount : 0.0
isLoading: root.isLoading
errorType: root.errorType errorType: root.errorType
isLoading: root.isLoading && !root.isBridgeTx
} }
} }
@ -126,7 +127,7 @@ RowLayout {
objectName: chainName objectName: chainName
leftPadding: 5 leftPadding: 5
rightPadding: 5 rightPadding: 5
implicitWidth: 150 implicitWidth: 410
title: chainName title: chainName
property bool tokenBalanceOnChainValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined property bool tokenBalanceOnChainValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined
property var tokenBalanceOnChain: tokenBalanceOnChainValid ? root.store.getTokenBalanceOnChain(selectedAccount, chainId, selectedAsset.symbol) : undefined property var tokenBalanceOnChain: tokenBalanceOnChainValid ? root.store.getTokenBalanceOnChain(selectedAccount, chainId, selectedAsset.symbol) : undefined
@ -136,11 +137,12 @@ RowLayout {
asset.height: 32 asset.height: 32
asset.name: Style.svg("tiny/" + iconUrl) asset.name: Style.svg("tiny/" + iconUrl)
asset.isImage: true asset.isImage: true
border.color: gasRectangle.checked ? Theme.palette.primaryColor2 : "transparent"
color: { color: {
if (sensor.containsMouse || highlighted || gasRectangle.checked) { 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() onClicked: gasRectangle.toggle()
} }