import QtQuick 2.15 import QtQuick.Layouts 1.15 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 shared.stores 1.0 as SharedStores import shared.stores.send 1.0 as SharedSendStores import "../controls" Item { id: root property SharedSendStores.TransactionStore store readonly property SharedStores.CurrenciesStore 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 var fromNetworksList property var toNetworksList property int errorType: Constants.NoError property bool isLoading QtObject { id: d property double customAmountToSend: 0 // Collectibles don't have a symbol readonly property string selectedSymbol: !!selectedAsset && !!selectedAsset.symbol ? 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: %1").arg(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: Theme.svg(model.iconUrl) disabledText: qsTr("Disabled") disableText: qsTr("Disable") enableText: qsTr("Enable") advancedMode: root.customMode disabled: !model.isRouteEnabled clickable: root.interactive onClicked: { store.toggleFromDisabledChains(model.chainId) store.lockCard(model.chainId, 0, false) root.reCalculateSuggestedRoute() } onLockCard: { let amount = lock ? (advancedInputCurrencyAmount * Math.pow(10, root.selectedAsset.decimals)).toString(16) : "" store.lockCard(model.chainId, amount, lock) d.calculateCustomAmounts() root.reCalculateSuggestedRoute() } } } } BalanceExceeded { Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter 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: root.toNetworksList StatusCard { id: toCard locale: LocaleUtils.userInputLocale objectName: model.chainId property bool preferred: model.isRoutePreferred 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: Theme.svg(model.iconUrl) disabledText: qsTr("Disabled") disableText: qsTr("Disable") enableText: qsTr("Enable") disabled: !model.isRouteEnabled clickable: root.interactive loading: root.isLoading onClicked: { store.toggleToDisabledChains(model.chainId) 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 || !fromN.hasGas ? 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() } } }