feat(@desktop/wallet): Wallet -> Send: polish Send/Bridge Modals
fixes #10344, #10321, #10320
This commit is contained in:
parent
c3d1133dfd
commit
c94997ddec
|
@ -17,6 +17,7 @@ QtObject:
|
|||
fetchingHistoryState: Table[string, bool]
|
||||
enabledChainIds: seq[int]
|
||||
isNonArchivalNode: bool
|
||||
tempAddress: string
|
||||
|
||||
proc delete*(self: View) =
|
||||
self.model.delete
|
||||
|
@ -197,3 +198,12 @@ QtObject:
|
|||
if not self.models.hasKey(fromAddress):
|
||||
self.models[fromAddress] = newModel()
|
||||
self.models[fromAddress].addNewTransactions(@[tx], wasFetchMore=false)
|
||||
|
||||
proc prepareTransactionsForAddress*(self: View, address: string) {.slot.} =
|
||||
self.tempAddress = address
|
||||
|
||||
proc getTransactions*(self: View): QVariant {.slot.} =
|
||||
if self.models.hasKey(self.tempAddress):
|
||||
return newQVariant(self.models[self.tempAddress])
|
||||
else:
|
||||
return newQVariant()
|
||||
|
|
|
@ -20,6 +20,13 @@ type
|
|||
|
||||
const lookupContactTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[LookupContactTaskArg](argEncoded)
|
||||
var output = %*{
|
||||
"id": "",
|
||||
"address": "",
|
||||
"uuid": arg.uuid,
|
||||
"reason": arg.reason
|
||||
}
|
||||
try:
|
||||
var pubkey = arg.value
|
||||
var address = ""
|
||||
|
||||
|
@ -35,13 +42,16 @@ const lookupContactTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
|||
pubkey = ens_utils.publicKeyOf(arg.chainId, arg.value)
|
||||
address = ens_utils.addressOf(arg.chainid, arg.value)
|
||||
|
||||
let output = %*{
|
||||
output = %*{
|
||||
"id": pubkey,
|
||||
"address": address,
|
||||
"uuid": arg.uuid,
|
||||
"reason": arg.reason
|
||||
}
|
||||
arg.finish(output)
|
||||
except Exception as e:
|
||||
error "error lookupContactTask: ", message = e.msg
|
||||
arg.finish(output)
|
||||
|
||||
#################################################
|
||||
# Async request contact info
|
||||
|
|
|
@ -111,6 +111,7 @@ ThemePalette {
|
|||
statusListItem: QtObject {
|
||||
property color backgroundColor: baseColor3
|
||||
property color secondaryHoverBackgroundColor: primaryColor3
|
||||
property color highlightColor: getColor('blue3', 0.05)
|
||||
}
|
||||
|
||||
statusChatListItem: QtObject {
|
||||
|
|
|
@ -109,6 +109,7 @@ ThemePalette {
|
|||
statusListItem: QtObject {
|
||||
property color backgroundColor: white
|
||||
property color secondaryHoverBackgroundColor: getColor('blue6')
|
||||
property color highlightColor: getColor('blue', 0.05)
|
||||
}
|
||||
|
||||
statusChatListItem: QtObject {
|
||||
|
|
|
@ -196,6 +196,7 @@ QtObject {
|
|||
property QtObject statusListItem: QtObject {
|
||||
property color backgroundColor
|
||||
property color secondaryHoverBackgroundColor
|
||||
property color highlightColor
|
||||
}
|
||||
|
||||
property QtObject statusChatListItem: QtObject {
|
||||
|
|
|
@ -22,7 +22,6 @@ StatusListItem {
|
|||
asset.bgColor: Theme.palette.primaryColor3
|
||||
asset.width: 40
|
||||
asset.height: 40
|
||||
width: parent.width
|
||||
|
||||
components: !showShevronIcon ? [] : [ shevronIcon ]
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ Column {
|
|||
}
|
||||
}
|
||||
delegate: WalletAccountDelegate {
|
||||
width: ListView.view.width
|
||||
account: model
|
||||
onGoToAccountView: {
|
||||
root.goToAccountView(model)
|
||||
|
@ -122,6 +123,7 @@ Column {
|
|||
Repeater {
|
||||
model: importedAccounts
|
||||
delegate: WalletAccountDelegate {
|
||||
width: ListView.view.width
|
||||
account: model
|
||||
onGoToAccountView: {
|
||||
root.goToAccountView(model)
|
||||
|
@ -149,6 +151,7 @@ Column {
|
|||
Repeater {
|
||||
model: watchOnlyAccounts
|
||||
delegate: WalletAccountDelegate {
|
||||
width: ListView.view.width
|
||||
account: model
|
||||
onGoToAccountView: {
|
||||
root.goToAccountView(model)
|
||||
|
|
|
@ -273,17 +273,16 @@ Rectangle {
|
|||
}
|
||||
components: [
|
||||
StatusIcon {
|
||||
icon: {
|
||||
if (model.walletType === Constants.watchWalletType)
|
||||
return "show"
|
||||
if (model.walletType === Constants.keyWalletType)
|
||||
return "keycard"
|
||||
|
||||
return ""
|
||||
}
|
||||
width: !!icon ? 15: 0
|
||||
height: !!icon ? 15: 0
|
||||
color: Theme.palette.directColor1
|
||||
width: 15
|
||||
height: 15
|
||||
icon: model.walletType === Constants.watchWalletType ? "show" : ""
|
||||
},
|
||||
StatusIcon {
|
||||
width: !!icon ? 15: 0
|
||||
height: !!icon ? 15: 0
|
||||
color: Theme.palette.directColor1
|
||||
icon: model.migratedToKeycard ? "keycard" : ""
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
icon.name: "clear"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
icon.color: Theme.palette.baseColor1
|
||||
backgroundHoverColor: "transparent"
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||
|
||||
import AppLayouts.Wallet 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
StatusListItem {
|
||||
id: root
|
||||
property var modelData
|
||||
property bool clearVisible: false
|
||||
signal cleared()
|
||||
|
||||
implicitHeight: visible ? 64 : 0
|
||||
title: !!modelData ? modelData.name: ""
|
||||
subTitle: {
|
||||
if(!!modelData) {
|
||||
if (modelData.ens.length > 0) {
|
||||
return sensor.containsMouse ? Utils.richColorText(modelData.ens, Theme.palette.directColor1) : modelData.ens
|
||||
}
|
||||
else {
|
||||
let elidedAddress = StatusQUtils.Utils.elideText(modelData.address,6,4)
|
||||
return sensor.containsMouse ? WalletUtils.colorizedChainPrefix(modelData.chainShortNames) + Utils.richColorText(elidedAddress, Theme.palette.directColor1): modelData.chainShortNames + elidedAddress
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
statusListItemSubTitle.elide: Text.ElideMiddle
|
||||
statusListItemSubTitle.wrapMode: Text.NoWrap
|
||||
radius: 0
|
||||
color: sensor.containsMouse || highlighted ? Theme.palette.statusListItem.highlightColor : "transparent"
|
||||
components: [
|
||||
ClearButton {
|
||||
width: 24
|
||||
height: 24
|
||||
visible: root.clearVisible
|
||||
onClicked: root.cleared()
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
StatusInput {
|
||||
placeholderText: qsTr("Search")
|
||||
input.implicitHeight: 56
|
||||
input.background.color: Theme.palette.indirectColor1
|
||||
input.background.border.width: 0
|
||||
input.rightComponent: StatusFlatRoundButton {
|
||||
icon.name: "search"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
enabled: false
|
||||
}
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
height: 1
|
||||
width: parent.width
|
||||
color: Theme.palette.baseColor2
|
||||
}
|
||||
}
|
|
@ -13,20 +13,33 @@ StatusListItem {
|
|||
return ""
|
||||
}
|
||||
signal tokenSelected(var selectedToken)
|
||||
signal tokenHovered(var selectedToken, bool hovered)
|
||||
|
||||
title: name
|
||||
titleAsideText: symbol
|
||||
statusListItemTitleAside.font.pixelSize: 15
|
||||
label: LocaleUtils.currencyAmountToLocaleString(totalCurrencyBalance)
|
||||
asset.name: symbol ? Style.png("tokens/" + symbol) : ""
|
||||
asset.isImage: true
|
||||
asset.width: 32
|
||||
asset.height: 32
|
||||
statusListItemLabel.anchors.verticalCenterOffset: -12
|
||||
statusListItemLabel.color: Theme.palette.directColor1
|
||||
statusListItemInlineTagsSlot.spacing: sensor.containsMouse ? 0 : -8
|
||||
tagsModel: balances.count > 0 ? balances : []
|
||||
tagsDelegate: sensor.containsMouse ? expandedItem : compactItem
|
||||
radius: sensor.containsMouse || root.highlighted ? 0 : 8
|
||||
color: sensor.containsMouse || highlighted ? Theme.palette.statusListItem.highlightColor : "transparent"
|
||||
|
||||
onClicked: d.selectToken()
|
||||
|
||||
Connections {
|
||||
target: root.sensor
|
||||
function onContainsMouseChanged() {
|
||||
root.tokenHovered({name, symbol, totalBalance, totalCurrencyBalance, balances, decimals}, root.sensor.containsMouse)
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
|
@ -42,7 +55,6 @@ StatusListItem {
|
|||
width: 16
|
||||
height: 16
|
||||
image.source: Style.svg("tiny/%1".arg(root.getNetworkIcon(chainId)))
|
||||
visible: balance.amount > 0
|
||||
}
|
||||
}
|
||||
Component {
|
||||
|
@ -57,7 +69,6 @@ StatusListItem {
|
|||
asset.height: 16
|
||||
asset.isImage: true
|
||||
asset.name: Style.svg("tiny/%1".arg(root.getNetworkIcon(chainId)))
|
||||
visible: balance.amount > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||
|
||||
import AppLayouts.Wallet 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
StatusListItem {
|
||||
id: root
|
||||
|
||||
property var modelData
|
||||
property string chainShortNames
|
||||
property bool clearVisible: false
|
||||
signal cleared()
|
||||
|
||||
objectName: !!modelData ? modelData.name: ""
|
||||
|
||||
height: visible ? 64 : 0
|
||||
title: !!modelData && !!modelData.name ? modelData.name : ""
|
||||
subTitle:{
|
||||
if(!!modelData) {
|
||||
let elidedAddress = StatusQUtils.Utils.elideText(modelData.address,6,4)
|
||||
return sensor.containsMouse ? WalletUtils.colorizedChainPrefix(chainShortNames) + Utils.richColorText(elidedAddress, Theme.palette.directColor1): chainShortNames + elidedAddress
|
||||
}
|
||||
return ""
|
||||
}
|
||||
statusListItemSubTitle.wrapMode: Text.NoWrap
|
||||
asset.emoji: !!modelData && !!modelData.emoji ? modelData.emoji: ""
|
||||
asset.color: !!modelData ? modelData.color: ""
|
||||
asset.name: !!modelData && !modelData.emoji ? "filled-account": ""
|
||||
asset.letterSize: 14
|
||||
asset.isLetterIdenticon: !!modelData && !!modelData.emoji ? true : false
|
||||
asset.bgColor: Theme.palette.indirectColor1
|
||||
asset.width: 40
|
||||
asset.height: 40
|
||||
radius: 0
|
||||
color: sensor.containsMouse || highlighted ? Theme.palette.statusListItem.highlightColor : "transparent"
|
||||
components: [
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
StatusTextWithLoadingState {
|
||||
anchors.right: parent.right
|
||||
font.pixelSize: 15
|
||||
text: LocaleUtils.currencyAmountToLocaleString(!!modelData ? modelData.currencyBalance: "")
|
||||
}
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
spacing: 6
|
||||
StatusIcon {
|
||||
width: !!icon ? 15: 0
|
||||
height: !!icon ? 15 : 0
|
||||
color: Theme.palette.directColor1
|
||||
icon: modelData.walletType === Constants.watchWalletType ? "show" : ""
|
||||
}
|
||||
StatusIcon {
|
||||
width: !!icon ? 15: 0
|
||||
height: !!icon ? 15 : 0
|
||||
color: Theme.palette.directColor1
|
||||
icon: modelData.migratedToKeycard ? "keycard" : ""
|
||||
}
|
||||
}
|
||||
},
|
||||
ClearButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 24
|
||||
height: 24
|
||||
visible: root.clearVisible
|
||||
onClicked: root.cleared()
|
||||
}
|
||||
]
|
||||
}
|
|
@ -25,6 +25,7 @@ Item {
|
|||
property string userSelectedToken
|
||||
property string currentCurrencySymbol
|
||||
property string placeholderText
|
||||
property var hoveredToken
|
||||
|
||||
property var tokenAssetSourceFn: function (symbol) {
|
||||
return ""
|
||||
|
@ -51,12 +52,19 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
onHoveredTokenChanged: {
|
||||
if (hoveredToken && hoveredToken.symbol) {
|
||||
d.iconSource = tokenAssetSourceFn(hoveredToken.symbol)
|
||||
d.text = hoveredToken.symbol
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property string iconSource: ""
|
||||
property string text: ""
|
||||
property string searchString
|
||||
property bool isTokenSelected: !!root.selectedAsset
|
||||
readonly property bool isTokenSelected: !!root.selectedAsset || !!root.hoveredToken
|
||||
|
||||
readonly property var updateSearchText: Backpressure.debounce(root, 1000, function(inputText) {
|
||||
d.searchString = inputText
|
||||
|
@ -70,8 +78,8 @@ Item {
|
|||
|
||||
control.padding: 4
|
||||
control.popup.width: 492
|
||||
control.popup.height: 416
|
||||
control.popup.x: -root.x
|
||||
control.popup.verticalPadding: 0
|
||||
|
||||
popupContentItemObjectName: "assetSelectorList"
|
||||
|
||||
|
@ -171,11 +179,11 @@ Item {
|
|||
placeholderText: qsTr("Search for token or enter token address")
|
||||
onTextChanged: Qt.callLater(d.updateSearchText, text)
|
||||
input.clearable: true
|
||||
input.rightComponent: StatusIcon {
|
||||
width: 16
|
||||
height: 16
|
||||
color: Theme.palette.baseColor1
|
||||
icon: "search"
|
||||
input.implicitHeight: 56
|
||||
input.rightComponent: StatusFlatRoundButton {
|
||||
icon.name: "search"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
enabled: false
|
||||
}
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
|
|
|
@ -38,7 +38,7 @@ StatusDialog {
|
|||
property var currencyStore: store.currencyStore
|
||||
property var selectedAccount: store.currentAccount
|
||||
property var bestRoutes
|
||||
property string addressText
|
||||
property alias addressText: recipientLoader.addressText
|
||||
property bool isLoading: false
|
||||
property int sendType: isBridgeTx ? Constants.SendType.Bridge : Constants.SendType.Transfer
|
||||
property MessageDialog sendingError: MessageDialog {
|
||||
|
@ -49,7 +49,7 @@ StatusDialog {
|
|||
}
|
||||
|
||||
property var sendTransaction: function() {
|
||||
let recipientAddress = Utils.isValidAddress(popup.addressText) ? popup.addressText : d.resolvedENSAddress
|
||||
let recipientAddress = Utils.isValidAddress(popup.addressText) ? popup.addressText : recipientLoader.resolvedENSAddress
|
||||
d.isPendingTx = true
|
||||
popup.store.authenticateAndTransfer(
|
||||
popup.selectedAccount.address,
|
||||
|
@ -62,7 +62,7 @@ StatusDialog {
|
|||
}
|
||||
|
||||
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
|
||||
if(!!popup.selectedAccount && !!assetSelector.selectedAsset && d.recipientReady && amountToSendInput.inputNumberValid) {
|
||||
if(!!popup.selectedAccount && !!assetSelector.selectedAsset && recipientLoader.ready && amountToSendInput.inputNumberValid) {
|
||||
popup.isLoading = true
|
||||
let amount = Math.round(amountToSendInput.cryptoValueToSend * Math.pow(10, assetSelector.selectedAsset.decimals))
|
||||
popup.store.suggestedRoutes(popup.selectedAccount.address, amount.toString(16), assetSelector.selectedAsset.symbol,
|
||||
|
@ -74,21 +74,14 @@ StatusDialog {
|
|||
QtObject {
|
||||
id: d
|
||||
readonly property int errorType: !amountToSendInput.input.valid ? Constants.SendAmountExceedsBalance :
|
||||
(networkSelector.bestRoutes && networkSelector.bestRoutes.length <= 0 && !!amountToSendInput.input.text && recipientReady && !popup.isLoading) ?
|
||||
(networkSelector.bestRoutes && networkSelector.bestRoutes.length <= 0 && !!amountToSendInput.input.text && recipientLoader.ready && !popup.isLoading) ?
|
||||
Constants.NoRoute : Constants.NoError
|
||||
readonly property double maxFiatBalance: !!assetSelector.selectedAsset ? assetSelector.selectedAsset.totalCurrencyBalance.amount : 0
|
||||
readonly property double maxCryptoBalance: !!assetSelector.selectedAsset ? assetSelector.selectedAsset.totalBalance.amount : 0
|
||||
readonly property double maxInputBalance: amountToSendInput.inputIsFiat ? maxFiatBalance : maxCryptoBalance
|
||||
readonly property string selectedSymbol: !!assetSelector.selectedAsset ? assetSelector.selectedAsset.symbol : ""
|
||||
readonly property string inputSymbol: amountToSendInput.inputIsFiat ? popup.store.currentCurrency : selectedSymbol
|
||||
readonly property bool errorMode: popup.isLoading || !recipientReady ? false : errorType !== Constants.NoError || networkSelector.errorMode || !amountToSendInput.inputNumberValid
|
||||
readonly property bool recipientReady: (isAddressValid || isENSValid) && !recipientSelector.isPending
|
||||
property bool isAddressValid: Utils.isValidAddress(popup.addressText)
|
||||
property bool isENSValid: false
|
||||
readonly property var resolveENS: Backpressure.debounce(popup, 500, function (ensName) {
|
||||
store.resolveENS(ensName)
|
||||
})
|
||||
property string resolvedENSAddress
|
||||
readonly property bool errorMode: popup.isLoading || !recipientLoader.ready ? false : errorType !== Constants.NoError || networkSelector.errorMode || !amountToSendInput.inputNumberValid
|
||||
readonly property string uuid: Utils.uuid()
|
||||
property bool isPendingTx: false
|
||||
property string totalTimeEstimate
|
||||
|
@ -96,24 +89,6 @@ StatusDialog {
|
|||
property double totalFeesInFiat
|
||||
property double totalAmountToReceive
|
||||
|
||||
property Timer waitTimer: Timer {
|
||||
interval: 1500
|
||||
onTriggered: {
|
||||
if (recipientSelector.isPending) {
|
||||
return
|
||||
}
|
||||
if (d.isENSValid) {
|
||||
recipientSelector.input.text = d.resolvedENSAddress
|
||||
popup.addressText = d.resolvedENSAddress
|
||||
} else {
|
||||
let result = store.splitAndFormatAddressPrefix(recipientSelector.input.text, isBridgeTx, networkSelector.showUnpreferredNetworks)
|
||||
popup.addressText = result.address
|
||||
recipientSelector.input.text = result.formattedText
|
||||
}
|
||||
|
||||
popup.recalculateRoutesAndFees()
|
||||
}
|
||||
}
|
||||
readonly property NetworkConnectionStore networkConnectionStore: NetworkConnectionStore {}
|
||||
|
||||
onErrorTypeChanged: {
|
||||
|
@ -124,6 +99,7 @@ StatusDialog {
|
|||
|
||||
width: 556
|
||||
topMargin: 64 + header.height
|
||||
bottomPadding: footer.visible ? 0 : 32
|
||||
|
||||
padding: 0
|
||||
background: StatusDialogBackground {
|
||||
|
@ -153,13 +129,13 @@ StatusDialog {
|
|||
}
|
||||
|
||||
if(!!popup.preSelectedRecipient) {
|
||||
recipientSelector.input.text = popup.preSelectedRecipient
|
||||
d.waitTimer.restart()
|
||||
recipientLoader.selectedRecipientType = TabAddressSelectorView.Type.Address
|
||||
recipientLoader.selectedRecipient = {address: popup.preSelectedRecipient}
|
||||
}
|
||||
|
||||
if(popup.isBridgeTx) {
|
||||
recipientSelector.input.text = popup.selectedAccount.address
|
||||
d.waitTimer.restart()
|
||||
recipientLoader.selectedRecipientType = TabAddressSelectorView.Type.Address
|
||||
recipientLoader.selectedRecipient = {address: popup.selectedAccount.address}
|
||||
}
|
||||
|
||||
// add networks that are down to disabled list
|
||||
|
@ -186,6 +162,7 @@ StatusDialog {
|
|||
selectedAccount: popup.selectedAccount
|
||||
changeSelectedAccount: function(newAccount) {
|
||||
popup.selectedAccount = newAccount
|
||||
assetSelector.selectedAsset = store.getAsset(selectedAccount.assets, assetSelector.selectedAsset.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,23 +238,56 @@ StatusDialog {
|
|||
}
|
||||
popup.recalculateRoutesAndFees()
|
||||
}
|
||||
visible: !!assetSelector.selectedAsset || !!assetSelector.hoveredToken
|
||||
}
|
||||
StatusListItemTag {
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
Layout.preferredHeight: 22
|
||||
visible: !!assetSelector.selectedAsset || !!assetSelector.hoveredToken
|
||||
title: {
|
||||
if(!!assetSelector.hoveredToken) {
|
||||
const balance = popup.currencyStore.formatCurrencyAmount(assetSelector.hoveredToken.totalCurrencyBalance.amount, assetSelector.hoveredToken.symbol)
|
||||
return qsTr("Max: %1").arg(balance)
|
||||
}
|
||||
if (d.maxInputBalance <= 0)
|
||||
return qsTr("No balances active")
|
||||
const balance = popup.currencyStore.formatCurrencyAmount(d.maxInputBalance, d.inputSymbol)
|
||||
return qsTr("Max: %1").arg(balance)
|
||||
}
|
||||
tagClickable: true
|
||||
closeButtonVisible: false
|
||||
titleText.font.pixelSize: 12
|
||||
bgColor: amountToSendInput.input.valid ? Theme.palette.primaryColor3 : Theme.palette.dangerColor2
|
||||
titleText.color: amountToSendInput.input.valid ? Theme.palette.primaryColor1 : Theme.palette.dangerColor1
|
||||
bgColor: amountToSendInput.input.valid || !amountToSendInput.input.text ? Theme.palette.primaryColor3 : Theme.palette.dangerColor2
|
||||
titleText.color: amountToSendInput.input.valid || !amountToSendInput.input.text ? Theme.palette.primaryColor1 : Theme.palette.dangerColor1
|
||||
onTagClicked: amountToSendInput.input.text = d.maxInputBalance
|
||||
}
|
||||
}
|
||||
TokenListView {
|
||||
id: tokenListRect
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
visible: !assetSelector.selectedAsset
|
||||
assets: popup.selectedAccount && popup.selectedAccount.assets ? popup.selectedAccount.assets : null
|
||||
searchTokenSymbolByAddressFn: function (address) {
|
||||
return store.findTokenSymbolByAddress(address)
|
||||
}
|
||||
getNetworkIcon: function(chainId){
|
||||
return RootStore.getNetworkIcon(chainId)
|
||||
}
|
||||
onTokenSelected: {
|
||||
assetSelector.userSelectedToken = selectedToken.symbol
|
||||
assetSelector.selectedAsset = selectedToken
|
||||
}
|
||||
onTokenHovered: {
|
||||
if(hovered)
|
||||
assetSelector.hoveredToken = selectedToken
|
||||
else
|
||||
assetSelector.hoveredToken = null
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
visible: !!assetSelector.selectedAsset
|
||||
AmountToSend {
|
||||
id: amountToSendInput
|
||||
Layout.fillWidth:true
|
||||
|
@ -319,24 +329,6 @@ StatusDialog {
|
|||
formatCurrencyAmount: popup.currencyStore.formatCurrencyAmount
|
||||
}
|
||||
}
|
||||
TokenListView {
|
||||
id: tokenListRect
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
visible: !assetSelector.selectedAsset
|
||||
assets: popup.selectedAccount && popup.selectedAccount.assets ? popup.selectedAccount.assets : null
|
||||
searchTokenSymbolByAddressFn: function (address) {
|
||||
return store.findTokenSymbolByAddress(address)
|
||||
}
|
||||
getNetworkIcon: function(chainId){
|
||||
return RootStore.getNetworkIcon(chainId)
|
||||
}
|
||||
onTokenSelected: {
|
||||
assetSelector.userSelectedToken = selectedToken.symbol
|
||||
assetSelector.selectedAsset = selectedToken
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,72 +352,31 @@ StatusDialog {
|
|||
spacing: Style.current.bigPadding
|
||||
anchors.left: parent.left
|
||||
|
||||
StatusInput {
|
||||
id: recipientSelector
|
||||
property bool isPending: false
|
||||
|
||||
height: visible ? implicitHeight: 0
|
||||
visible: !isBridgeTx && !!assetSelector.selectedAsset
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 8
|
||||
width: parent.width
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.bigPadding
|
||||
anchors.rightMargin: Style.current.bigPadding
|
||||
|
||||
label: qsTr("To")
|
||||
placeholderText: qsTr("Enter an ENS name or address")
|
||||
text: popup.addressText
|
||||
input.background.color: Theme.palette.indirectColor1
|
||||
input.background.border.width: 0
|
||||
input.implicitHeight: 56
|
||||
input.clearable: popup.interactive
|
||||
input.edit.readOnly: !popup.interactive
|
||||
multiline: false
|
||||
input.edit.textFormat: TextEdit.RichText
|
||||
input.rightComponent: RowLayout {
|
||||
StatusIcon {
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 16
|
||||
icon: "tiny/checkmark"
|
||||
color: Theme.palette.primaryColor1
|
||||
visible: d.recipientReady
|
||||
}
|
||||
StatusFlatRoundButton {
|
||||
visible: recipientSelector.text !== ""
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
Layout.preferredWidth: 24
|
||||
Layout.preferredHeight: 24
|
||||
icon.name: "clear"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
icon.color: Theme.palette.baseColor1
|
||||
backgroundHoverColor: "transparent"
|
||||
onClicked: {
|
||||
popup.isLoading = true
|
||||
recipientSelector.input.edit.clear()
|
||||
d.waitTimer.restart()
|
||||
}
|
||||
}
|
||||
}
|
||||
Keys.onReleased: {
|
||||
popup.isLoading = true
|
||||
d.waitTimer.restart()
|
||||
if(!d.isAddressValid) {
|
||||
isPending = true
|
||||
Qt.callLater(d.resolveENS, store.plainText(input.edit.text))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: store.mainModuleInst
|
||||
function onResolvedENS(resolvedPubKey: string, resolvedAddress: string, uuid: string) {
|
||||
recipientSelector.isPending = false
|
||||
if(Utils.isValidAddress(resolvedAddress)) {
|
||||
d.resolvedENSAddress = resolvedAddress
|
||||
d.isENSValid = true
|
||||
visible: !isBridgeTx && !!assetSelector.selectedAsset
|
||||
StatusBaseText {
|
||||
id: label
|
||||
elide: Text.ElideRight
|
||||
text: qsTr("To")
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
RecipientView {
|
||||
id: recipientLoader
|
||||
Layout.fillWidth: true
|
||||
store: popup.store
|
||||
isBridgeTx: popup.isBridgeTx
|
||||
interactive: popup.interactive
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
showUnpreferredNetworks: networkSelector.showUnpreferredNetworks
|
||||
onIsLoading: popup.isLoading = true
|
||||
onRecalculateRoutesAndFees: popup.recalculateRoutesAndFees()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -438,12 +389,11 @@ StatusDialog {
|
|||
anchors.rightMargin: Style.current.bigPadding
|
||||
store: popup.store
|
||||
selectedAccount: popup.selectedAccount
|
||||
onContactSelected: {
|
||||
recipientSelector.input.text = address
|
||||
popup.isLoading = true
|
||||
d.waitTimer.restart()
|
||||
onRecipientSelected: {
|
||||
recipientLoader.selectedRecipientType = type
|
||||
recipientLoader.selectedRecipient = recipient
|
||||
}
|
||||
visible: !d.recipientReady && !isBridgeTx && !!assetSelector.selectedAsset
|
||||
visible: !recipientLoader.ready && !isBridgeTx && !!assetSelector.selectedAsset
|
||||
}
|
||||
|
||||
NetworkSelector {
|
||||
|
@ -456,14 +406,14 @@ StatusDialog {
|
|||
store: popup.store
|
||||
interactive: popup.interactive
|
||||
selectedAccount: popup.selectedAccount
|
||||
ensAddressOrEmpty: d.isENSValid ? d.resolvedENSAddress : ""
|
||||
ensAddressOrEmpty: recipientLoader.isENSValid ? recipientLoader.resolvedENSAddress : ""
|
||||
amountToSend: amountToSendInput.cryptoValueToSend
|
||||
minSendCryptoDecimals: amountToSendInput.minSendCryptoDecimals
|
||||
minReceiveCryptoDecimals: amountToSendInput.minReceiveCryptoDecimals
|
||||
requiredGasInEth: d.totalFeesInEth
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
|
||||
visible: d.recipientReady && !!assetSelector.selectedAsset && amountToSendInput.inputNumberValid
|
||||
visible: recipientLoader.ready && !!assetSelector.selectedAsset && amountToSendInput.inputNumberValid
|
||||
errorType: d.errorType
|
||||
isLoading: popup.isLoading
|
||||
bestRoutes: popup.bestRoutes
|
||||
|
@ -477,7 +427,7 @@ StatusDialog {
|
|||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.bigPadding
|
||||
anchors.rightMargin: Style.current.bigPadding
|
||||
visible: d.recipientReady && !!assetSelector.selectedAsset && networkSelector.advancedOrCustomMode && amountToSendInput.inputNumberValid
|
||||
visible: recipientLoader.ready && !!assetSelector.selectedAsset && networkSelector.advancedOrCustomMode && amountToSendInput.inputNumberValid
|
||||
selectedTokenSymbol: d.selectedSymbol
|
||||
isLoading: popup.isLoading
|
||||
bestRoutes: popup.bestRoutes
|
||||
|
@ -495,7 +445,7 @@ StatusDialog {
|
|||
maxFiatFees: popup.isLoading ? "..." : popup.currencyStore.formatCurrencyAmount(d.totalFeesInFiat, popup.store.currentCurrency)
|
||||
totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate
|
||||
pending: d.isPendingTx || popup.isLoading
|
||||
visible: d.recipientReady && amountToSendInput.inputNumberValid && !d.errorMode
|
||||
visible: recipientLoader.ready && amountToSendInput.inputNumberValid && !d.errorMode
|
||||
onNextButtonClicked: popup.sendTransaction()
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import utils 1.0
|
|||
|
||||
import shared.stores 1.0
|
||||
import "../../../app/AppLayouts/Profile/stores"
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
@ -20,7 +21,15 @@ QtObject {
|
|||
property var accounts: walletSectionAccounts.model
|
||||
property var currentAccount: walletSectionCurrent
|
||||
property string signingPhrase: walletSection.signingPhrase
|
||||
property var savedAddressesModel: walletSectionSavedAddresses.model
|
||||
property var savedAddressesModel: SortFilterProxyModel {
|
||||
sourceModel: walletSectionSavedAddresses.model
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "isTest"
|
||||
value: networksModule.areTestNetworksEnabled
|
||||
}
|
||||
]
|
||||
}
|
||||
property var disabledChainIdsFromList: []
|
||||
property var disabledChainIdsToList: []
|
||||
|
||||
|
@ -280,4 +289,21 @@ QtObject {
|
|||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
function prepareTransactionsForAddress(address) {
|
||||
walletSectionTransactions.prepareTransactionsForAddress(address)
|
||||
}
|
||||
|
||||
function getTransactions() {
|
||||
return walletSectionTransactions.getTransactions()
|
||||
}
|
||||
|
||||
function getAllNetworksSupportedString() {
|
||||
let result = ""
|
||||
for(var i = 0; i < allNetworks.count; i++) {
|
||||
let shortName = allNetworks.rowData(i, "shortName")
|
||||
result += shortName + ':'
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||
|
||||
import AppLayouts.Wallet 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import "../controls"
|
||||
|
||||
Loader {
|
||||
id: root
|
||||
|
||||
property var store
|
||||
property bool isBridgeTx: false
|
||||
property bool interactive: true
|
||||
property bool showUnpreferredNetworks: false
|
||||
property var selectedAsset
|
||||
property var selectedRecipient: null
|
||||
property int selectedRecipientType
|
||||
|
||||
readonly property bool ready: (d.isAddressValid || root.isENSValid) && !d.isPending
|
||||
property string addressText
|
||||
property bool isENSValid: false
|
||||
property string resolvedENSAddress
|
||||
|
||||
signal recalculateRoutesAndFees()
|
||||
signal isLoading()
|
||||
|
||||
onAddressTextChanged: d.isPending = false
|
||||
|
||||
onSelectedRecipientChanged: {
|
||||
root.isLoading()
|
||||
d.waitTimer.restart()
|
||||
if(!!root.selectedRecipient && root.selectedRecipientType !== TabAddressSelectorView.Type.None) {
|
||||
switch(root.selectedRecipientType) {
|
||||
case TabAddressSelectorView.Type.SavedAddress: {
|
||||
if (root.selectedRecipient.ens.length > 0) {
|
||||
d.isPending = true
|
||||
return store.resolveENS(root.selectedRecipient.ens)
|
||||
}
|
||||
}
|
||||
case TabAddressSelectorView.Type.RecentsAddress: {
|
||||
let isIncoming = root.selectedRecipient.to === root.selectedRecipient.address
|
||||
root.addressText = isIncoming ? root.selectedRecipient.from : root.selectedRecipient.to
|
||||
root.item.input.text = root.addressText
|
||||
return
|
||||
}
|
||||
case TabAddressSelectorView.Type.Address: {
|
||||
root.item.input.text = root.selectedRecipient.address
|
||||
}
|
||||
}
|
||||
root.addressText = root.selectedRecipient.address
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property bool isAddressValid: Utils.isValidAddress(root.addressText)
|
||||
readonly property var resolveENS: Backpressure.debounce(root, 500, function (ensName) {
|
||||
store.resolveENS(ensName)
|
||||
})
|
||||
property bool isPending: false
|
||||
function clearValues() {
|
||||
root.addressText = ""
|
||||
root.isENSValid = false
|
||||
root.resolvedENSAddress = ""
|
||||
root.selectedRecipientType = TabAddressSelectorView.Type.None
|
||||
root.selectedRecipient = null
|
||||
}
|
||||
property Timer waitTimer: Timer {
|
||||
interval: 1500
|
||||
onTriggered: {
|
||||
if(!!root.item) {
|
||||
if (d.isPending) {
|
||||
return
|
||||
}
|
||||
if (root.isENSValid) {
|
||||
if(!!root.item.input)
|
||||
root.item.input.text = root.resolvedENSAddress
|
||||
root.addressText = root.resolvedENSAddress
|
||||
store.splitAndFormatAddressPrefix(root.address, root.isBridgeTx, root.showUnpreferredNetworks)
|
||||
} else {
|
||||
let address = d.getAddress()
|
||||
let result = store.splitAndFormatAddressPrefix(address, root.isBridgeTx, root.showUnpreferredNetworks)
|
||||
if(!!result.address) {
|
||||
root.addressText = result.address
|
||||
if(!!root.item.input)
|
||||
root.item.input.text = result.formattedText
|
||||
}
|
||||
}
|
||||
root.recalculateRoutesAndFees()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getAddress() {
|
||||
if(root.selectedRecipientType === TabAddressSelectorView.Type.SavedAddress || root.selectedRecipientType === TabAddressSelectorView.Type.Account){
|
||||
return root.item.chainShortNames + root.selectedRecipient.address
|
||||
}
|
||||
else {
|
||||
return !!root.item.input && !!root.store.plainText(root.item.input.text) ? root.store.plainText(root.item.input.text): ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceComponent: root.selectedRecipientType === TabAddressSelectorView.Type.SavedAddress ? savedAddressRecipient:
|
||||
root.selectedRecipientType === TabAddressSelectorView.Type.Account ? myAccountRecipient : addressRecipient
|
||||
|
||||
Component {
|
||||
id: savedAddressRecipient
|
||||
SavedAddressListItem {
|
||||
property string chainShortNames: !!modelData ? modelData.chainShortNames: ""
|
||||
implicitWidth: parent.width
|
||||
modelData: root.selectedRecipient
|
||||
radius: 8
|
||||
clearVisible: true
|
||||
color: Theme.palette.indirectColor1
|
||||
sensor.enabled: false
|
||||
subTitle: {
|
||||
if(!!modelData) {
|
||||
if (!!modelData && !!modelData.ens && modelData.ens.length > 0)
|
||||
return Utils.richColorText(modelData.ens, Theme.palette.directColor1)
|
||||
else
|
||||
return WalletUtils.colorizedChainPrefix(modelData.chainShortNames) + StatusQUtils.Utils.elideText(modelData.address,6,4)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
onCleared: d.clearValues()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: myAccountRecipient
|
||||
WalletAccountListItem {
|
||||
implicitWidth: parent.width
|
||||
chainShortNames: store.getAllNetworksSupportedString()
|
||||
modelData: root.selectedRecipient
|
||||
radius: 8
|
||||
clearVisible: true
|
||||
color: Theme.palette.indirectColor1
|
||||
sensor.enabled: false
|
||||
subTitle: {
|
||||
if(!!modelData) {
|
||||
let elidedAddress = StatusQUtils.Utils.elideText(modelData.address,6,4)
|
||||
return WalletUtils.colorizedChainPrefix(chainShortNames) + StatusQUtils.Utils.elideText(elidedAddress,6,4)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
onCleared: d.clearValues()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: addressRecipient
|
||||
StatusInput {
|
||||
id: recipientInput
|
||||
width: parent.width
|
||||
height: visible ? implicitHeight: 0
|
||||
visible: !root.isBridgeTx && !!root.selectedAsset
|
||||
|
||||
placeholderText: qsTr("Enter an ENS name or address")
|
||||
input.background.color: Theme.palette.indirectColor1
|
||||
input.background.border.width: 0
|
||||
input.implicitHeight: 56
|
||||
input.clearable: root.interactive
|
||||
input.edit.readOnly: !root.interactive
|
||||
multiline: false
|
||||
input.edit.textFormat: TextEdit.RichText
|
||||
|
||||
input.rightComponent: RowLayout {
|
||||
StatusButton {
|
||||
font.weight: Font.Normal
|
||||
borderColor: Theme.palette.primaryColor1
|
||||
size: StatusBaseButton.Size.Tiny
|
||||
text: qsTr("Paste")
|
||||
visible: !store.plainText(recipientInput.text)
|
||||
onClicked: recipientInput.input.edit.paste()
|
||||
}
|
||||
StatusIcon {
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 16
|
||||
icon: "tiny/checkmark"
|
||||
color: Theme.palette.primaryColor1
|
||||
visible: !!store.plainText(recipientInput.text)
|
||||
}
|
||||
ClearButton {
|
||||
Layout.preferredWidth: 24
|
||||
Layout.preferredHeight: 24
|
||||
visible: !!store.plainText(recipientInput.text)
|
||||
onClicked: {
|
||||
recipientInput.input.edit.clear()
|
||||
d.clearValues()
|
||||
}
|
||||
}
|
||||
}
|
||||
Keys.onReleased: {
|
||||
let plainText = store.plainText(input.edit.text)
|
||||
if(!plainText) {
|
||||
d.clearValues()
|
||||
}
|
||||
else {
|
||||
root.isLoading()
|
||||
d.waitTimer.restart()
|
||||
if(!Utils.isValidAddress(plainText)) {
|
||||
d.isPending = true
|
||||
d.resolveENS(plainText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: store.mainModuleInst
|
||||
function onResolvedENS(resolvedPubKey: string, resolvedAddress: string, uuid: string) {
|
||||
d.isPending = false
|
||||
if(Utils.isValidAddress(resolvedAddress)) {
|
||||
root.resolvedENSAddress = resolvedAddress
|
||||
root.isENSValid = true
|
||||
}
|
||||
d.waitTimer.restart()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,11 +6,14 @@ import QtQuick.Dialogs 1.3
|
|||
import utils 1.0
|
||||
import shared.stores 1.0
|
||||
|
||||
import AppLayouts.Wallet 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 "../panels"
|
||||
import "../controls"
|
||||
|
@ -24,7 +27,16 @@ Item {
|
|||
property var selectedAccount
|
||||
property var store
|
||||
|
||||
signal contactSelected(string address, int type)
|
||||
signal recipientSelected(var recipient, int type)
|
||||
|
||||
enum Type {
|
||||
Address,
|
||||
Contact,
|
||||
Account,
|
||||
SavedAddress,
|
||||
RecentsAddress,
|
||||
None
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
@ -58,6 +70,7 @@ Item {
|
|||
StackLayout {
|
||||
id: stackLayout
|
||||
anchors.top: accountSelectionTabBar.bottom
|
||||
anchors.topMargin: -5
|
||||
height: currentIndex === 0 ? savedAddresses.height: currentIndex === 1 ? myAccounts.height : recents.height
|
||||
width: parent.width
|
||||
currentIndex: accountSelectionTabBar.currentIndex
|
||||
|
@ -79,44 +92,18 @@ Item {
|
|||
model: root.store.savedAddressesModel
|
||||
header: savedAddresses.count > 0 ? search : nothingInList
|
||||
headerPositioning: ListView.OverlayHeader
|
||||
delegate: StatusListItem {
|
||||
implicitWidth: parent.width
|
||||
height: visible ? 64 : 0
|
||||
title: name
|
||||
subTitle: address
|
||||
radius: 0
|
||||
color: sensor.containsMouse || highlighted ? Theme.palette.baseColor3 : "transparent"
|
||||
delegate: SavedAddressListItem {
|
||||
implicitWidth: ListView.view.width
|
||||
modelData: model
|
||||
visible: !savedAddresses.headerItem.text || name.toLowerCase().includes(savedAddresses.headerItem.text)
|
||||
// TODO uncomment when #6456 is fixed
|
||||
// components: [
|
||||
// StatusIcon {
|
||||
// icon: "star-icon"
|
||||
// width: 12
|
||||
// height: 12
|
||||
// }
|
||||
// ]
|
||||
onClicked: contactSelected(address, RecipientSelector.Type.Address )
|
||||
onClicked: recipientSelected(modelData, TabAddressSelectorView.Type.SavedAddress)
|
||||
}
|
||||
Component {
|
||||
id: search
|
||||
ColumnLayout {
|
||||
SearchBoxWithRightIcon {
|
||||
width: parent.width
|
||||
StatusInput {
|
||||
Layout.preferredHeight: 55
|
||||
Layout.preferredWidth: parent.width
|
||||
input.showBackground: false
|
||||
placeholderText: qsTr("Search for saved address")
|
||||
input.rightComponent: StatusIcon {
|
||||
icon: "search"
|
||||
height: 17
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
Layout.preferredHeight: 1
|
||||
Layout.preferredWidth: parent.width
|
||||
color: Theme.palette.baseColor3
|
||||
}
|
||||
z: 2
|
||||
}
|
||||
}
|
||||
Component {
|
||||
|
@ -148,21 +135,11 @@ Item {
|
|||
width: parent.width
|
||||
height: Math.min(d.maxHeightForList, myAccounts.contentHeight)
|
||||
|
||||
delegate: StatusListItem {
|
||||
implicitWidth: parent.width
|
||||
objectName: model.name
|
||||
height: visible ? 64 : 0
|
||||
title: !!model.name ? model.name : ""
|
||||
subTitle: LocaleUtils.currencyAmountToLocaleString(model.currencyBalance)
|
||||
asset.emoji: !!model.emoji ? model.emoji: ""
|
||||
asset.color: model.color
|
||||
asset.name: !model.emoji ? "filled-account": ""
|
||||
asset.letterSize: 14
|
||||
asset.isLetterIdenticon: !!model.emoji ? true : false
|
||||
asset.bgColor: Theme.palette.indirectColor1
|
||||
radius: 0
|
||||
color: sensor.containsMouse || highlighted ? Theme.palette.baseColor3 : "transparent"
|
||||
onClicked: contactSelected(model.address, RecipientSelector.Type.Account )
|
||||
delegate: WalletAccountListItem {
|
||||
implicitWidth: ListView.view.width
|
||||
modelData: model
|
||||
chainShortNames: root.store.getAllNetworksSupportedString()
|
||||
onClicked: recipientSelected(modelData, TabAddressSelectorView.Type.Account )
|
||||
}
|
||||
|
||||
model: root.store.accounts
|
||||
|
@ -194,15 +171,18 @@ Item {
|
|||
}
|
||||
|
||||
delegate: StatusListItem {
|
||||
id: listItem
|
||||
property bool isIncoming: root.selectedAccount ? to === root.selectedAccount.address : false
|
||||
implicitWidth: parent.width
|
||||
implicitWidth: ListView.view.width
|
||||
height: visible ? 64 : 0
|
||||
title: isIncoming ? from : to
|
||||
title: loading ? Constants.dummyText : isIncoming ? StatusQUtils.Utils.elideText(from,6,4) : StatusQUtils.Utils.elideText(to,6,4)
|
||||
subTitle: LocaleUtils.getTimeDifference(new Date(parseInt(timestamp) * 1000), new Date())
|
||||
statusListItemTitle.elide: Text.ElideMiddle
|
||||
statusListItemTitle.wrapMode: Text.NoWrap
|
||||
radius: 0
|
||||
color: sensor.containsMouse || highlighted ? Theme.palette.baseColor3 : "transparent"
|
||||
color: sensor.containsMouse || highlighted ? Theme.palette.statusListItem.highlightColor : "transparent"
|
||||
statusListItemComponentsSlot.spacing: 5
|
||||
loading: loadingTransaction
|
||||
components: [
|
||||
StatusIcon {
|
||||
id: transferIcon
|
||||
|
@ -211,18 +191,25 @@ Item {
|
|||
color: isIncoming ? Style.current.success : Style.current.danger
|
||||
icon: isIncoming ? "arrow-down" : "arrow-up"
|
||||
rotation: 45
|
||||
visible: !listItem.loading
|
||||
},
|
||||
StatusBaseText {
|
||||
StatusTextWithLoadingState {
|
||||
id: contactsLabel
|
||||
loading: listItem.loading
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
text: LocaleUtils.currencyAmountToLocaleString(value)
|
||||
customColor: Theme.palette.directColor1
|
||||
text: loading ? Constants.dummyText : LocaleUtils.currencyAmountToLocaleString(value)
|
||||
}
|
||||
]
|
||||
onClicked: contactSelected(title, RecipientSelector.Type.Address)
|
||||
onClicked: recipientSelected(model, TabAddressSelectorView.Type.RecentsAddress)
|
||||
}
|
||||
|
||||
model: root.store.walletSectionTransactionsInst.model
|
||||
model: {
|
||||
if(root.selectedAccount) {
|
||||
root.store.prepareTransactionsForAddress(root.selectedAccount.address)
|
||||
return root.store.getTransactions()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ Item {
|
|||
|
||||
property var assets: null
|
||||
signal tokenSelected(var selectedToken)
|
||||
signal tokenHovered(var selectedToken, bool hovered)
|
||||
property var searchTokenSymbolByAddressFn: function (address) {
|
||||
return ""
|
||||
}
|
||||
|
@ -37,47 +38,34 @@ Item {
|
|||
id: contentLayout
|
||||
|
||||
anchors.fill: parent
|
||||
spacing: 8
|
||||
|
||||
StatusBaseText {
|
||||
id: label
|
||||
elide: Text.ElideRight
|
||||
text: qsTr("Token to send")
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: headerColumn.height
|
||||
Layout.preferredHeight: tokenList.height
|
||||
|
||||
color: Theme.palette.indirectColor1
|
||||
radius: 8
|
||||
|
||||
Column {
|
||||
id: headerColumn
|
||||
|
||||
width: parent.width
|
||||
Item {
|
||||
height: 5
|
||||
width: parent.width
|
||||
}
|
||||
StatusInput {
|
||||
height: 50
|
||||
width: parent.width
|
||||
input.showBackground: false
|
||||
placeholderText: qsTr("Search for token or enter token address")
|
||||
input.rightComponent: StatusIcon {
|
||||
icon: "search"
|
||||
height: 17
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
onTextChanged: Qt.callLater(d.updateSearchText, text)
|
||||
}
|
||||
Rectangle {
|
||||
height: 1
|
||||
width: parent.width
|
||||
color: Theme.palette.baseColor3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusListView {
|
||||
id: tokenList
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 396
|
||||
width: parent.width
|
||||
height: tokenList.contentHeight
|
||||
|
||||
header: SearchBoxWithRightIcon {
|
||||
width: parent.width
|
||||
placeholderText: qsTr("Search for token or enter token address")
|
||||
onTextChanged: Qt.callLater(d.updateSearchText, text)
|
||||
}
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: root.assets
|
||||
|
@ -97,6 +85,8 @@ Item {
|
|||
width: ListView.view.width
|
||||
getNetworkIcon: root.getNetworkIcon
|
||||
onTokenSelected: root.tokenSelected(selectedToken)
|
||||
onTokenHovered: root.tokenHovered(selectedToken, hovered)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue