parent
dbfa9b0b39
commit
3010fb58cb
|
@ -47,8 +47,6 @@ SplitView {
|
|||
PopupBackground {
|
||||
id: popupBg
|
||||
|
||||
property var popupIntance: null
|
||||
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
|
@ -80,14 +78,19 @@ SplitView {
|
|||
}
|
||||
return ""
|
||||
}
|
||||
toTokenAmount: swapOutputAmount.text
|
||||
}
|
||||
|
||||
Component {
|
||||
id: swapModal
|
||||
SwapModal {
|
||||
visible: true
|
||||
modal: false
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
swapInputParamsForm: swapInputForm
|
||||
swapAdaptor: SwapModalAdaptor {
|
||||
swapProposalLoading: loadingCheckBox.checked
|
||||
swapProposalReady: swapProposalReadyCheckBox.checked
|
||||
swapStore: SwapStore {
|
||||
readonly property var accounts: d.accountsModel
|
||||
readonly property var flatNetworks: d.flatNetworksModel
|
||||
|
@ -183,6 +186,25 @@ SplitView {
|
|||
model: d.tokenBySymbolModel
|
||||
currentIndex: 1
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
id: swapOutputAmount
|
||||
Layout.preferredWidth: 100
|
||||
label: "Token amount to receive"
|
||||
text: "100"
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: loadingCheckBox
|
||||
text: "swap proposal loading"
|
||||
checked: false
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: swapProposalReadyCheckBox
|
||||
text: "swap proposal ready"
|
||||
checked: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -385,5 +385,64 @@ Item {
|
|||
networkComboBox.control.popup.close()
|
||||
closeAndVerfyModal()
|
||||
}
|
||||
|
||||
function test_edit_slippage() {
|
||||
// by default the max slippage button should show no values and the edit button shouldnt be visible
|
||||
|
||||
// Launch popup
|
||||
launchAndVerfyModal()
|
||||
|
||||
// test default values for the various footer items for slippage
|
||||
const maxSlippageText = findChild(controlUnderTest, "maxSlippageText")
|
||||
verify(!!maxSlippageText)
|
||||
compare(maxSlippageText.text, qsTr("Max slippage:"))
|
||||
|
||||
const maxSlippageValue = findChild(controlUnderTest, "maxSlippageValue")
|
||||
verify(!!maxSlippageValue)
|
||||
|
||||
const editSlippageButton = findChild(controlUnderTest, "editSlippageButton")
|
||||
verify(!!editSlippageButton)
|
||||
|
||||
const editSlippagePanel = findChild(controlUnderTest, "editSlippagePanel")
|
||||
verify(!!editSlippagePanel)
|
||||
verify(!editSlippagePanel.visible)
|
||||
|
||||
// set swap proposal to ready and check state of the edit slippage buttons and max slippage values
|
||||
root.swapAdaptor.swapProposalReady = true
|
||||
compare(maxSlippageValue.text, "%1%".arg(0.5))
|
||||
verify(editSlippageButton.visible)
|
||||
|
||||
// clicking on editSlippageButton should show the edit slippage panel
|
||||
mouseClick(editSlippageButton)
|
||||
verify(!editSlippageButton.visible)
|
||||
verify(editSlippagePanel.visible)
|
||||
|
||||
const slippageSelector = findChild(editSlippagePanel, "slippageSelector")
|
||||
verify(!!slippageSelector)
|
||||
|
||||
verify(slippageSelector.valid)
|
||||
compare(slippageSelector.value, 0.5)
|
||||
|
||||
const buttonsRepeater = findChild(slippageSelector, "buttonsRepeater")
|
||||
verify(!!buttonsRepeater)
|
||||
waitForRendering(buttonsRepeater)
|
||||
|
||||
for(let i =0; i< buttonsRepeater.count; i++) {
|
||||
let buttonUnderTest = buttonsRepeater.itemAt(i)
|
||||
verify(!!buttonUnderTest)
|
||||
|
||||
// the mouseClick(buttonUnderTest) doesnt seem to work
|
||||
buttonUnderTest.clicked()
|
||||
|
||||
verify(slippageSelector.valid)
|
||||
compare(slippageSelector.value, buttonUnderTest.value)
|
||||
|
||||
compare(maxSlippageValue.text, "%1%".arg(buttonUnderTest.value))
|
||||
}
|
||||
|
||||
const signButton = findChild(controlUnderTest, "signButton")
|
||||
verify(!!signButton)
|
||||
verify(signButton.enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ Column {
|
|||
|
||||
property real topPadding: 0
|
||||
property real bottomPadding: 0
|
||||
property alias dividerColor: divider.color
|
||||
|
||||
width: 480
|
||||
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import shared.controls 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
Control {
|
||||
id: root
|
||||
|
||||
property bool loading
|
||||
property var selectedToToken
|
||||
property string toTokenAmount
|
||||
property alias slippageValue: slippageSelector.value
|
||||
property alias valid: slippageSelector.valid
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property string selectedToTokenSymbol: !!root.selectedToToken && !!root.selectedToToken.symbol ?
|
||||
root.selectedToToken.symbol : ""
|
||||
}
|
||||
|
||||
horizontalPadding: Style.current.padding
|
||||
verticalPadding: Style.current.bigPadding
|
||||
|
||||
background: Rectangle {
|
||||
radius: 16
|
||||
border.width: 1
|
||||
border.color: Theme.palette.directColor8
|
||||
color: Theme.palette.indirectColor3
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
id: baseLayout
|
||||
spacing: Style.current.bigPadding
|
||||
RowLayout {
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Slippage tolerance")
|
||||
font.weight: Font.Medium
|
||||
lineHeight: button.implicitHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
StatusLinkText {
|
||||
id: button
|
||||
visible: slippageSelector.isEdited
|
||||
text: qsTr("Use default")
|
||||
normalColor: Theme.palette.primaryColor1
|
||||
onClicked: slippageSelector.reset()
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -12
|
||||
text: qsTr("Maximum deviation in price due to market volatility and liquidity allowed before the swap is cancelled. (0.5% default).")
|
||||
wrapMode: Text.Wrap
|
||||
color: Theme.palette.directColor5
|
||||
}
|
||||
/* TODO: error conditions for custom enteries missing will be done under -
|
||||
https://github.com/status-im/status-desktop/issues/15017 */
|
||||
SlippageSelector {
|
||||
id: slippageSelector
|
||||
objectName: "slippageSelector"
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
StatusModalDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 0
|
||||
Layout.bottomMargin: -Style.current.smallPadding
|
||||
dividerColor: Theme.palette.directColor8
|
||||
}
|
||||
RowLayout {
|
||||
spacing: 4
|
||||
StatusBaseText {
|
||||
text: qsTr("Receive at least")
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
StatusSmartIdenticon {
|
||||
Layout.preferredWidth: Style.current.padding
|
||||
Layout.preferredHeight: Style.current.padding
|
||||
asset.name: !!root.selectedToToken && !!root.selectedToToken.image
|
||||
? root.selectedToToken.image
|
||||
: Constants.tokenIcon(d.selectedToTokenSymbol)
|
||||
asset.isImage: true
|
||||
}
|
||||
StatusTextWithLoadingState {
|
||||
text: {
|
||||
let amount = parseFloat(root.toTokenAmount)
|
||||
let percentageAmount = (amount - ((amount/100) * slippageSelector.value))
|
||||
return ("%1 %2").arg(LocaleUtils.numberToLocaleString(percentageAmount)).arg(d.selectedToTokenSymbol)
|
||||
}
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
loading: root.loading
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,3 +16,4 @@ CollectibleBalanceTag 1.0 CollectibleBalanceTag.qml
|
|||
ConnectedDappsButton 1.0 ConnectedDappsButton.qml
|
||||
CollectibleLinksTags 1.0 CollectibleLinksTags.qml
|
||||
SwapExchangeButton 1.0 SwapExchangeButton.qml
|
||||
EditSlippagePanel 1.0 EditSlippagePanel.qml
|
||||
|
|
|
@ -7,7 +7,8 @@ QtObject {
|
|||
property int selectedAccountIndex: 0
|
||||
property int selectedNetworkChainId: -1
|
||||
property string fromTokensKey: ""
|
||||
property string fromTokenAmount: ""
|
||||
property string fromTokenAmount: "0"
|
||||
property string toTokenKey: ""
|
||||
property string toTokenAmount
|
||||
property string toTokenAmount: "0"
|
||||
property double selectedSlippage: 0.5
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQml.Models 2.15
|
||||
|
||||
import utils 1.0
|
||||
|
||||
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
|
||||
|
||||
|
@ -24,11 +25,15 @@ StatusDialog {
|
|||
|
||||
implicitWidth: 556
|
||||
topPadding: 0
|
||||
bottomPadding: Style.current.padding
|
||||
bottomPadding: Style.current.xlPadding
|
||||
leftPadding: Style.current.xlPadding
|
||||
rightPadding: Style.current.xlPadding
|
||||
backgroundColor: Theme.palette.baseColor3
|
||||
|
||||
Behavior on implicitHeight {
|
||||
NumberAnimation { duration: 1000; easing.type: Easing.OutExpo; alwaysRunToEnd: true}
|
||||
}
|
||||
|
||||
header: AccountsModalHeader {
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: -height - 18
|
||||
|
@ -46,6 +51,7 @@ StatusDialog {
|
|||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 5
|
||||
clip: true
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
@ -100,7 +106,90 @@ StatusDialog {
|
|||
text: qsTr("Selected to token: %1").arg(swapInputParamsForm.toTokenKey)
|
||||
}
|
||||
StatusBaseText {
|
||||
text: qsTr("Selected network chainId: %1").arg(swapInputParamsForm.selectedNetworkChainId)
|
||||
text: qsTr("to token amount: %1").arg(swapInputParamsForm.toTokenAmount)
|
||||
}
|
||||
// End temporary placeholders
|
||||
|
||||
EditSlippagePanel {
|
||||
id: editSlippagePanel
|
||||
objectName: "editSlippagePanel"
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.padding
|
||||
visible: editSlippageButton.checked
|
||||
selectedToToken: root.swapAdaptor.toToken
|
||||
toTokenAmount: root.swapInputParamsForm.toTokenAmount
|
||||
loading: root.swapAdaptor.swapProposalLoading
|
||||
onSlippageValueChanged: {
|
||||
root.swapInputParamsForm.selectedSlippage = slippageValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
text:qsTr("Max fees:")
|
||||
color: Theme.palette.directColor5
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
StatusTextWithLoadingState {
|
||||
text: loading ? Constants.dummyText : "--"
|
||||
customColor: Theme.palette.directColor4
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Medium
|
||||
loading: root.swapAdaptor.swapProposalLoading
|
||||
}
|
||||
}
|
||||
StatusButton {
|
||||
objectName: "signButton"
|
||||
/* TODO: there maybe a different icon shown here in case of approval of spending cap
|
||||
needed TBD under https://github.com/status-im/status-desktop/issues/14833 */
|
||||
icon.name: "password"
|
||||
text: qsTr("Swap")
|
||||
disabledColor: Theme.palette.directColor8
|
||||
enabled: root.swapAdaptor.swapProposalReady && editSlippagePanel.valid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,15 @@ QObject {
|
|||
required property WalletStore.SwapStore swapStore
|
||||
required property SwapInputParamsForm swapFormData
|
||||
|
||||
/* TODO: link to the actually api to get swap proposal from backend under
|
||||
https://github.com/status-im/status-desktop/issues/14828 */
|
||||
property bool swapProposalReady: false
|
||||
property bool swapProposalLoading: false
|
||||
|
||||
// To expose the selected from and to Token from the SwapModal
|
||||
readonly property var fromToken: ModelUtils.getByKey(root.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel, "key", root.swapFormData.fromTokensKey)
|
||||
readonly property var toToken: ModelUtils.getByKey(root.walletAssetsStore.walletTokensStore.plainTokensBySymbolModel, "key", root.swapFormData.toTokenKey)
|
||||
|
||||
readonly property var nonWatchAccounts: SortFilterProxyModel {
|
||||
sourceModel: root.swapStore.accounts
|
||||
filters: ValueFilter {
|
||||
|
@ -33,7 +42,7 @@ QObject {
|
|||
},
|
||||
FastExpressionRole {
|
||||
name: "fromToken"
|
||||
expression: root.__fromToken
|
||||
expression: root.fromToken
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ Control {
|
|||
property double value: d.defaultValue
|
||||
readonly property bool valid: customInput.activeFocus && customInput.valid
|
||||
|| buttons.value !== null
|
||||
readonly property bool isEdited: root.value !== d.defaultValue
|
||||
|
||||
function reset() {
|
||||
value = d.defaultValue
|
||||
|
|
Loading…
Reference in New Issue