mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-07 20:25:36 +00:00
429203cd66
This is the first step in refactoring the NetworkFilter, by cleaning the base component that handles the check states. This component supports multiple configurations: 1. Single selection with or without radio button 2. Multiple selection with or without checkbox 3. Automatic handling of the check state. The component will change the check state based on user clicks 4. Manual handling of the check state. The component will not change the check state, but offers a toggled signal and expects the user to change the check state based on external flows + Fix minor bugs
357 lines
14 KiB
QML
357 lines
14 KiB
QML
import QtQuick 2.15
|
|
import QtQuick.Layouts 1.15
|
|
import QtQml.Models 2.15
|
|
|
|
import utils 1.0
|
|
|
|
import StatusQ.Controls 0.1
|
|
import StatusQ.Core 0.1
|
|
import StatusQ.Core.Theme 0.1
|
|
import StatusQ.Core.Utils 0.1 as SQUtils
|
|
import StatusQ.Popups.Dialog 0.1
|
|
import StatusQ.Controls 0.1
|
|
|
|
import shared.popups.send.controls 1.0
|
|
import shared.controls 1.0
|
|
|
|
import AppLayouts.Wallet.controls 1.0
|
|
import AppLayouts.Wallet.panels 1.0
|
|
|
|
StatusDialog {
|
|
id: root
|
|
|
|
/* This should be the only property which should be used to input
|
|
parameters to the modal when being launched from elsewhere */
|
|
required property SwapInputParamsForm swapInputParamsForm
|
|
required property SwapModalAdaptor swapAdaptor
|
|
|
|
objectName: "swapModal"
|
|
|
|
implicitWidth: 556
|
|
topPadding: 0
|
|
bottomPadding: Style.current.xlPadding
|
|
leftPadding: Style.current.xlPadding
|
|
rightPadding: Style.current.xlPadding
|
|
backgroundColor: Theme.palette.baseColor3
|
|
|
|
QtObject {
|
|
id: d
|
|
property var debounceFetchSuggestedRoutes: Backpressure.debounce(root, 1000, function() {
|
|
root.swapAdaptor.fetchSuggestedRoutes(payPanel.rawValue)
|
|
})
|
|
|
|
function fetchSuggestedRoutes() {
|
|
if (payPanel.valueValid) {
|
|
root.swapAdaptor.newFetchReset()
|
|
root.swapAdaptor.swapProposalLoading = true
|
|
debounceFetchSuggestedRoutes()
|
|
}
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: root.swapInputParamsForm
|
|
function onFormValuesChanged() {
|
|
d.fetchSuggestedRoutes()
|
|
}
|
|
// refresh the selected asset in payPanel when account/network changes
|
|
function onSelectedAccountAddressChanged() {
|
|
payPanel.reevaluateSelectedId()
|
|
}
|
|
function onSelectedNetworkChainIdChanged() {
|
|
payPanel.reevaluateSelectedId()
|
|
}
|
|
}
|
|
|
|
Behavior on implicitHeight {
|
|
NumberAnimation { duration: 1000; easing.type: Easing.OutExpo; alwaysRunToEnd: true}
|
|
}
|
|
|
|
onClosed: root.swapAdaptor.reset()
|
|
|
|
header: Item {
|
|
height: selector.height
|
|
anchors.top: parent.top
|
|
anchors.topMargin: -height - 18
|
|
AccountSelectorHeader {
|
|
id: selector
|
|
control.popup.width: 512
|
|
model: root.swapAdaptor.nonWatchAccounts
|
|
selectedAddress: root.swapInputParamsForm.selectedAccountAddress
|
|
onCurrentAccountAddressChanged: {
|
|
if (currentAccountAddress !== "" && currentAccountAddress !== root.swapInputParamsForm.selectedAccountAddress) {
|
|
root.swapInputParamsForm.selectedAccountAddress = currentAccountAddress
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
contentItem: ColumnLayout {
|
|
spacing: Style.current.padding
|
|
clip: true
|
|
|
|
// without this Column, the whole popup resizing when the network selector popup is clicked
|
|
Column {
|
|
Layout.fillWidth: true
|
|
spacing: 0
|
|
RowLayout {
|
|
width: parent.width
|
|
spacing: 12
|
|
HeaderTitleText {
|
|
Layout.fillWidth: true
|
|
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
|
id: modalHeader
|
|
text: qsTr("Swap")
|
|
}
|
|
StatusBaseText {
|
|
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
|
text: qsTr("On:")
|
|
color: Theme.palette.baseColor1
|
|
font.pixelSize: 13
|
|
lineHeight: 38
|
|
lineHeightMode: Text.FixedHeight
|
|
verticalAlignment: Text.AlignVCenter
|
|
}
|
|
// TODO: update this once https://github.com/status-im/status-desktop/issues/14780 is ready
|
|
NetworkFilter {
|
|
id: networkFilter
|
|
objectName: "networkFilter"
|
|
Layout.alignment: Qt.AlignVCenter
|
|
multiSelection: false
|
|
showRadioButtons: false
|
|
showTitle: false
|
|
flatNetworks: root.swapAdaptor.filteredFlatNetworksModel
|
|
onToggleNetwork: (network) => {
|
|
root.swapInputParamsForm.selectedNetworkChainId = network.chainId
|
|
}
|
|
Component.onCompleted: {
|
|
if(root.swapInputParamsForm.selectedNetworkChainId !== -1)
|
|
networkFilter.setChain(root.swapInputParamsForm.selectedNetworkChainId)
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: root.swapInputParamsForm
|
|
function onSelectedNetworkChainIdChanged() {
|
|
networkFilter.setChain(root.swapInputParamsForm.selectedNetworkChainId)
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: root.swapInputParamsForm
|
|
function onSelectedNetworkChainIdChanged() {
|
|
networkFilter.setChain(root.swapInputParamsForm.selectedNetworkChainId)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: 2
|
|
Layout.preferredHeight: payPanel.height + receivePanel.height + 4
|
|
|
|
SwapInputPanel {
|
|
id: payPanel
|
|
objectName: "payPanel"
|
|
|
|
anchors {
|
|
left: parent.left
|
|
right: parent.right
|
|
top: parent.top
|
|
}
|
|
|
|
currencyStore: root.swapAdaptor.currencyStore
|
|
flatNetworksModel: root.swapAdaptor.filteredFlatNetworksModel
|
|
processedAssetsModel: root.swapAdaptor.processedAssetsModel
|
|
|
|
tokenKey: root.swapInputParamsForm.fromTokensKey
|
|
tokenAmount: {
|
|
// Only update if there is different in amount displayed
|
|
if (root.swapInputParamsForm.fromTokenAmount !==
|
|
SQUtils.AmountsArithmetic.fromString(value).toLocaleString(locale, 'f', -128)){
|
|
return root.swapInputParamsForm.fromTokenAmount
|
|
}
|
|
return payPanel.tokenAmount
|
|
}
|
|
|
|
swapSide: SwapInputPanel.SwapSide.Pay
|
|
swapExchangeButtonWidth: swapButton.width
|
|
|
|
onSelectedHoldingIdChanged: root.swapInputParamsForm.fromTokensKey = selectedHoldingId
|
|
onValueChanged: root.swapInputParamsForm.fromTokenAmount = value.toLocaleString(locale, 'f', -128)
|
|
onValueValidChanged: d.fetchSuggestedRoutes()
|
|
}
|
|
|
|
SwapInputPanel {
|
|
id: receivePanel
|
|
objectName: "receivePanel"
|
|
|
|
anchors {
|
|
left: parent.left
|
|
right: parent.right
|
|
bottom: parent.bottom
|
|
}
|
|
|
|
currencyStore: root.swapAdaptor.currencyStore
|
|
flatNetworksModel: root.swapAdaptorfilteredFlatNetworksModel
|
|
processedAssetsModel: root.swapAdaptor.processedAssetsModel
|
|
|
|
tokenKey: root.swapInputParamsForm.toTokenKey
|
|
tokenAmount: root.swapAdaptor.validSwapProposalReceived && root.swapAdaptor.toToken ? root.swapAdaptor.swapOutputData.toTokenAmount: root.swapInputParamsForm.toTokenAmount
|
|
|
|
swapSide: SwapInputPanel.SwapSide.Receive
|
|
swapExchangeButtonWidth: swapButton.width
|
|
|
|
mainInputLoading: root.swapAdaptor.swapProposalLoading
|
|
bottomTextLoading: root.swapAdaptor.swapProposalLoading
|
|
|
|
onSelectedHoldingIdChanged: root.swapInputParamsForm.toTokenKey = selectedHoldingId
|
|
|
|
/* TODO: keep this input as disabled until the work for adding a param to handle to
|
|
and from tokens inputed is supported by backend under
|
|
https://github.com/status-im/status-desktop/issues/15095 */
|
|
interactive: false
|
|
}
|
|
|
|
SwapExchangeButton {
|
|
id: swapButton
|
|
anchors.centerIn: parent
|
|
}
|
|
}
|
|
|
|
/* TODO: remove! Needed only till sign after approval is implemented under
|
|
https://github.com/status-im/status-desktop/issues/14833 */
|
|
StatusButton {
|
|
text: "Final Swap after Approval"
|
|
visible: root.swapAdaptor.validSwapProposalReceived && root.swapAdaptor.swapOutputData.approvalNeeded
|
|
onClicked: {
|
|
swapAdaptor.sendSwapTx()
|
|
close()
|
|
}
|
|
}
|
|
|
|
EditSlippagePanel {
|
|
id: editSlippagePanel
|
|
objectName: "editSlippagePanel"
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: Style.current.padding
|
|
visible: editSlippageButton.checked
|
|
selectedToToken: root.swapAdaptor.toToken
|
|
toTokenAmount: root.swapAdaptor.swapOutputData.toTokenAmount
|
|
loading: root.swapAdaptor.swapProposalLoading
|
|
onSlippageValueChanged: {
|
|
root.swapInputParamsForm.selectedSlippage = slippageValue
|
|
}
|
|
}
|
|
|
|
ErrorTag {
|
|
objectName: "errorTag"
|
|
visible: root.swapAdaptor.swapOutputData.hasError || payPanel.amountEnteredGreaterThanBalance
|
|
Layout.alignment: Qt.AlignHCenter
|
|
Layout.topMargin: Style.current.smallPadding
|
|
text: {
|
|
if (payPanel.amountEnteredGreaterThanBalance) {
|
|
return qsTr("Insufficient funds for swap")
|
|
}
|
|
return qsTr("An error has occured, please try again")
|
|
}
|
|
buttonText: qsTr("Buy crypto")
|
|
buttonVisible: payPanel.amountEnteredGreaterThanBalance
|
|
onButtonClicked: Global.openBuyCryptoModalRequested()
|
|
}
|
|
}
|
|
|
|
footer: StatusDialogFooter {
|
|
color: Theme.palette.baseColor3
|
|
dropShadowEnabled: true
|
|
leftButtons: ObjectModel {
|
|
ColumnLayout {
|
|
Layout.leftMargin: Style.current.padding
|
|
spacing: 0
|
|
StatusBaseText {
|
|
objectName: "maxSlippageText"
|
|
text: qsTr("Max slippage:")
|
|
color: Theme.palette.directColor5
|
|
font.pixelSize: 15
|
|
font.weight: Font.Medium
|
|
}
|
|
RowLayout {
|
|
StatusBaseText {
|
|
objectName: "maxSlippageValue"
|
|
text: "%1%".arg(LocaleUtils.numberToLocaleString(root.swapInputParamsForm.selectedSlippage))
|
|
color: Theme.palette.directColor4
|
|
font.pixelSize: 15
|
|
font.weight: Font.Medium
|
|
}
|
|
StatusFlatButton {
|
|
id: editSlippageButton
|
|
objectName: "editSlippageButton"
|
|
checkable: true
|
|
checked: false
|
|
icon.name: "edit_pencil"
|
|
textColor: editSlippageButton.hovered ? Theme.palette.directColor1 : Theme.palette.directColor5
|
|
size: StatusBaseButton.Size.Tiny
|
|
hoverColor: Theme.palette.transparent
|
|
visible: !checked
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rightButtons: ObjectModel {
|
|
RowLayout {
|
|
Layout.rightMargin: Style.current.padding
|
|
spacing: Style.current.bigPadding
|
|
ColumnLayout {
|
|
StatusBaseText {
|
|
objectName: "maxFeesText"
|
|
text: qsTr("Max fees:")
|
|
color: Theme.palette.directColor5
|
|
font.pixelSize: 15
|
|
font.weight: Font.Medium
|
|
}
|
|
StatusTextWithLoadingState {
|
|
objectName: "maxFeesValue"
|
|
text: loading ? Constants.dummyText :
|
|
root.swapAdaptor.validSwapProposalReceived ?
|
|
root.swapAdaptor.currencyStore.formatCurrencyAmount(
|
|
root.swapAdaptor.swapOutputData.totalFees,
|
|
root.swapAdaptor.currencyStore.currentCurrency) :
|
|
"--"
|
|
customColor: Theme.palette.directColor4
|
|
font.pixelSize: 15
|
|
font.weight: Font.Medium
|
|
loading: root.swapAdaptor.swapProposalLoading
|
|
}
|
|
}
|
|
StatusButton {
|
|
objectName: "signButton"
|
|
icon.name: "password"
|
|
/* TODO: Handling the next step agter approval of spending cap TBD under
|
|
https://github.com/status-im/status-desktop/issues/14833 */
|
|
text: root.swapAdaptor.validSwapProposalReceived &&
|
|
root.swapAdaptor.swapOutputData.approvalNeeded ?
|
|
qsTr("Approve %1").arg(!!root.swapAdaptor.fromToken ? root.swapAdaptor.fromToken.symbol: "") :
|
|
qsTr("Swap")
|
|
disabledColor: Theme.palette.directColor8
|
|
enabled: root.swapAdaptor.validSwapProposalReceived &&
|
|
editSlippagePanel.valid &&
|
|
!payPanel.amountEnteredGreaterThanBalance
|
|
onClicked: {
|
|
if (root.swapAdaptor.validSwapProposalReceived ){
|
|
if(root.swapAdaptor.swapOutputData.approvalNeeded) {
|
|
swapAdaptor.sendApproveTx()
|
|
}
|
|
else {
|
|
swapAdaptor.sendSwapTx()
|
|
close()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|