import QtQuick 2.13 import QtQuick.Layouts 1.13 import utils 1.0 import StatusQ.Controls 0.1 import StatusQ.Popups 0.1 import StatusQ.Components 0.1 import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 import StatusQ.Core.Utils 0.1 as StatusQUtils import "../controls" Item { id: root property var store readonly property var currencyStore: store.currencyStore property string receiverIdentityText property var selectedAsset property bool customMode: false property double amountToSend property int minSendCryptoDecimals: 0 property int minReceiveCryptoDecimals: 0 property bool errorMode: d.customAmountToSend > root.amountToSend property bool interactive: true property var weiToEth: function(wei) {} property var reCalculateSuggestedRoute: function() {} property int errorType: Constants.NoError property bool isLoading QtObject { id: d property double customAmountToSend: 0 readonly property string selectedSymbol: !!selectedAsset ? selectedAsset.symbol : "" function resetAllSetValues() { for(var i = 0; i 0) ? qsTr("No Balance") : !model.hasGas ? qsTr("No Gas") : root.currencyStore.formatCurrencyAmount(advancedInputCurrencyAmount, d.selectedSymbol, {"minDecimals": root.minSendCryptoDecimals}) tertiaryText: root.errorMode && advancedInputCurrencyAmount > 0 ? qsTr("EXCEEDS SEND AMOUNT"): qsTr("BALANCE: ") + root.currencyStore.formatCurrencyAmount(model.tokenBalance.amount, d.selectedSymbol) locked: model.locked preCalculatedAdvancedText: { if(locked && model.lockedAmount) { let amount = root.weiToEth(parseInt(model.lockedAmount, 16)) return LocaleUtils.numberToLocaleString(amount, -1, LocaleUtils.userInputLocale) } else return LocaleUtils.numberToLocaleString(root.weiToEth(model.amountIn), -1, LocaleUtils.userInputLocale) } maxAdvancedValue: tokenBalance.amount state: (model.tokenBalance.amount === 0 && root.amountToSend > 0) || !model.hasGas ? "unavailable" : (root.errorMode || !advancedInput.valid) && advancedInputCurrencyAmount > 0 ? "error" : "default" cardIcon.source: Style.svg(model.iconUrl) disabledText: qsTr("Disabled") disableText: qsTr("Disable") enableText: qsTr("Enable") advancedMode: root.customMode disabled: !model.isEnabled clickable: root.interactive onClicked: { store.toggleFromDisabledChains(model.chainId) // only recalculate if the a best route was disabled if(!!model.toNetworks || !disabled) root.reCalculateSuggestedRoute() } onLockCard: { let amount = lock ? (advancedInputCurrencyAmount * Math.pow(10, root.selectedAsset.decimals)).toString(16) : "" store.lockCard(model.chainId, amount, lock) d.calculateCustomAmounts() if(!locked || (d.customAmountToSend <= root.amountToSend && advancedInput.valid)) root.reCalculateSuggestedRoute() } } } } BalanceExceeded { Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter amountToSend: root.amountToSend errorType: root.errorType visible: root.errorType === Constants.NoRoute } ColumnLayout { id: toNetworksLayout Layout.alignment: Qt.AlignRight | Qt.AlignTop spacing: 12 RowLayout { Layout.alignment: Qt.AlignRight | Qt.AlignTop Layout.maximumWidth: 160 StatusBaseText { id: receiverIdentityText text: root.receiverIdentityText Layout.fillWidth: true font.pixelSize: 10 color: Theme.palette.baseColor1 elide: Text.ElideMiddle horizontalAlignment: Text.AlignRight } StatusBaseText { font.pixelSize: receiverIdentityText.font.pixelSize color: receiverIdentityText.color text: qsTr("WILL RECEIVE") } } Repeater { id: toNetworksRepeater model: store.toNetworksModel StatusCard { id: toCard locale: LocaleUtils.userInputLocale objectName: model.chainId property bool preferred: model.isPreferred property int bentLine: 0 property int routeOnNetwork: 0 primaryText: model.chainName secondaryText: root.currencyStore.formatCurrencyAmount(root.weiToEth(model.amountOut), d.selectedSymbol, {"minDecimals": root.minReceiveCryptoDecimals}) tertiaryText: state === "unpreferred" ? qsTr("UNPREFERRED") : "" state: !preferred ? "unpreferred" : "default" opacity: preferred || store.showUnPreferredChains ? 1 : 0 cardIcon.source: Style.svg(model.iconUrl) disabledText: qsTr("Disabled") disableText: qsTr("Disable") enableText: qsTr("Enable") disabled: !model.isEnabled clickable: root.interactive loading: root.isLoading onClicked: { store.toggleToDisabledChains(model.chainId) // only recalculate if the a best route was disabled if(root.weiToEth(model.amountOut) > 0 || !disabled) root.reCalculateSuggestedRoute() } onOpacityChanged: { if(opacity === 0 && root.weiToEth(model.amountOut) > 0) root.reCalculateSuggestedRoute() } } } } } Canvas { id: canvas x: networkCardsLayout.x + fromNetworksLayout.x y: networkCardsLayout.y width: networkCardsLayout.width height: networkCardsLayout.height function clear() { if(available) { var ctx = getContext("2d"); if(ctx) ctx.reset() } } onPaint: { d.resetAllSetValues() // in case you are drawing multiple routes we need an offset so that the lines dont overlap let yOffsetFrom = 0 let yOffsetTo = 0 let xOffset = 0 // Get the canvas context var ctx = getContext("2d"); for(var j = 0; j 0 ? -1 : 1) * toN.bentLine * 16 fromN.routeOnNetwork += 1 toN.routeOnNetwork += 1 toN.bentLine = toN.objectName !== fromN.objectName let routeColor = root.errorMode ? Theme.palette.dangerColor1 : toN.preferred ? '#627EEA' : Theme.palette.pinColor1 StatusQUtils.Utils.drawArrow(ctx, fromN.x + fromN.width, fromN.y + fromN.cardIconPosition + yOffsetFrom, toNetworksLayout.x + toN.x, toNetworksLayout.y + toN.y + toN.cardIconPosition + yOffsetTo, routeColor, xOffset) break } } } } d.calculateCustomAmounts() } } }