feat(@desktop/wallet): Implement the advanced/custom view with simple same network transfers
fixes #6268
This commit is contained in:
parent
4f3a6b46d3
commit
35a5ab57f0
|
@ -9,6 +9,7 @@ QtObject:
|
|||
type
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
all: Model
|
||||
enabled: Model
|
||||
layer1: Model
|
||||
layer2: Model
|
||||
|
@ -23,6 +24,7 @@ QtObject:
|
|||
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||
new(result, delete)
|
||||
result.delegate = delegate
|
||||
result.all = newModel()
|
||||
result.layer1 = newModel()
|
||||
result.layer2 = newModel()
|
||||
result.enabled = newModel()
|
||||
|
@ -41,6 +43,15 @@ QtObject:
|
|||
self.areTestNetworksEnabled = areTestNetworksEnabled
|
||||
self.areTestNetworksEnabledChanged()
|
||||
|
||||
proc allChanged*(self: View) {.signal.}
|
||||
|
||||
proc getAll(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.all)
|
||||
|
||||
QtProperty[QVariant] all:
|
||||
read = getAll
|
||||
notify = allChanged
|
||||
|
||||
proc layer1Changed*(self: View) {.signal.}
|
||||
|
||||
proc getLayer1(self: View): QVariant {.slot.} =
|
||||
|
@ -88,10 +99,12 @@ QtObject:
|
|||
balance,
|
||||
))
|
||||
|
||||
self.all.setItems(items)
|
||||
self.layer1.setItems(items.filter(i => i.getLayer() == 1))
|
||||
self.layer2.setItems(items.filter(i => i.getLayer() == 2))
|
||||
self.enabled.setItems(items.filter(i => i.getIsEnabled()))
|
||||
|
||||
self.allChanged()
|
||||
self.layer1Changed()
|
||||
self.layer2Changed()
|
||||
self.enabledChanged()
|
||||
|
|
|
@ -97,8 +97,8 @@ proc suggestedFees*(self: Controller, chainId: int): string =
|
|||
let suggestedFees = self.transactionService.suggestedFees(chainId)
|
||||
return suggestedFees.toJson()
|
||||
|
||||
proc suggestedRoutes*(self: Controller, account: string, amount: float64, token: string): string =
|
||||
let suggestedRoutes = self.transactionService.suggestedRoutes(account, amount, token)
|
||||
proc suggestedRoutes*(self: Controller, account: string, amount: float64, token: string, disabledChainIDs: seq[uint64]): string =
|
||||
let suggestedRoutes = self.transactionService.suggestedRoutes(account, amount, token, disabledChainIDs)
|
||||
return suggestedRoutes.toJson()
|
||||
|
||||
proc getChainIdForChat*(self: Controller): int =
|
||||
|
|
|
@ -55,7 +55,7 @@ method transactionWasSent*(self: AccessInterface, result: string) {.base.} =
|
|||
method suggestedFees*(self: AccessInterface, chainId: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method suggestedRoutes*(self: AccessInterface, account: string, amount: float64, token: string): string {.base.} =
|
||||
method suggestedRoutes*(self: AccessInterface, account: string, amount: float64, token: string, disabledChainIDs: seq[uint64]): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getChainIdForChat*(self: AccessInterface): int =
|
||||
|
|
|
@ -102,8 +102,8 @@ method transactionWasSent*(self: Module, result: string) =
|
|||
method suggestedFees*(self: Module, chainId: int): string =
|
||||
return self.controller.suggestedFees(chainId)
|
||||
|
||||
method suggestedRoutes*(self: Module, account: string, amount: float64, token: string): string =
|
||||
return self.controller.suggestedRoutes(account, amount, token)
|
||||
method suggestedRoutes*(self: Module, account: string, amount: float64, token: string, disabledChainIDs: seq[uint64]): string =
|
||||
return self.controller.suggestedRoutes(account, amount, token, disabledChainIDs)
|
||||
|
||||
method getChainIdForChat*(self: Module): int =
|
||||
return self.controller.getChainIdForChat()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NimQml, tables, stint, json, strformat, sequtils, strutils
|
||||
import NimQml, tables, stint, json, strformat, sequtils, strutils, sugar
|
||||
|
||||
import ./item
|
||||
import ./model
|
||||
|
@ -125,15 +125,22 @@ QtObject:
|
|||
proc suggestedFees*(self: View, chainId: int): string {.slot.} =
|
||||
return self.delegate.suggestedFees(chainId)
|
||||
|
||||
proc suggestedRoutes*(self: View, account: string, amount: string, token: string): string {.slot.} =
|
||||
proc suggestedRoutes*(self: View, account: string, amount: string, token: string, disabledChainIDs: string): string {.slot.} =
|
||||
var parsedAmount = 0.0
|
||||
var seqDisabledChainIds = seq[uint64] : @[]
|
||||
|
||||
try:
|
||||
for chainID in disabledChainIDs.split(','):
|
||||
seqDisabledChainIds.add(parseUInt(chainID))
|
||||
except:
|
||||
discard
|
||||
|
||||
try:
|
||||
parsedAmount = parsefloat(amount)
|
||||
except:
|
||||
discard
|
||||
|
||||
return self.delegate.suggestedRoutes(account, parsedAmount, token)
|
||||
return self.delegate.suggestedRoutes(account, parsedAmount, token, seqDisabledChainIds)
|
||||
|
||||
proc getChainIdForChat*(self: View): int {.slot.} =
|
||||
return self.delegate.getChainIdForChat()
|
||||
|
|
|
@ -111,3 +111,17 @@ QtObject:
|
|||
return true
|
||||
|
||||
return false
|
||||
|
||||
proc hasGas*(self: Model, chainId: int, nativeGasSymbol: string, requiredGas: float): bool {.slot.} =
|
||||
for item in self.items:
|
||||
if(item.getSymbol() != nativeGasSymbol):
|
||||
continue
|
||||
|
||||
for balance in item.getBalances().items:
|
||||
if (balance.chainId != chainId):
|
||||
continue
|
||||
|
||||
if(balance.balance >= requiredGas):
|
||||
return true
|
||||
|
||||
return false
|
||||
|
|
|
@ -369,8 +369,8 @@ QtObject:
|
|||
eip1559Enabled: response{"eip1559Enabled"}.getbool,
|
||||
)
|
||||
|
||||
proc suggestedRoutes*(self: Service, account: string, amount: float64, token: string): SuggestedRoutes =
|
||||
let response = eth.suggestedRoutes(account, amount, token)
|
||||
proc suggestedRoutes*(self: Service, account: string, amount: float64, token: string, disabledChainIDs: seq[uint64]): SuggestedRoutes =
|
||||
let response = eth.suggestedRoutes(account, amount, token, disabledChainIDs)
|
||||
return SuggestedRoutes(
|
||||
networks: Json.decode($response.result{"networks"}, seq[NetworkDto])
|
||||
)
|
||||
|
|
|
@ -28,6 +28,6 @@ proc suggestedFees*(chainId: int): RpcResponse[JsonNode] {.raises: [Exception].}
|
|||
let payload = %* [chainId]
|
||||
return core.callPrivateRPC("wallet_getSuggestedFees", payload)
|
||||
|
||||
proc suggestedRoutes*(account: string, amount: float64, token: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [account, amount, token]
|
||||
proc suggestedRoutes*(account: string, amount: float64, token: string, disabledChainIDs: seq[uint64]): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [account, amount, token, disabledChainIDs]
|
||||
return core.callPrivateRPC("wallet_getSuggestedRoutes", payload)
|
|
@ -1 +1 @@
|
|||
Subproject commit 8fc073a749c5499c4cd3f43bd3382e215476e1fa
|
||||
Subproject commit e0fd627050b45440132acce69c8c317f4efe129a
|
|
@ -6,6 +6,8 @@ import StatusQ.Core.Utils 0.1 as StatusQUtils
|
|||
QtObject {
|
||||
id: root
|
||||
|
||||
property string locale: localAppSettings.locale
|
||||
|
||||
property var contactsStore
|
||||
|
||||
property bool openCreateChat: false
|
||||
|
@ -473,6 +475,36 @@ QtObject {
|
|||
return userProfile.getPubKey()
|
||||
}
|
||||
|
||||
property var allNetworks: networksModule.all
|
||||
|
||||
property var disabledChainIds: []
|
||||
|
||||
function addRemoveDisabledChain(suggestedRoutes, chainID, isDisbaled) {
|
||||
if(isDisbaled) {
|
||||
for(var i = 0; i < suggestedRoutes.length;i++) {
|
||||
if(suggestedRoutes[i].chainId === chainID) {
|
||||
disabledChainIds.push(suggestedRoutes[i].chainId)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(var i = 0; i < disabledChainIds.length;i++) {
|
||||
if(disabledChainIds[i] === chainID) {
|
||||
disabledChainIds.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkIfDisabledByUser(chainID) {
|
||||
for(var i = 0; i < disabledChainIds.length;i++) {
|
||||
if(disabledChainIds[i] === chainID) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function getFiatValue(balance, cryptoSymbo, fiatSymbol) {
|
||||
return profileSectionModule.ensUsernamesModule.getFiatValue(balance, cryptoSymbo, fiatSymbol)
|
||||
}
|
||||
|
@ -526,7 +558,7 @@ QtObject {
|
|||
return JSON.parse(walletSectionTransactions.suggestedFees(chainId))
|
||||
}
|
||||
|
||||
function suggestedRoutes(account, amount, token) {
|
||||
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token)).networks
|
||||
function suggestedRoutes(account, amount, token, disabledChainIds) {
|
||||
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token, disabledChainIds)).networks
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ import "../Profile/stores"
|
|||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
property string locale: localAppSettings.locale
|
||||
|
||||
property var mainModuleInst: mainModule
|
||||
property var aboutModuleInst: aboutModule
|
||||
property var communitiesModuleInst: communitiesModule
|
||||
|
@ -66,9 +69,34 @@ QtObject {
|
|||
|
||||
property var walletSectionTransactionsInst: walletSectionTransactions
|
||||
|
||||
|
||||
property var savedAddressesModel: walletSectionSavedAddresses.model
|
||||
|
||||
property var allNetworks: networksModule.all
|
||||
|
||||
property var disabledChainIds: []
|
||||
|
||||
function addRemoveDisabledChain(suggestedRoutes, chainID, isDisbaled) {
|
||||
if(isDisbaled) {
|
||||
disabledChainIds.push(chainID)
|
||||
}
|
||||
else {
|
||||
for(var i = 0; i < disabledChainIds.length;i++) {
|
||||
if(disabledChainIds[i] === chainID) {
|
||||
disabledChainIds.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkIfDisabledByUser(chainID) {
|
||||
for(var i = 0; i < disabledChainIds.length;i++) {
|
||||
if(disabledChainIds[i] === chainID) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function getEtherscanLink() {
|
||||
return profileSectionModule.ensUsernamesModule.getEtherscanLink()
|
||||
}
|
||||
|
@ -125,8 +153,8 @@ QtObject {
|
|||
return walletSectionTransactions.getChainIdForBrowser()
|
||||
}
|
||||
|
||||
function suggestedRoutes(account, amount, token) {
|
||||
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token)).networks
|
||||
function suggestedRoutes(account, amount, token, disabledChainIds) {
|
||||
return JSON.parse(walletSectionTransactions.suggestedRoutes(account, amount, token, disabledChainIds)).networks
|
||||
}
|
||||
|
||||
function hex2Eth(value) {
|
||||
|
|
|
@ -33,7 +33,7 @@ StatusInput {
|
|||
|
||||
SequentialAnimation {
|
||||
loops: Animation.Infinite
|
||||
running: visible && input.edit.cursorVisible
|
||||
running: input.edit.cursorVisible
|
||||
|
||||
PropertyAction {
|
||||
target: cursor
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 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
|
||||
|
||||
ColumnLayout {
|
||||
id: balancedExceededError
|
||||
|
||||
property bool transferPossible: false
|
||||
property double amountToSend: 0
|
||||
|
||||
StatusIcon {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: !balancedExceededError.transferPossible && balancedExceededError.amountToSend > 0
|
||||
icon: "cancel"
|
||||
color: Theme.palette.dangerColor1
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
font.pixelSize: 15
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Theme.palette.dangerColor1
|
||||
text: balancedExceededError.amountToSend > 0 ? qsTr("Balance exceeded"): qsTr("No networks available")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
|
@ -189,7 +189,7 @@ Item {
|
|||
height: 16
|
||||
}
|
||||
StatusBaseText {
|
||||
text: currentContact.address
|
||||
text: currentContact.publicKey
|
||||
width: 85
|
||||
elide: Text.ElideMiddle
|
||||
color: Theme.palette.baseColor1
|
||||
|
|
|
@ -7,6 +7,7 @@ import shared.panels 1.0
|
|||
import shared.controls 1.0
|
||||
import shared.controls.chat 1.0
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
@ -14,7 +15,6 @@ Item {
|
|||
height: visible ? Style.current.smallPadding + prioritytext.height +
|
||||
(advancedMode ? advancedModeItemGroup.height : selectorButtons.height) : 0
|
||||
|
||||
|
||||
property var suggestedFees: ({
|
||||
eip1559Enabled: true
|
||||
})
|
||||
|
@ -30,7 +30,6 @@ Item {
|
|||
property int estimatedTxTimeFlag: Constants.transactionEstimatedTime.unknown
|
||||
property int chainId: 1
|
||||
|
||||
|
||||
property alias selectedTipLimit: inputPerGasTipLimit.text
|
||||
property alias selectedOverallLimit: inputGasPrice.text
|
||||
|
||||
|
@ -109,8 +108,8 @@ Item {
|
|||
}
|
||||
|
||||
function checkOptimal() {
|
||||
if (!optimalGasButton.gasRadioBtn.checked) {
|
||||
optimalGasButton.gasRadioBtn.toggle()
|
||||
if (!optimalGasButton.checked) {
|
||||
optimalGasButton.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,10 +190,13 @@ Item {
|
|||
color: Style.current.secondaryText
|
||||
}
|
||||
|
||||
StatusFlatButton {
|
||||
id: buttonAdvanced
|
||||
StatusButton {
|
||||
anchors.verticalCenter: prioritytext.verticalCenter
|
||||
anchors.right: parent.right
|
||||
height: 22
|
||||
defaultTopPadding: 2
|
||||
defaultBottomPadding: 2
|
||||
size: StatusBaseButton.Size.Tiny
|
||||
visible: root.suggestedFees.eip1559Enabled
|
||||
text: advancedMode ?
|
||||
qsTr("Use suggestions") :
|
||||
|
@ -210,24 +212,19 @@ Item {
|
|||
anchors.topMargin: Style.current.halfPadding
|
||||
spacing: 11
|
||||
|
||||
ButtonGroup {
|
||||
id: gasGroup
|
||||
onClicked: updateGasEthValue()
|
||||
}
|
||||
|
||||
GasSelectorButton {
|
||||
id: lowGasButton
|
||||
buttonGroup: gasGroup
|
||||
text: qsTr("Low")
|
||||
price: {
|
||||
if (!root.suggestedFees.eip1559Enabled) return root.suggestedFees.gasPrice;
|
||||
return formatDec(root.suggestedFees.maxFeePerGasL, 6)
|
||||
}
|
||||
primaryText: qsTr("Low")
|
||||
gasLimit: inputGasLimit ? inputGasLimit.text : ""
|
||||
getGasEthValue: root.getGasEthValue
|
||||
getFiatValue: root.getFiatValue
|
||||
defaultCurrency: root.defaultCurrency
|
||||
onChecked: {
|
||||
price: {
|
||||
if (!root.suggestedFees.eip1559Enabled) return root.suggestedFees.gasPrice;
|
||||
return formatDec(root.suggestedFees.maxFeePerGasL, 6)
|
||||
}
|
||||
onCheckedChanged: {
|
||||
if(checked) {
|
||||
if (root.suggestedFees.eip1559Enabled){
|
||||
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
|
||||
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasL, 2);
|
||||
|
@ -238,10 +235,11 @@ Item {
|
|||
root.checkLimits()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GasSelectorButton {
|
||||
id: optimalGasButton
|
||||
buttonGroup: gasGroup
|
||||
text: qsTr("Optimal")
|
||||
primaryText: qsTr("Optimal")
|
||||
price: {
|
||||
if (!root.suggestedFees.eip1559Enabled) {
|
||||
// Setting the gas price field here because the binding didn't work
|
||||
|
@ -255,7 +253,8 @@ Item {
|
|||
getGasEthValue: root.getGasEthValue
|
||||
getFiatValue: root.getFiatValue
|
||||
defaultCurrency: root.defaultCurrency
|
||||
onChecked: {
|
||||
onCheckedChanged: {
|
||||
if(checked) {
|
||||
if (root.suggestedFees.eip1559Enabled){
|
||||
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
|
||||
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasM, 2);
|
||||
|
@ -266,11 +265,11 @@ Item {
|
|||
root.checkLimits()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GasSelectorButton {
|
||||
id: highGasButton
|
||||
buttonGroup: gasGroup
|
||||
text: qsTr("High")
|
||||
primaryText: qsTr("High")
|
||||
price: {
|
||||
if (!root.suggestedFees.eip1559Enabled) return root.suggestedFees.gasPrice;
|
||||
return formatDec(root.suggestedFees.maxFeePerGasH,6);
|
||||
|
@ -279,7 +278,8 @@ Item {
|
|||
getGasEthValue: root.getGasEthValue
|
||||
getFiatValue: root.getFiatValue
|
||||
defaultCurrency: root.defaultCurrency
|
||||
onChecked: {
|
||||
onCheckedChanged: {
|
||||
if(checked) {
|
||||
if (root.suggestedFees.eip1559Enabled){
|
||||
inputPerGasTipLimit.text = formatDec(root.suggestedFees.maxPriorityFeePerGas, 2);
|
||||
inputGasPrice.text = formatDec(root.suggestedFees.maxFeePerGasH, 2);
|
||||
|
@ -291,6 +291,7 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: advancedModeItemGroup
|
||||
|
|
|
@ -1,95 +1,93 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQuick.Layouts 1.0
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
import shared.panels 1.0
|
||||
import shared.controls 1.0
|
||||
|
||||
// TODO: use StatusQ components
|
||||
Rectangle {
|
||||
property var buttonGroup
|
||||
property string text: qsTr("Low")
|
||||
StatusRadioButton {
|
||||
id: gasRectangle
|
||||
|
||||
property string primaryText: qsTr("Low")
|
||||
property string gasLimit
|
||||
property double price: 1
|
||||
property string defaultCurrency: "USD"
|
||||
property bool hovered: false
|
||||
property bool checkedByDefault: false
|
||||
property double price: 1
|
||||
property var getGasEthValue: function () {}
|
||||
property var getFiatValue: function () {}
|
||||
|
||||
property alias gasRadioBtn: gasRadioBtn
|
||||
|
||||
function formatDec(num, dec){
|
||||
return Math.round((num + Number.EPSILON) * Math.pow(10, dec)) / Math.pow(10, dec)
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property double fiatValue: getFiatValue(ethValue, "ETH", defaultCurrency)
|
||||
property double ethValue: {
|
||||
if (!gasLimit) {
|
||||
return 0
|
||||
}
|
||||
return formatDec(parseFloat(getGasEthValue(gasRectangle.price, gasLimit)), 6)
|
||||
}
|
||||
property double fiatValue: getFiatValue(ethValue, "ETH", defaultCurrency)
|
||||
signal checked()
|
||||
}
|
||||
|
||||
id: gasRectangle
|
||||
border.color: hovered || gasRadioBtn.checked ? Style.current.primary : Style.current.border
|
||||
border.width: 1
|
||||
color: Style.current.transparent
|
||||
width: 130
|
||||
height: 120
|
||||
clip: true
|
||||
radius: Style.current.radius
|
||||
width: contentItem.implicitWidth
|
||||
|
||||
StatusRadioButton {
|
||||
id: gasRadioBtn
|
||||
ButtonGroup.group: buttonGroup
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
// To-do Use StatusCard instead. It crashes if I use StatusCard and
|
||||
// already spent 2 days on this, so leaving it out for now
|
||||
contentItem: Rectangle {
|
||||
id: card
|
||||
|
||||
implicitHeight: 76
|
||||
implicitWidth: 128
|
||||
|
||||
radius: 8
|
||||
color: gasRectangle.checked || mouseArea.containsMouse ? "transparent": Theme.palette.baseColor4
|
||||
border.color: gasRectangle.checked || mouseArea.containsMouse ? Theme.palette.primaryColor2: Theme.palette.baseColor4
|
||||
|
||||
ColumnLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 14
|
||||
checked: gasRectangle.checkedByDefault
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
gasRectangle.checked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: gasText
|
||||
text: gasRectangle.text
|
||||
anchors.leftMargin: 8
|
||||
anchors.rightMargin: 8
|
||||
anchors.topMargin: 8
|
||||
StatusBaseText {
|
||||
id: primaryText
|
||||
font.pixelSize: 15
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: gasRadioBtn.bottom
|
||||
anchors.topMargin: 6
|
||||
font.weight: Font.Medium
|
||||
elide: Text.ElideRight
|
||||
text: gasRectangle.primaryText
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: ethText
|
||||
text: gasRectangle.ethValue + " ETH"
|
||||
StatusBaseText {
|
||||
id: secondaryLabel
|
||||
font.pixelSize: 13
|
||||
color: Style.current.secondaryText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: gasText.bottom
|
||||
anchors.topMargin: 4
|
||||
font.weight: Font.Medium
|
||||
text: d.ethValue + " ETH"
|
||||
color: Theme.palette.primaryColor1
|
||||
}
|
||||
StatusBaseText {
|
||||
id: tertiaryText
|
||||
font.pixelSize: 10
|
||||
text: d.fiatValue + " " + gasRectangle.defaultCurrency.toUpperCase()
|
||||
color: Theme.palette.directColor5
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: fiatText
|
||||
text: `${gasRectangle.fiatValue} ${gasRectangle.defaultCurrency}`
|
||||
font.pixelSize: 13
|
||||
color: Style.current.secondaryText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: ethText.bottom
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onEntered: gasRectangle.hovered = true
|
||||
onExited: gasRectangle.hovered = false
|
||||
onClicked: gasRadioBtn.toggle()
|
||||
onClicked: gasRectangle.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
indicator: Item {
|
||||
width:card.width
|
||||
height: card.height
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,9 +54,10 @@ StatusModal {
|
|||
)
|
||||
}
|
||||
|
||||
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
|
||||
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function(disabledChainIds) {
|
||||
if (disabledChainIds === undefined) disabledChainIds = []
|
||||
networkSelector.suggestedRoutes = popup.store.suggestedRoutes(
|
||||
popup.selectedAccount.address, amountToSendInput.text, assetSelector.selectedAsset.symbol
|
||||
popup.selectedAccount.address, amountToSendInput.text, assetSelector.selectedAsset.symbol, disabledChainIds
|
||||
)
|
||||
if (networkSelector.suggestedRoutes.length) {
|
||||
networkSelector.selectedNetwork = networkSelector.suggestedRoutes[0]
|
||||
|
@ -73,6 +74,7 @@ StatusModal {
|
|||
id: d
|
||||
readonly property string maxFiatBalance: Utils.stripTrailingZeros(parseFloat(assetSelector.selectedAsset.totalBalance).toFixed(4))
|
||||
readonly property bool isReady: amountToSendInput.valid && !amountToSendInput.pending && recipientSelector.isValid && !recipientSelector.isPending
|
||||
readonly property bool errorMode: networkSelector.suggestedRoutes && networkSelector.suggestedRoutes.length <= 0 || networkSelector.errorMode
|
||||
onIsReadyChanged: {
|
||||
if(!isReady && stack.isLastGroup)
|
||||
stack.back()
|
||||
|
@ -83,7 +85,7 @@ StatusModal {
|
|||
height: 595
|
||||
showHeader: false
|
||||
showFooter: false
|
||||
showAdvancedFooter: d.isReady && gasValidator.isValid
|
||||
showAdvancedFooter: d.isReady && !isNaN(parseFloat(amountToSendInput.text)) && gasValidator.isValid
|
||||
showAdvancedHeader: true
|
||||
|
||||
onSelectedAccountChanged: popup.recalculateRoutesAndFees()
|
||||
|
@ -91,12 +93,6 @@ StatusModal {
|
|||
onOpened: {
|
||||
amountToSendInput.input.edit.forceActiveFocus()
|
||||
|
||||
assetSelector.assets = Qt.binding(function() {
|
||||
if (popup.selectedAccount) {
|
||||
return popup.selectedAccount.assets
|
||||
}
|
||||
})
|
||||
|
||||
if(popup.launchedFromChat) {
|
||||
recipientSelector.selectedType = RecipientSelector.Type.Contact
|
||||
recipientSelector.readOnly = true
|
||||
|
@ -145,6 +141,8 @@ StatusModal {
|
|||
titleText.font.pixelSize: 12
|
||||
Layout.preferredHeight: 22
|
||||
Layout.preferredWidth: childrenRect.width
|
||||
color: d.errorMode ? Theme.palette.dangerColor2 : Theme.palette.primaryColor3
|
||||
titleText.color: d.errorMode ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
Item {
|
||||
|
@ -157,6 +155,7 @@ StatusModal {
|
|||
width: parent.width - assetSelector.width
|
||||
input.placeholderText: "0.00" + " " + assetSelector.selectedAsset.symbol
|
||||
errorMessageCmp.anchors.rightMargin: -100
|
||||
input.edit.color: d.errorMode ? Theme.palette.dangerColor1 : Theme.palette.directColor1
|
||||
validators: [
|
||||
StatusFloatValidator{
|
||||
id: floatValidator
|
||||
|
@ -184,6 +183,7 @@ StatusModal {
|
|||
id: assetSelector
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
assets: popup.selectedAccount.assets
|
||||
defaultToken: Style.png("tokens/DEFAULT-TOKEN@3x")
|
||||
getCurrencyBalanceString: function (currencyBalance) {
|
||||
return Utils.toLocaleString(currencyBalance.toFixed(2), popup.store.locale, {"currency": true}) + " " + popup.store.currentCurrency.toUpperCase()
|
||||
|
@ -269,12 +269,12 @@ StatusModal {
|
|||
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
contentHeight: recipientSelector.height + addressSelector.height + networkSelector.height + gasSelector.height + gasValidator.height
|
||||
contentHeight: recipientSelector.height + addressSelector.height + networkSelector.height + fees.height + Style.current.halfPadding
|
||||
clip: true
|
||||
|
||||
// To-do use standard StatusInput component once the flow for ens name resolution is clear
|
||||
RecipientSelector {
|
||||
anchors.top: assetAndAmmountSelector.bottom
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.current.halfPadding
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
|
@ -308,24 +308,53 @@ StatusModal {
|
|||
|
||||
NetworkSelector {
|
||||
id: networkSelector
|
||||
store: popup.store
|
||||
selectedAccount: popup.selectedAccount
|
||||
anchors.top: addressSelector.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
amountToSend: isNaN(parseFloat(amountToSendInput.text)) ? 0 : parseFloat(amountToSendInput.text)
|
||||
requiredGasInEth: gasSelector.selectedGasEthValue
|
||||
assets: popup.selectedAccount.assets
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
onNetworkChanged: function(chainId) {
|
||||
gasSelector.suggestedFees = popup.store.suggestedFees(chainId)
|
||||
gasSelector.updateGasEthValue()
|
||||
}
|
||||
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees(disabledChainIds)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: fees
|
||||
radius: 13
|
||||
color: Theme.palette.indirectColor1
|
||||
anchors.top: networkSelector.bottom
|
||||
width: parent.width
|
||||
height: gasSelector.visible || gasValidator.visible ? feesLayout.height + gasValidator.height : 0
|
||||
|
||||
RowLayout {
|
||||
id: feesLayout
|
||||
spacing: 10
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.margins: Style.current.padding
|
||||
|
||||
StatusRoundIcon {
|
||||
id: feesIcon
|
||||
Layout.alignment: Qt.AlignTop
|
||||
radius: 8
|
||||
icon.name: "fees"
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
GasSelector {
|
||||
id: gasSelector
|
||||
anchors.top: networkSelector.bottom
|
||||
Layout.preferredWidth: fees.width - feesIcon.width - Style.current.xlPadding
|
||||
getGasEthValue: popup.store.getGasEthValue
|
||||
getFiatValue: popup.store.getFiatValue
|
||||
getEstimatedTime: popup.store.getEstimatedTime
|
||||
defaultCurrency: popup.store.currentCurrency
|
||||
chainId: networkSelector.selectedNetwork.chainId
|
||||
width: stack.width
|
||||
chainId: networkSelector.selectedNetwork && networkSelector.selectedNetwork.chainId ? networkSelector.selectedNetwork.chainId : 1
|
||||
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
|
||||
if (!(popup.selectedAccount && popup.selectedAccount.address &&
|
||||
recipientSelector.selectedRecipient && recipientSelector.selectedRecipient.address &&
|
||||
|
@ -336,17 +365,19 @@ StatusModal {
|
|||
return
|
||||
}
|
||||
|
||||
var chainID = networkSelector.selectedNetwork ? networkSelector.selectedNetwork.chainId: 1
|
||||
|
||||
let gasEstimate = JSON.parse(popup.store.estimateGas(
|
||||
popup.selectedAccount.address,
|
||||
recipientSelector.selectedRecipient.address,
|
||||
assetSelector.selectedAsset.symbol,
|
||||
amountToSendInput.text,
|
||||
networkSelector.selectedNetwork.chainId || Global.currentChainId,
|
||||
chainID || Global.currentChainId,
|
||||
""))
|
||||
|
||||
if (!gasEstimate.success) {
|
||||
|
||||
console.warn(qsTr("Error estimating gas: %1").arg(gasEstimate.error.message))
|
||||
console.warn(qsTrId("error-estimating-gas---1").arg(gasEstimate.error.message))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -354,16 +385,19 @@ StatusModal {
|
|||
defaultGasLimit = selectedGasLimit
|
||||
})
|
||||
}
|
||||
|
||||
GasValidator {
|
||||
id: gasValidator
|
||||
anchors.top: gasSelector.bottom
|
||||
anchors.horizontalCenter: undefined
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
selectedAccount: popup.selectedAccount
|
||||
selectedAmount: amountToSendInput.text === "" ? 0.0
|
||||
: parseFloat(amountToSendInput.text)
|
||||
selectedAmount: amountToSendInput.text === "" ? 0.0 :
|
||||
parseFloat(amountToSendInput.text)
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
selectedGasEthValue: gasSelector.selectedGasEthValue
|
||||
selectedNetwork: networkSelector.selectedNetwork
|
||||
selectedNetwork: networkSelector.selectedNetwork ? networkSelector.selectedNetwork: null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
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
|
||||
|
||||
Item {
|
||||
id: networkCardsComponent
|
||||
|
||||
property var assets
|
||||
property var store
|
||||
property string locale: ""
|
||||
property var selectedAsset
|
||||
property var suggestedRoutes
|
||||
property bool customMode: false
|
||||
property var selectedNetwork
|
||||
property var selectedAccount
|
||||
property var allNetworks
|
||||
property double amountToSend: 0
|
||||
property double requiredGasInEth: 0
|
||||
property bool errorMode: (d.customAmountToSend > amountToSend) ||
|
||||
(d.customAmountToSend < amountToSend) ||
|
||||
(d.customAmountToReceive > amountToSend) ||
|
||||
(d.customAmountToReceive < amountToSend)
|
||||
|
||||
signal reCalculateSuggestedRoute(var disabled)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property var selectedFromNetwork
|
||||
property var selectedToNetwork
|
||||
property double customAmountToSend: 0
|
||||
property double customAmountToReceive: 0
|
||||
|
||||
function getBalance(chainID) {
|
||||
for(var i=0; i< selectedAsset.balances.count; i++) {
|
||||
if(selectedAsset.balances.rowData(i, "chainId") === chainID.toString()) {
|
||||
return selectedAsset.balances.rowData(i, "balance")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSelectedFromNetworkChanged: {
|
||||
canvas.clear()
|
||||
canvas.requestPaint()
|
||||
}
|
||||
|
||||
onSelectedToNetworkChanged: {
|
||||
canvas.clear()
|
||||
canvas.requestPaint()
|
||||
}
|
||||
}
|
||||
|
||||
width: 410
|
||||
height: networkCardsLayout.height
|
||||
|
||||
RowLayout {
|
||||
id: networkCardsLayout
|
||||
width: parent.width
|
||||
ColumnLayout {
|
||||
id: fromNetworksLayout
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
spacing: 12
|
||||
StatusBaseText {
|
||||
font.pixelSize: 10
|
||||
color: Theme.palette.baseColor1
|
||||
text: qsTr("Your Balances").toUpperCase()
|
||||
}
|
||||
Repeater {
|
||||
model: networkCardsComponent.allNetworks
|
||||
StatusCard {
|
||||
id: fromNetwork
|
||||
property var tokenBalanceOnChain: Utils.toLocaleString(parseFloat(d.getBalance(model.chainId)).toFixed(4), locale, {"currency": true})
|
||||
property var hasGas: assets.hasGas(model.chainId, model.nativeCurrencySymbol, requiredGasInEth + parseFloat(amountToSend))
|
||||
primaryText: model.chainName
|
||||
secondaryText: (parseFloat(tokenBalanceOnChain) === 0 && amountToSend !== 0) ?
|
||||
qsTr("No Balance") : !hasGas ? qsTr("No Gas") :
|
||||
(selectedNetwork && selectedNetwork.chainName === model.chainName) ?
|
||||
amountToSend: 0
|
||||
tertiaryText: qsTr("BALANCE: ") + tokenBalanceOnChain
|
||||
state: tokenBalanceOnChain === 0 || !hasGas ? "unavailable" : networkCardsComponent.errorMode ? "error" : "default"
|
||||
cardIcon.source: Style.png(model.iconUrl)
|
||||
disabledText: qsTr("Disabled")
|
||||
advancedMode: networkCardsComponent.customMode
|
||||
advancedInputText: (selectedNetwork && selectedNetwork.chainName === model.chainName) ? amountToSend: 0
|
||||
Component.onCompleted: {
|
||||
disabled = store.checkIfDisabledByUser(model.chainId)
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName)
|
||||
d.selectedFromNetwork = this
|
||||
}
|
||||
Connections {
|
||||
target: networkCardsComponent
|
||||
onSelectedNetworkChanged: {
|
||||
if(selectedNetwork.chainName === model.chainName) {
|
||||
d.selectedFromNetwork = fromNetwork
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
store.addRemoveDisabledChain(suggestedRoutes, model.chainId, disabled)
|
||||
reCalculateSuggestedRoute(store.disabledChainIds)
|
||||
}
|
||||
onAdvancedInputTextChanged: {
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName) {
|
||||
d.customAmountToSend = isNaN(parseFloat(advancedInputText)) ? 0 : parseFloat(advancedInputText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
id: toNetworksLayout
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignTop
|
||||
spacing: 12
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.maximumWidth: 70
|
||||
font.pixelSize: 10
|
||||
color: Theme.palette.baseColor1
|
||||
text: selectedAccount.address
|
||||
elide: Text.ElideMiddle
|
||||
}
|
||||
Repeater {
|
||||
model: networkCardsComponent.allNetworks
|
||||
StatusCard {
|
||||
id: toCard
|
||||
primaryText: model.chainName
|
||||
secondaryText: (selectedNetwork && selectedNetwork.chainName === model.chainName) ? amountToSend: 0
|
||||
tertiaryText: ""
|
||||
// To-do preferred in not something that is supported yet
|
||||
state: networkCardsComponent.errorMode ? "error" : "default"
|
||||
// opacity: preferred ? 1 : 0
|
||||
cardIcon.source: Style.png(model.iconUrl)
|
||||
disabledText: qsTr("Disabled")
|
||||
advancedMode: networkCardsComponent.customMode
|
||||
advancedInputText: (selectedNetwork && selectedNetwork.chainName === model.chainName) ? amountToSend: 0
|
||||
Component.onCompleted: {
|
||||
disabled = store.checkIfDisabledByUser(model.chainId)
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName)
|
||||
d.selectedToNetwork = this
|
||||
}
|
||||
Connections {
|
||||
target: networkCardsComponent
|
||||
onSelectedNetworkChanged: {
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName)
|
||||
d.selectedToNetwork = toCard
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
store.addRemoveDisabledChain(suggestedRoutes, model.chainId, disabled)
|
||||
reCalculateSuggestedRoute(store.disabledChainIds)
|
||||
}
|
||||
onAdvancedInputTextChanged: {
|
||||
if(selectedNetwork && selectedNetwork.chainName === model.chainName)
|
||||
d.customAmountToReceive = isNaN(parseFloat(advancedInputText)) ? 0 : parseFloat(advancedInputText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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: {
|
||||
if(d.selectedFromNetwork && d.selectedToNetwork) {
|
||||
// Get the canvas context
|
||||
var ctx = getContext("2d");
|
||||
StatusQUtils.Utils.drawArrow(ctx, d.selectedFromNetwork.x + d.selectedFromNetwork.width,
|
||||
d.selectedFromNetwork.y + d.selectedFromNetwork.height/2,
|
||||
toNetworksLayout.x + d.selectedToNetwork.x,
|
||||
d.selectedToNetwork.y + d.selectedToNetwork.height/2,
|
||||
'#627EEA')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
import utils 1.0
|
||||
import shared.stores 1.0
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
@ -12,117 +9,117 @@ import StatusQ.Components 0.1
|
|||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import "../panels"
|
||||
import "../controls"
|
||||
import "../views"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: visible ? stackLayout.height + 2* Style.current.xlPadding : 0
|
||||
|
||||
height: visible ? tabBar.height + stackLayout.height + 2* Style.current.xlPadding : 0
|
||||
|
||||
property var store
|
||||
property var suggestedRoutes
|
||||
property var selectedNetwork
|
||||
property var selectedAccount
|
||||
property var selectedAsset
|
||||
property var assets
|
||||
property double amountToSend: 0
|
||||
property double requiredGasInEth: 0
|
||||
property bool errorMode: customNetworkRoutingPage.errorMode
|
||||
|
||||
signal networkChanged(int chainId)
|
||||
signal reCalculateSuggestedRoute(var disabledChainIds)
|
||||
|
||||
property var suggestedRoutes: ""
|
||||
property var selectedNetwork: ""
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int backgroundRectRadius: 13
|
||||
readonly property string backgroundRectColor: Theme.palette.indirectColor1
|
||||
}
|
||||
|
||||
StatusSwitchTabBar {
|
||||
id: tabBar
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.current.bigPadding
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
StatusSwitchTabButton {
|
||||
text: qsTr("Simple")
|
||||
}
|
||||
StatusSwitchTabButton {
|
||||
text: qsTr("Advanced")
|
||||
}
|
||||
StatusSwitchTabButton {
|
||||
text: qsTr("Custom")
|
||||
}
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
id: stackLayout
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.current.xlPadding
|
||||
height: simpleLayout.height
|
||||
anchors.top: tabBar.bottom
|
||||
anchors.topMargin: Style.current.bigPadding
|
||||
height: currentIndex == 0 ? networksSimpleRoutingPage.height + networksSimpleRoutingPage.anchors.margins + Style.current.bigPadding:
|
||||
currentIndex == 1 ? advancedNetworkRoutingPage.height + advancedNetworkRoutingPage.anchors.margins + Style.current.bigPadding:
|
||||
customNetworkRoutingPage.height + customNetworkRoutingPage.anchors.margins + Style.current.bigPadding
|
||||
width: parent.width
|
||||
currentIndex: 0
|
||||
currentIndex: tabBar.currentIndex
|
||||
|
||||
ColumnLayout {
|
||||
id: simpleLayout
|
||||
Layout.fillWidth: true
|
||||
spacing: 24
|
||||
Rectangle {
|
||||
id: networksRect
|
||||
radius: 13
|
||||
color: Theme.palette.indirectColor1
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: layout.height + 24
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
id: simple
|
||||
radius: d.backgroundRectRadius
|
||||
color: d.backgroundRectColor
|
||||
NetworksSimpleRoutingView {
|
||||
id: networksSimpleRoutingPage
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.margins: 16
|
||||
spacing: 20
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
StatusRoundIcon {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
radius: 8
|
||||
icon.name: "flash"
|
||||
}
|
||||
ColumnLayout {
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: 410
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Medium
|
||||
color: Theme.palette.directColor1
|
||||
text: qsTr("Networks")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: 410
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
text: qsTr("Choose a network to use for the transaction")
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.margins: Style.current.padding
|
||||
selectedNetwork: root.selectedNetwork
|
||||
suggestedRoutes: root.suggestedRoutes
|
||||
amountToSend: root.amountToSend
|
||||
onNetworkChanged: {
|
||||
root.selectedNetwork = network
|
||||
root.networkChanged(network.chainId)
|
||||
}
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
visible: suggestedRoutes.length === 0
|
||||
font.pixelSize: 15
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Theme.palette.dangerColor1
|
||||
text: qsTr("No networks available")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
height: 50
|
||||
ScrollView {
|
||||
width: parent.width
|
||||
contentWidth: row.width
|
||||
contentHeight: row.height + 10
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOn
|
||||
clip: true
|
||||
Row {
|
||||
id: row
|
||||
spacing: 16
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: suggestedRoutes
|
||||
StatusListItem {
|
||||
id: item
|
||||
implicitWidth: 126
|
||||
title: modelData.chainName
|
||||
subTitle: ""
|
||||
image.source: Style.png("networks/" + modelData.chainName.toLowerCase())
|
||||
image.width: 32
|
||||
image.height: 32
|
||||
leftPadding: 5
|
||||
rightPadding: 5
|
||||
color: "transparent"
|
||||
border.color: Style.current.primary
|
||||
border.width: root.selectedNetwork.chainId === modelData.chainId ? 1 : 0
|
||||
onClicked: {
|
||||
root.selectedNetwork = modelData
|
||||
root.networkChanged(modelData.chainId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: advanced
|
||||
radius: d.backgroundRectRadius
|
||||
color: d.backgroundRectColor
|
||||
NetworksAdvancedCustomRoutingView {
|
||||
id: advancedNetworkRoutingPage
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.margins: Style.current.padding
|
||||
store: root.store
|
||||
assets: root.assets
|
||||
selectedNetwork: root.selectedNetwork
|
||||
selectedAccount: root.selectedAccount
|
||||
amountToSend: root.amountToSend
|
||||
requiredGasInEth: root.requiredGasInEth
|
||||
selectedAsset: root.selectedAsset
|
||||
suggestedRoutes: root.suggestedRoutes
|
||||
onReCalculateSuggestedRoute: root.reCalculateSuggestedRoute(disabledChainIds)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: custom
|
||||
radius: d.backgroundRectRadius
|
||||
color: d.backgroundRectColor
|
||||
NetworksAdvancedCustomRoutingView {
|
||||
id: customNetworkRoutingPage
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.margins: Style.current.padding
|
||||
customMode: true
|
||||
store: root.store
|
||||
assets: root.assets
|
||||
selectedNetwork: root.selectedNetwork
|
||||
selectedAccount: root.selectedAccount
|
||||
amountToSend: root.amountToSend
|
||||
requiredGasInEth: root.requiredGasInEth
|
||||
selectedAsset: root.selectedAsset
|
||||
suggestedRoutes: root.suggestedRoutes
|
||||
onReCalculateSuggestedRoute: root.reCalculateSuggestedRoute(disabledChainIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
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 "../controls"
|
||||
|
||||
ColumnLayout {
|
||||
id: networksAdvancedCustomView
|
||||
|
||||
property var store
|
||||
property var assets
|
||||
property var selectedNetwork: ""
|
||||
property var selectedAccount
|
||||
property double amountToSend: 0
|
||||
property double requiredGasInEth: 0
|
||||
property bool customMode: false
|
||||
property var selectedAsset
|
||||
property var suggestedRoutes
|
||||
property bool errorMode: networksLoader.item ? networksLoader.item.errorMode : false
|
||||
|
||||
signal reCalculateSuggestedRoute(var disabledChainIds)
|
||||
|
||||
onSelectedNetworkChanged: {
|
||||
networksLoader.active = false
|
||||
networksLoader.active = true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
|
||||
StatusRoundIcon {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
radius: 8
|
||||
icon.name: "flash"
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
RowLayout {
|
||||
Layout.maximumWidth: 410
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: 410
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Medium
|
||||
color: Theme.palette.directColor1
|
||||
text: qsTr("Networks")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
StatusButton {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.preferredHeight: 22
|
||||
defaultTopPadding: 0
|
||||
defaultBottomPadding: 0
|
||||
size: StatusBaseButton.Size.Small
|
||||
icon.name: "hide"
|
||||
text: qsTr("Show Unpreferred Networks")
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: 410
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
text: qsTr("The networks where the receipient will receive tokens. Amounts calculated automatically for the lowest cost.")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
Loader {
|
||||
id: networksLoader
|
||||
Layout.topMargin: Style.current.padding
|
||||
active: false
|
||||
visible: active
|
||||
sourceComponent: NetworkCardsComponent {
|
||||
store: networksAdvancedCustomView.store
|
||||
selectedNetwork: networksAdvancedCustomView.selectedNetwork
|
||||
selectedAccount: networksAdvancedCustomView.selectedAccount
|
||||
allNetworks: networksAdvancedCustomView.store.allNetworks
|
||||
amountToSend: networksAdvancedCustomView.amountToSend
|
||||
customMode: networksAdvancedCustomView.customMode
|
||||
requiredGasInEth: networksAdvancedCustomView.requiredGasInEth
|
||||
assets: networksAdvancedCustomView.assets
|
||||
selectedAsset: networksAdvancedCustomView.selectedAsset
|
||||
locale: networksAdvancedCustomView.store.locale
|
||||
suggestedRoutes: networksAdvancedCustomView.suggestedRoutes
|
||||
onReCalculateSuggestedRoute: networksAdvancedCustomView.reCalculateSuggestedRoute(disabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 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 "../controls"
|
||||
|
||||
RowLayout {
|
||||
id: networksSimpleRoutingView
|
||||
|
||||
property var selectedNetwork
|
||||
property var suggestedRoutes
|
||||
property double amountToSend: 0
|
||||
|
||||
signal networkChanged(var network)
|
||||
|
||||
spacing: 10
|
||||
|
||||
StatusRoundIcon {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
radius: 8
|
||||
icon.name: "flash"
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: 410
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Medium
|
||||
color: Theme.palette.directColor1
|
||||
text: qsTr("Networks")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: 410
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
text: qsTr("Choose a network to use for the transaction")
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
BalanceExceeded {
|
||||
Layout.topMargin: Style.current.bigPadding
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
visible: !transferPossible
|
||||
transferPossible: networksSimpleRoutingView.suggestedRoutes ? networksSimpleRoutingView.suggestedRoutes.length > 0 : false
|
||||
amountToSend: networksSimpleRoutingView.amountToSend
|
||||
}
|
||||
ScrollView {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: row.height + 10
|
||||
Layout.topMargin: Style.current.bigPadding
|
||||
contentWidth: row.width
|
||||
contentHeight: row.height + 10
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
||||
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
|
||||
clip: true
|
||||
visible: networksSimpleRoutingView.suggestedRoutes ? networksSimpleRoutingView.suggestedRoutes.length > 0 : false
|
||||
Row {
|
||||
id: row
|
||||
spacing: Style.current.padding
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: networksSimpleRoutingView.suggestedRoutes
|
||||
StatusListItem {
|
||||
id: item
|
||||
leftPadding: 5
|
||||
rightPadding: 5
|
||||
implicitWidth: 126
|
||||
title: modelData.chainName
|
||||
subTitle: ""
|
||||
image.width: 32
|
||||
image.height: 32
|
||||
image.source: Style.png("networks/" + modelData.chainName.toLowerCase())
|
||||
color: "transparent"
|
||||
border.color: Style.current.primary
|
||||
border.width: networksSimpleRoutingView.selectedNetwork !== undefined ? networksSimpleRoutingView.selectedNetwork.chainId === modelData.chainId ? 1 : 0 : 0
|
||||
onClicked: networksSimpleRoutingView.networkChanged(modelData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -134,7 +134,7 @@ Item {
|
|||
width: visible ? parent.width: 0
|
||||
height: visible ? 64 : 0
|
||||
title: model.name
|
||||
subTitle: Utils.toLocaleString(model.currencyBalance.toFixed(2), popup.store.locale, {"model.currency": true}) + " " + popup.store.currentCurrency.toUpperCase()
|
||||
subTitle: Utils.toLocaleString(model.currencyBalance.toFixed(2), store.locale, {"model.currency": true}) + " " + store.currentCurrency.toUpperCase()
|
||||
icon.emoji: !!model.emoji ? model.emoji: ""
|
||||
icon.color: model.color
|
||||
icon.name: !model.emoji ? "filled-account": ""
|
||||
|
@ -173,7 +173,7 @@ Item {
|
|||
}
|
||||
|
||||
delegate: StatusListItem {
|
||||
property bool isIncoming: to === popup.store.currentAccount.address
|
||||
property bool isIncoming: to === store.currentAccount.address
|
||||
width: visible ? parent.width: 0
|
||||
height: visible ? 64 : 0
|
||||
title: isIncoming ? from : to
|
||||
|
@ -187,14 +187,14 @@ Item {
|
|||
height: 15
|
||||
width: 15
|
||||
color: isIncoming ? Style.current.success : Style.current.danger
|
||||
icon: isIncoming ? "down" : "up"
|
||||
icon: isIncoming ? "arrow-down" : "arrow-up"
|
||||
rotation: 45
|
||||
},
|
||||
StatusBaseText {
|
||||
id: contactsLabel
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
text: popup.store.hex2Eth(value)
|
||||
text: store.hex2Eth(value)
|
||||
}
|
||||
]
|
||||
onClicked: contactSelected(title, RecipientSelector.Type.Address)
|
||||
|
|
|
@ -355,6 +355,7 @@ QtObject {
|
|||
return qsTr("%1D").arg(diffDay)
|
||||
}
|
||||
|
||||
// To-do move to Wallet Store, this should not be under Utils.
|
||||
function findAssetByChainAndSymbol(chainIdToFind, assets, symbolToFind) {
|
||||
for(var i=0; i<assets.rowCount(); i++) {
|
||||
const symbol = assets.rowData(i, "symbol")
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 35c4001e5727c3bd5f59995a4d1698ed2888f5f8
|
||||
Subproject commit b2ce92fd41a3b899749e2ed2ebd94ec8d4e1859f
|
Loading…
Reference in New Issue