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 property var bestRoutes property var selectedAccount property var selectedAsset property var allNetworks property bool customMode: false property double amountToSend: 0 property double requiredGasInEth: 0 property bool errorMode: d.customAmountToSend > root.amountToSend property bool interactive: true property bool showPreferredChains: false property var weiToEth: function(wei) {} property var reCalculateSuggestedRoute: function() {} property int errorType: Constants.NoError property bool isLoading QtObject { id: d property double customAmountToSend: 0 property bool thereIsApossibleRoute: false function resetAllSetValues() { for(var i = 0; i lockedItem !== undefined && lockedItem.chainID === model.chainId) !== -1 preCalculatedAdvancedText: { let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem!== undefined && lockedItem.chainID === model.chainId) if(locked && index !== -1) { return root.weiToEth(parseInt(store.lockedInAmounts[index].value, 16)) } else return LocaleUtils.numberToLocaleString(fromNetwork.amountToSend) } maxAdvancedValue: tokenBalanceOnChain.amount state: tokenBalanceOnChain.amount === 0 || !hasGas ? "unavailable" : (root.errorMode || !advancedInput.valid) && (parseFloat(advancedInputText) !== 0) ? "error" : "default" cardIcon.source: Style.svg(model.iconUrl) disabledText: qsTr("Disabled") disableText: qsTr("Disable") enableText: qsTr("Enable") advancedMode: root.customMode disabled: store.disabledChainIdsFromList.includes(model.chainId) clickable: root.interactive onClicked: { store.addRemoveDisabledFromChain(model.chainId, disabled) // only recalculate if the a best route was disabled if(root.bestRoutes.length === 0 || routeOnNetwork !== 0 || !disabled) root.reCalculateSuggestedRoute() } onVisibleChanged: { if(visible) disabled = store.disabledChainIdsFromList.includes(model.chainId) } onCardLocked: { store.addLockedInAmount(model.chainId, advancedInputText, root.selectedAsset.decimals, isLocked) d.calculateCustomAmounts() if(!locked || (d.customAmountToSend <= root.amountToSend && advancedInput.valid)) root.reCalculateSuggestedRoute() } } } } BalanceExceeded { Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter amountToSend: root.amountToSend isLoading: root.isLoading errorType: root.errorType } ColumnLayout { id: toNetworksLayout Layout.alignment: Qt.AlignRight | Qt.AlignTop spacing: 12 StatusBaseText { Layout.alignment: Qt.AlignRight | Qt.AlignTop Layout.maximumWidth: 100 font.pixelSize: 10 color: Theme.palette.baseColor1 text: StatusQUtils.Utils.elideText(selectedAccount.address, 6, 4).toUpperCase() elide: Text.ElideMiddle } Repeater { id: toNetworksRepeater model: root.allNetworks StatusCard { id: toCard objectName: model.chainId property int routeOnNetwork: 0 property int bentLine: 0 property double amountToReceive: 0 property bool preferred: store.preferredChainIds.includes(model.chainId) primaryText: model.chainName secondaryText: LocaleUtils.numberToLocaleString(amountToReceive) tertiaryText: state === "unpreferred" ? qsTr("UNPREFERRED") : "" state: !preferred ? "unpreferred" : "default" opacity: preferred || showPreferredChains ? 1 : 0 cardIcon.source: Style.svg(model.iconUrl) disabledText: qsTr("Disabled") disableText: qsTr("Disable") enableText: qsTr("Enable") disabled: store.disabledChainIdsToList.includes(model.chainId) clickable: root.interactive onClicked: { store.addRemoveDisabledToChain(model.chainId, disabled) // only recalculate if the a best route was disabled if((root.bestRoutes !== undefined && root.bestRoutes.length === 0) || routeOnNetwork !== 0 || !disabled) root.reCalculateSuggestedRoute() } onVisibleChanged: { if(visible) { disabled = store.disabledChainIdsToList.includes(model.chainId) preferred = store.preferredChainIds.includes(model.chainId) } } onOpacityChanged: { if(opacity === 1) { disabled = store.disabledChainIdsToList.includes(model.chainId) } else { if(opacity === 0 && routeOnNetwork > 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() d.thereIsApossibleRoute = false if(bestRoutes === undefined) return // 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 i = 0; i< bestRoutes.length; i++) { var fromN, toN = null for(var j = 0; j 0 ? -1 : 1) * toN.bentLine * 16 let amountToSend = weiToEth(bestRoutes[i].amountIn) let amountToReceive = weiToEth(bestRoutes[i].amountOut) fromN.amountToSend = amountToSend toN.amountToReceive += amountToReceive fromN.routeOnNetwork += 1 toN.routeOnNetwork += 1 toN.bentLine = toN.objectName !== fromN.objectName d.thereIsApossibleRoute = true 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) } } d.calculateCustomAmounts() } } }