feat(@desktop/wallet): add collectibles list to send modal
Fixes #12072
This commit is contained in:
parent
bad497cc90
commit
50ffbb9dce
|
@ -9,6 +9,8 @@ import utils 1.0
|
|||
import shared.popups 1.0
|
||||
import shared.stores 1.0
|
||||
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
SplitView {
|
||||
id: root
|
||||
|
||||
|
@ -32,11 +34,14 @@ SplitView {
|
|||
visible: true
|
||||
modal: false
|
||||
closePolicy: Popup.NoAutoClose
|
||||
onlyAssets: false
|
||||
|
||||
store: TransactionStore {
|
||||
readonly property QtObject selectedSenderAccount: QtObject {
|
||||
readonly property var assets: WalletAssetsModel {}
|
||||
}
|
||||
readonly property QtObject collectiblesModel: WalletCollectiblesModel {}
|
||||
readonly property QtObject nestedCollectiblesModel: WalletNestedCollectiblesModel {}
|
||||
|
||||
readonly property QtObject walletSectionSendInst: QtObject {}
|
||||
readonly property QtObject mainModuleInst: QtObject {}
|
||||
|
@ -61,6 +66,75 @@ SplitView {
|
|||
return ""
|
||||
}
|
||||
|
||||
function getAsset(assetsList, symbol) {
|
||||
const idx = ModelUtils.indexOf(assetsList, "symbol", symbol)
|
||||
if (idx < 0) {
|
||||
return {}
|
||||
}
|
||||
return ModelUtils.get(assetsList, idx)
|
||||
}
|
||||
|
||||
function getCollectible(uid) {
|
||||
const idx = ModelUtils.indexOf(collectiblesModel, "uid", uid)
|
||||
if (idx < 0) {
|
||||
return {}
|
||||
}
|
||||
return ModelUtils.get(collectiblesModel, idx)
|
||||
}
|
||||
|
||||
function getSelectorCollectible(uid) {
|
||||
const idx = ModelUtils.indexOf(nestedCollectiblesModel, "uid", uid)
|
||||
if (idx < 0) {
|
||||
return {}
|
||||
}
|
||||
return ModelUtils.get(nestedCollectiblesModel, idx)
|
||||
}
|
||||
|
||||
function getHolding(holdingId, holdingType) {
|
||||
if (holdingType === Constants.HoldingType.Asset) {
|
||||
return getAsset(selectedSenderAccount.assets, holdingId)
|
||||
} else if (holdingType === Constants.HoldingType.Collectible) {
|
||||
return getCollectible(holdingId)
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectorHolding(holdingId, holdingType) {
|
||||
if (holdingType === Constants.HoldingType.Asset) {
|
||||
return getAsset(selectedSenderAccount.assets, holdingId)
|
||||
} else if (holdingType === Constants.HoldingType.Collectible) {
|
||||
return getSelectorCollectible(holdingId)
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function assetToSelectorAsset(asset) {
|
||||
return asset
|
||||
}
|
||||
|
||||
function collectibleToSelectorCollectible(collectible) {
|
||||
return {
|
||||
uid: collectible.uid,
|
||||
chainId: collectible.chainId,
|
||||
name: collectible.name,
|
||||
iconUrl: collectible.imageUrl,
|
||||
collectionUid: collectible.collectionUid,
|
||||
collectionName: collectible.collectionName,
|
||||
isCollection: false
|
||||
}
|
||||
}
|
||||
|
||||
function holdingToSelectorHolding(holding, holdingType) {
|
||||
if (holdingType === Constants.HoldingType.Asset) {
|
||||
return assetToSelectorAsset(holding)
|
||||
} else if (holdingType === Constants.HoldingType.Collectible) {
|
||||
return collectibleToSelectorCollectible(holding)
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
readonly property string currentCurrency: "USD"
|
||||
|
||||
|
|
|
@ -3,7 +3,12 @@ import QtQuick 2.15
|
|||
ListModel {
|
||||
readonly property var data: [
|
||||
{
|
||||
totalBalance: 323.3,
|
||||
totalBalance: ({
|
||||
displayDecimals: true,
|
||||
stripTrailingZeroes: true,
|
||||
amount: 323.3,
|
||||
symbol: "ETH"
|
||||
}),
|
||||
decimals: 2,
|
||||
totalCurrencyBalance: ({
|
||||
displayDecimals: true,
|
||||
|
@ -27,7 +32,12 @@ ListModel {
|
|||
allChecked: true
|
||||
},
|
||||
{
|
||||
totalBalance: 324343.3,
|
||||
totalBalance: ({
|
||||
displayDecimals: true,
|
||||
stripTrailingZeroes: true,
|
||||
amount: 324343.3,
|
||||
symbol: "SNT"
|
||||
}),
|
||||
decimals: 2,
|
||||
totalCurrencyBalance: ({
|
||||
displayDecimals: true,
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
ListModel {
|
||||
readonly property var rootData: [
|
||||
{
|
||||
uid: "ID-Kitty1",
|
||||
chainId: 1,
|
||||
contractAddress: "0x1",
|
||||
tokenId: "1",
|
||||
name: "Furbeard",
|
||||
imageUrl: ModelsData.collectibles.kitty1Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
},
|
||||
{
|
||||
uid: "ID-Kitty2",
|
||||
chainId: 1,
|
||||
contractAddress: "0x1",
|
||||
tokenId: "2",
|
||||
name: "Magicat",
|
||||
imageUrl: ModelsData.collectibles.kitty2Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
},
|
||||
{
|
||||
uid: "ID-Kitty3",
|
||||
chainId: 1,
|
||||
contractAddress: "0x1",
|
||||
tokenId: "3",
|
||||
name: "Happy Meow",
|
||||
imageUrl: ModelsData.collectibles.kitty3Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
},
|
||||
{
|
||||
uid: "ID-Kitty4",
|
||||
chainId: 1,
|
||||
contractAddress: "0x1",
|
||||
tokenId: "4",
|
||||
name: "Furbeard-2",
|
||||
imageUrl: ModelsData.collectibles.kitty4Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
},
|
||||
{
|
||||
uid: "ID-Kitty5",
|
||||
chainId: 1,
|
||||
contractAddress: "0x1",
|
||||
tokenId: "4",
|
||||
name: "Magicat-3",
|
||||
imageUrl: ModelsData.collectibles.kitty5Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties"
|
||||
},
|
||||
{
|
||||
uid: "ID-Anniversary",
|
||||
chainId: 1,
|
||||
contractAddress: "0x2",
|
||||
tokenId: "1",
|
||||
name: "Anniversary",
|
||||
imageUrl: ModelsData.collectibles.anniversary,
|
||||
collectionUid: "anniversary",
|
||||
collectionName: "Anniversary",
|
||||
},
|
||||
{
|
||||
uid: "ID-SuperRare",
|
||||
chainId: 1,
|
||||
contractAddress: "0x3",
|
||||
tokenId: "101",
|
||||
name: "SuperRare",
|
||||
imageUrl: ModelsData.collectibles.superRare,
|
||||
collectionUid: "super-rare",
|
||||
collectionName: "SuperRare",
|
||||
},
|
||||
{
|
||||
uid: "ID-Custom",
|
||||
chainId: 1,
|
||||
contractAddress: "0x04",
|
||||
tokenId: "403",
|
||||
name: "Custom Collectible",
|
||||
imageUrl: ModelsData.collectibles.custom,
|
||||
collectionUid: "custom",
|
||||
collectionName: "Custom",
|
||||
}
|
||||
]
|
||||
|
||||
Component.onCompleted: append(rootData)
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
ListModel {
|
||||
readonly property var rootData: [
|
||||
{
|
||||
uid: "ID-Anniversary",
|
||||
chainId: 1,
|
||||
name: "Anniversary",
|
||||
iconUrl: ModelsData.collectibles.anniversary,
|
||||
collectionUid: "anniversary",
|
||||
collectionName: "Anniversary",
|
||||
isCollection: false,
|
||||
},
|
||||
{
|
||||
uid: "ID-SuperRare",
|
||||
chainId: 1,
|
||||
name: "SuperRare",
|
||||
iconUrl: ModelsData.collectibles.superRare,
|
||||
collectionUid: "super-rare",
|
||||
collectionName: "SuperRare",
|
||||
isCollection: false,
|
||||
},
|
||||
{
|
||||
uid: "cryptokitties",
|
||||
chainId: 1,
|
||||
name: "CryptoKitties",
|
||||
iconUrl: ModelsData.collectibles.cryptoKitties,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
isCollection: true,
|
||||
},
|
||||
{
|
||||
uid: "ID-Custom",
|
||||
chainId: 1,
|
||||
name: "Custom Collectible",
|
||||
iconUrl: ModelsData.collectibles.custom,
|
||||
collectionUid: "custom",
|
||||
collectionName: "Custom",
|
||||
isCollection: false,
|
||||
}
|
||||
]
|
||||
|
||||
readonly property var criptoKittiesData: [
|
||||
{
|
||||
uid: "ID-Kitty1",
|
||||
chainId: 1,
|
||||
name: "Furbeard",
|
||||
iconUrl: ModelsData.collectibles.kitty1Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
isCollection: false,
|
||||
},
|
||||
{
|
||||
uid: "ID-Kitty2",
|
||||
chainId: 1,
|
||||
name: "Magicat",
|
||||
iconUrl: ModelsData.collectibles.kitty2Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
isCollection: false,
|
||||
},
|
||||
{
|
||||
uid: "ID-Kitty3",
|
||||
chainId: 1,
|
||||
name: "Happy Meow",
|
||||
iconUrl: ModelsData.collectibles.kitty3Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
isCollection: false,
|
||||
},
|
||||
{
|
||||
uid: "ID-Kitty4",
|
||||
chainId: 1,
|
||||
name: "Furbeard-2",
|
||||
iconUrl: ModelsData.collectibles.kitty4Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
isCollection: false,
|
||||
},
|
||||
{
|
||||
uid: "ID-Kitty5",
|
||||
chainId: 1,
|
||||
name: "Magicat-3",
|
||||
iconUrl: ModelsData.collectibles.kitty5Big,
|
||||
collectionUid: "cryptokitties",
|
||||
collectionName: "CryptoKitties",
|
||||
isCollection: false,
|
||||
}
|
||||
]
|
||||
|
||||
property string currentCollectionUid
|
||||
|
||||
onCurrentCollectionUidChanged: {
|
||||
clear()
|
||||
if (currentCollectionUid === "") {
|
||||
append(rootData)
|
||||
} else if (currentCollectionUid === "cryptokitties") {
|
||||
append(criptoKittiesData)
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: append(rootData)
|
||||
}
|
|
@ -12,7 +12,9 @@ TokenHoldersModel 1.0 TokenHoldersModel.qml
|
|||
UsersModel 1.0 UsersModel.qml
|
||||
WalletAccountsModel 1.0 WalletAccountsModel.qml
|
||||
WalletAssetsModel 1.0 WalletAssetsModel.qml
|
||||
WalletCollectiblesModel 1.0 WalletCollectiblesModel.qml
|
||||
WalletKeyPairModel 1.0 WalletKeyPairModel.qml
|
||||
WalletNestedCollectiblesModel 1.0 WalletNestedCollectiblesModel.qml
|
||||
singleton ModelsData 1.0 ModelsData.qml
|
||||
singleton NetworksModel 1.0 NetworksModel.qml
|
||||
singleton PermissionsModel 1.0 PermissionsModel.qml
|
||||
|
|
|
@ -64,7 +64,8 @@ StatusSectionLayout {
|
|||
property Component sendTransactionModalComponent: SendModal {
|
||||
anchors.centerIn: parent
|
||||
selectedAccount: WalletStore.dappBrowserAccount
|
||||
preSelectedAsset: store.getAsset(WalletStore.dappBrowserAccount.assets, "ETH")
|
||||
preSelectedHolding: store.getAsset(WalletStore.dappBrowserAccount.assets, "ETH")
|
||||
preSelectedHoldingType: Constants.HoldingType.Asset
|
||||
}
|
||||
|
||||
property Component signMessageModalComponent: SignMessageModal {}
|
||||
|
|
|
@ -120,7 +120,8 @@ Item {
|
|||
sendType: Constants.SendType.ENSRelease
|
||||
preSelectedRecipient: root.ensUsernamesStore.getEnsRegisteredAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(0)
|
||||
preSelectedAsset: store.getAsset(releaseEnsModal.store.assets, "ETH")
|
||||
preSelectedHolding: store.getAsset(releaseEnsModal.store.assets, Constants.ethToken)
|
||||
preSelectedHoldingType: Constants.HoldingType.Asset
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.count === 1) {
|
||||
let path = bestRoutes.firstItem()
|
||||
|
|
|
@ -66,7 +66,8 @@ Item {
|
|||
sendType: Constants.SendType.ENSSetPubKey
|
||||
preSelectedRecipient: root.ensUsernamesStore.getEnsRegisteredAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(0)
|
||||
preSelectedAsset: store.getAsset(connectEnsModal.store.assets, "ETH")
|
||||
preSelectedHolding: store.getAsset(connectEnsModal.store.assets, Constants.ethToken)
|
||||
preSelectedHoldingType: Constants.HoldingType.Asset
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.count === 1) {
|
||||
let path = bestRoutes.firstItem()
|
||||
|
|
|
@ -50,7 +50,8 @@ Item {
|
|||
sendType: Constants.SendType.ENSRegister
|
||||
preSelectedRecipient: root.ensUsernamesStore.getEnsRegisteredAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(10)
|
||||
preSelectedAsset: store.getAsset(buyEnsModal.store.assets, JSON.parse(root.stickersStore.getStatusToken()).symbol)
|
||||
preSelectedHolding: store.getAsset(buyEnsModal.store.assets, JSON.parse(root.stickersStore.getStatusToken()).symbol)
|
||||
preSelectedHoldingType: Constants.HoldingType.Asset
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.count === 1) {
|
||||
let path = bestRoutes.firstItem()
|
||||
|
|
|
@ -40,6 +40,8 @@ Rectangle {
|
|||
text: qsTr("Send")
|
||||
interactive: networkConnectionStore.sendBuyBridgeEnabled
|
||||
onClicked: function() {
|
||||
sendModal.preSelectedHoldingID = walletStore.currentViewedHoldingID
|
||||
sendModal.preSelectedHoldingType = walletStore.currentViewedHoldingType
|
||||
sendModal.open()
|
||||
}
|
||||
tooltipText: networkConnectionStore.sendBuyBridgeToolTipText
|
||||
|
@ -61,6 +63,8 @@ Rectangle {
|
|||
interactive: networkConnectionStore.sendBuyBridgeEnabled
|
||||
onClicked: function() {
|
||||
sendModal.isBridgeTx = true
|
||||
sendModal.preSelectedHoldingID = walletStore.currentViewedHoldingID
|
||||
sendModal.preSelectedHoldingType = walletStore.currentViewedHoldingType
|
||||
sendModal.open()
|
||||
}
|
||||
tooltipText: networkConnectionStore.sendBuyBridgeToolTipText
|
||||
|
|
|
@ -118,6 +118,24 @@ QtObject {
|
|||
|
||||
property var cryptoRampServicesModel: walletSectionBuySellCrypto.model
|
||||
|
||||
function resetCurrentViewedHolding() {
|
||||
currentViewedHoldingID = ""
|
||||
currentViewedHoldingType = null
|
||||
}
|
||||
|
||||
function setCurrentViewedHoldingType(type) {
|
||||
currentViewedHoldingID = ""
|
||||
currentViewedHoldingType = type
|
||||
}
|
||||
|
||||
function setCurrentViewedHolding(id, type) {
|
||||
currentViewedHoldingID = id
|
||||
currentViewedHoldingType = type
|
||||
}
|
||||
|
||||
property string currentViewedHoldingID: ""
|
||||
property var currentViewedHoldingType
|
||||
|
||||
// This should be exposed to the UI via "walletModule", WalletModule should use
|
||||
// Accounts Service which keeps the info about that (isFirstTimeAccountLogin).
|
||||
// Then in the View of WalletModule we may have either QtProperty or
|
||||
|
|
|
@ -16,7 +16,7 @@ Item {
|
|||
property var collectiblesModel
|
||||
width: parent.width
|
||||
|
||||
signal collectibleClicked(int chainId, string contractAddress, string tokenId)
|
||||
signal collectibleClicked(int chainId, string contractAddress, string tokenId, string uid)
|
||||
|
||||
Loader {
|
||||
id: contentLoader
|
||||
|
@ -64,7 +64,7 @@ Item {
|
|||
backgroundColor: model.backgroundColor ? model.backgroundColor : "transparent"
|
||||
isLoading: !!model.isLoading
|
||||
|
||||
onClicked: root.collectibleClicked(model.chainId, model.contractAddress, model.tokenId)
|
||||
onClicked: root.collectibleClicked(model.chainId, model.contractAddress, model.tokenId, model.uid)
|
||||
}
|
||||
|
||||
ScrollBar.vertical: StatusScrollBar {}
|
||||
|
|
|
@ -8,6 +8,7 @@ import utils 1.0
|
|||
import shared.controls 1.0
|
||||
import shared.views 1.0
|
||||
import shared.stores 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import "./"
|
||||
import "../stores"
|
||||
|
@ -124,6 +125,7 @@ Item {
|
|||
assetDetailsLaunched: stack.currentIndex === 2
|
||||
onAssetClicked: {
|
||||
assetDetailView.token = token
|
||||
RootStore.setCurrentViewedHolding(token.symbol, Constants.HoldingType.Asset)
|
||||
stack.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +133,7 @@ Item {
|
|||
collectiblesModel: RootStore.collectiblesStore.ownedCollectibles
|
||||
onCollectibleClicked: {
|
||||
RootStore.collectiblesStore.getDetailedCollectible(chainId, contractAddress, tokenId)
|
||||
RootStore.setCurrentViewedHolding(uid, Constants.HoldingType.Collectible)
|
||||
stack.currentIndex = 1
|
||||
}
|
||||
}
|
||||
|
@ -151,6 +154,11 @@ Item {
|
|||
Layout.fillHeight: true
|
||||
collectible: RootStore.collectiblesStore.detailedCollectible
|
||||
isCollectibleLoading: RootStore.collectiblesStore.isDetailedCollectibleLoading
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible)
|
||||
RootStore.resetCurrentViewedHolding()
|
||||
}
|
||||
}
|
||||
AssetsDetailView {
|
||||
id: assetDetailView
|
||||
|
@ -163,6 +171,11 @@ Item {
|
|||
address: RootStore.overview.mixedcaseAddress
|
||||
|
||||
networkConnectionStore: root.networkConnectionStore
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible)
|
||||
RootStore.resetCurrentViewedHolding()
|
||||
}
|
||||
}
|
||||
|
||||
TransactionDetailView {
|
||||
|
|
|
@ -1345,18 +1345,29 @@ Item {
|
|||
}
|
||||
property var selectedAccount
|
||||
property bool isBridgeTx
|
||||
property string preSelectedHoldingID
|
||||
property var preSelectedHoldingType
|
||||
|
||||
sourceComponent: SendModal {
|
||||
onlyAssets: false
|
||||
onClosed: {
|
||||
sendModal.closed()
|
||||
sendModal.isBridgeTx = false
|
||||
sendModal.preSelectedHoldingID = ""
|
||||
sendModal.preSelectedHoldingType = Constants.HoldingType.Unknown
|
||||
}
|
||||
}
|
||||
onLoaded: {
|
||||
if (!!sendModal.selectedAccount) {
|
||||
item.selectedAccount = sendModal.selectedAccount
|
||||
}
|
||||
if(isBridgeTx)
|
||||
if(isBridgeTx) {
|
||||
item.isBridgeTx = sendModal.isBridgeTx
|
||||
}
|
||||
if(preSelectedHoldingType !== Constants.HoldingType.Unknown) {
|
||||
item.preSelectedHoldingID = sendModal.preSelectedHoldingID
|
||||
item.preSelectedHoldingType = sendModal.preSelectedHoldingType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
import QtQuick 2.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
StatusListItem {
|
||||
id: root
|
||||
|
||||
property var getNetworkIcon: function(chainId) {
|
||||
return ""
|
||||
}
|
||||
signal itemSelected(var selectedItem)
|
||||
signal itemHovered(var selectedItem, bool hovered)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
function selectItem() {
|
||||
root.itemSelected(model)
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.sensor
|
||||
function onContainsMouseChanged() {
|
||||
root.itemHovered(model, root.sensor.containsMouse)
|
||||
}
|
||||
}
|
||||
|
||||
title: name
|
||||
statusListItemTitleAside.font.pixelSize: 15
|
||||
asset.name: iconUrl ? iconUrl : ""
|
||||
asset.isImage: true
|
||||
asset.width: 32
|
||||
asset.height: 32
|
||||
statusListItemLabel.color: Theme.palette.directColor1
|
||||
statusListItemInlineTagsSlot.spacing: 0
|
||||
|
||||
radius: sensor.containsMouse || root.highlighted ? 0 : 8
|
||||
color: sensor.containsMouse || root.highlighted ? Theme.palette.baseColor2 : "transparent"
|
||||
|
||||
onClicked: d.selectItem()
|
||||
|
||||
components: [
|
||||
StatusRoundedImage {
|
||||
width: 20
|
||||
height: 20
|
||||
image.source: Style.svg("tiny/%1".arg(root.getNetworkIcon(chainId)))
|
||||
visible: !isCollection && root.sensor.containsMouse
|
||||
},
|
||||
StatusIcon {
|
||||
icon: "tiny/chevron-right"
|
||||
color: Theme.palette.baseColor1
|
||||
width: 16
|
||||
height: 16
|
||||
visible: isCollection
|
||||
}
|
||||
]
|
||||
}
|
|
@ -2,6 +2,7 @@ AddressInput 1.0 AddressInput.qml
|
|||
AmountInput 1.0 AmountInput.qml
|
||||
AssetAndAmountInput 1.0 AssetAndAmountInput.qml
|
||||
AssetDelegate 1.0 AssetDelegate.qml
|
||||
CollectibleNestedDelegate 1.0 CollectibleNestedDelegate.qml
|
||||
ContactSelector 1.0 ContactSelector.qml
|
||||
ContactsListAndSearch 1.0 ContactsListAndSearch.qml
|
||||
CopyToClipBoardButton 1.0 CopyToClipBoardButton.qml
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Backpressure 1.0
|
||||
|
||||
import shared.controls 1.0
|
||||
import utils 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var comboBoxModel
|
||||
|
||||
property var selectedItem
|
||||
property var hoveredItem
|
||||
property string defaultIconSource
|
||||
property string placeholderText
|
||||
|
||||
property var itemIconSourceFn: function (item) {
|
||||
return ""
|
||||
}
|
||||
|
||||
property var itemTextFn: function (item) {
|
||||
return ""
|
||||
}
|
||||
|
||||
property alias comboBoxControl: comboBox.control
|
||||
property alias comboBoxDelegate: comboBox.delegate
|
||||
property var comboBoxPopupHeader
|
||||
|
||||
property int contentIconSize: 21
|
||||
property int contentTextSize: 28
|
||||
|
||||
function resetInternal() {
|
||||
items = null
|
||||
selectedItem = null
|
||||
hoveredItem = null
|
||||
}
|
||||
|
||||
function openPopup() {
|
||||
root.comboBoxControl.popup.open()
|
||||
}
|
||||
|
||||
implicitWidth: comboBox.width
|
||||
implicitHeight: comboBox.implicitHeight
|
||||
|
||||
onSelectedItemChanged: {
|
||||
if (!!selectedItem) {
|
||||
d.iconSource = itemIconSourceFn(selectedItem) ?? defaultIconSource
|
||||
d.text = itemTextFn(selectedItem) ?? placeholderText
|
||||
}
|
||||
}
|
||||
|
||||
onHoveredItemChanged: {
|
||||
if (!!hoveredItem) {
|
||||
d.iconSource = itemIconSourceFn(hoveredItem) ?? defaultIconSource
|
||||
d.text = itemTextFn(hoveredItem) ?? placeholderText
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property string iconSource: ""
|
||||
property string text: ""
|
||||
readonly property bool isItemSelected: !!root.selectedItem || !!root.hoveredItem
|
||||
|
||||
}
|
||||
|
||||
StatusComboBox {
|
||||
id: comboBox
|
||||
objectName: "assetSelectorButton"
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
control.padding: 4
|
||||
control.popup.width: 492
|
||||
control.popup.x: -root.x
|
||||
control.popup.verticalPadding: 0
|
||||
|
||||
popupContentItemObjectName: "assetSelectorList"
|
||||
|
||||
model: root.comboBoxModel
|
||||
|
||||
control.background: Rectangle {
|
||||
color: "transparent"
|
||||
border.width: d.isItemSelected ? 0 : 1
|
||||
border.color: Theme.palette.directColor7
|
||||
radius: 12
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
id: rowLayout
|
||||
implicitHeight: 38
|
||||
StatusRoundedImage {
|
||||
Layout.preferredWidth: root.contentIconSize
|
||||
Layout.preferredHeight: root.contentIconSize
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
visible: !!d.iconSource
|
||||
image.source: d.iconSource
|
||||
image.onStatusChanged: {
|
||||
if (image.status === Image.Error) {
|
||||
image.source = root.defaultIconSource
|
||||
}
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
font.pixelSize: root.contentTextSize
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.miscColor1
|
||||
text: d.text
|
||||
visible: d.isItemSelected
|
||||
}
|
||||
StatusIcon {
|
||||
Layout.leftMargin: -3
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 16
|
||||
icon: "chevron-down"
|
||||
color: Theme.palette.miscColor1
|
||||
visible: d.isItemSelected
|
||||
}
|
||||
}
|
||||
|
||||
control.indicator: null
|
||||
|
||||
Component.onCompleted: {
|
||||
control.currentIndex = -1
|
||||
control.popup.contentItem.header = root.comboBoxPopupHeader
|
||||
}
|
||||
|
||||
control.popup.onOpened: {
|
||||
control.currentIndex = -1
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,346 @@
|
|||
|
||||
import QtQml 2.15
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import shared.controls 1.0
|
||||
import utils 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import "../controls"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var assetsModel
|
||||
property var collectiblesModel
|
||||
property string currentCurrencySymbol
|
||||
property bool onlyAssets: true
|
||||
|
||||
implicitWidth: holdingItemSelector.implicitWidth
|
||||
implicitHeight: holdingItemSelector.implicitHeight
|
||||
|
||||
property var searchAssetSymbolByAddressFn: function (address) {
|
||||
return ""
|
||||
}
|
||||
|
||||
property var getNetworkIcon: function(chainId){
|
||||
return ""
|
||||
}
|
||||
|
||||
signal itemHovered(string holdingId, var holdingType)
|
||||
signal itemSelected(string holdingId, var holdingType)
|
||||
|
||||
property alias selectedItem: holdingItemSelector.selectedItem
|
||||
property alias hoveredItem: holdingItemSelector.hoveredItem
|
||||
|
||||
function setSelectedItem(item, holdingType) {
|
||||
d.browsingHoldingType = holdingType
|
||||
holdingItemSelector.selectedItem = null
|
||||
d.currentHoldingType = holdingType
|
||||
holdingItemSelector.selectedItem = item
|
||||
}
|
||||
|
||||
function setHoveredItem(item, holdingType) {
|
||||
d.browsingHoldingType = holdingType
|
||||
holdingItemSelector.hoveredItem = null
|
||||
d.currentHoldingType = holdingType
|
||||
holdingItemSelector.hoveredItem = item
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
// Internal management properties and signals:
|
||||
readonly property var holdingTypes: onlyAssets ?
|
||||
[Constants.HoldingType.Asset] :
|
||||
[Constants.HoldingType.Asset, Constants.HoldingType.Collectible]
|
||||
|
||||
readonly property var tabsModel: onlyAssets ?
|
||||
[qsTr("Assets")] :
|
||||
[qsTr("Assets"), qsTr("Collectibles")]
|
||||
|
||||
readonly property var updateSearchText: Backpressure.debounce(root, 1000, function(inputText) {
|
||||
searchText = inputText
|
||||
})
|
||||
|
||||
function isAsset(type) {
|
||||
return type === Constants.HoldingType.Asset
|
||||
}
|
||||
|
||||
property int browsingHoldingType: Constants.HoldingType.Asset
|
||||
readonly property bool isCurrentBrowsingTypeAsset: isAsset(browsingHoldingType)
|
||||
readonly property bool isBrowsingCollection: !isCurrentBrowsingTypeAsset && !!collectiblesModel && collectiblesModel.currentCollectionUid !== ""
|
||||
property string currentBrowsingCollectionName
|
||||
|
||||
property var currentHoldingType: Constants.HoldingType.Unknown
|
||||
|
||||
property string searchText
|
||||
readonly property string assetSymbolByAddress: isCurrentBrowsingTypeAsset ? "": root.searchAssetSymbolByAddressFn(searchText)
|
||||
readonly property string uppercaseSearchText: searchText.toUpperCase()
|
||||
|
||||
property var assetTextFn: function (asset) {
|
||||
return asset.symbol ? asset.symbol : ""
|
||||
}
|
||||
|
||||
property var assetIconSourceFn: function (asset) {
|
||||
return asset.symbol ? Style.png("tokens/%1".arg(asset.symbol)) : ""
|
||||
}
|
||||
|
||||
property var assetComboBoxModel: SortFilterProxyModel {
|
||||
sourceModel: root.assetsModel
|
||||
filters: [
|
||||
ExpressionFilter {
|
||||
expression: {
|
||||
d.uppercaseSearchText; // Force re-evaluation when searchText changes
|
||||
return visibleForNetwork && (
|
||||
d.uppercaseSearchText === "" ||
|
||||
symbol.startsWith(d.uppercaseSearchText) ||
|
||||
name.toUpperCase().startsWith(d.uppercaseSearchText) |
|
||||
(d.assetSymbolByAddress !== "" && symbol.startsWith(d.assetSymbolByAddress))
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
property var collectibleTextFn: function (item) {
|
||||
if (!!item) {
|
||||
return !!item.collectionName ? item.collectionName + ": " + item.name : item.name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
property var collectibleIconSourceFn: function (item) {
|
||||
return item.iconUrl ? item.iconUrl : ""
|
||||
}
|
||||
|
||||
property var collectibleComboBoxModel: SortFilterProxyModel {
|
||||
sourceModel: root.collectiblesModel
|
||||
filters: [
|
||||
ExpressionFilter {
|
||||
expression: {
|
||||
return d.uppercaseSearchText === "" || name.toUpperCase().startsWith(d.uppercaseSearchText)
|
||||
}
|
||||
}
|
||||
]
|
||||
sorters: RoleSorter {
|
||||
roleName: "isCollection"
|
||||
sortOrder: Qt.DescendingOrder
|
||||
}
|
||||
}
|
||||
|
||||
readonly property string searchPlaceholderText: {
|
||||
if (isCurrentBrowsingTypeAsset) {
|
||||
return qsTr("Search for token or enter token address")
|
||||
} else if (isBrowsingCollection) {
|
||||
return qsTr("Search %1").arg(d.currentBrowsingCollectionName ?? qsTr("collectibles in collection"))
|
||||
} else {
|
||||
return qsTr("Search collectibles")
|
||||
}
|
||||
}
|
||||
|
||||
// By design values:
|
||||
readonly property int padding: 16
|
||||
readonly property int headerTopMargin: 5
|
||||
readonly property int tabBarTopMargin: 20
|
||||
readonly property int tabBarHeight: 35
|
||||
readonly property int backButtonWidth: 56
|
||||
readonly property int backButtonHeight: 24
|
||||
readonly property int backButtonToContentSpace: 8
|
||||
readonly property int bottomInset: 20
|
||||
readonly property int assetContentIconSize: 21
|
||||
readonly property int collectibleContentIconSize: 28
|
||||
readonly property int assetContentTextSize: 28
|
||||
readonly property int collectibleContentTextSize: 15
|
||||
}
|
||||
|
||||
HoldingItemSelector {
|
||||
id: holdingItemSelector
|
||||
anchors.fill: parent
|
||||
|
||||
defaultIconSource: Style.png("tokens/DEFAULT-TOKEN@3x")
|
||||
placeholderText: d.isCurrentBrowsingTypeAsset ? qsTr("Select token") : qsTr("Select collectible")
|
||||
comboBoxDelegate: Item {
|
||||
property var itemModel: model // read 'model' from the delegate's context
|
||||
width: loader.width
|
||||
height: loader.height
|
||||
Loader {
|
||||
id: loader
|
||||
|
||||
// inject model properties to the loaded item's context
|
||||
// common
|
||||
property var model: itemModel
|
||||
property var chainId: model.chainId
|
||||
property var name: model.name
|
||||
// asset
|
||||
property var symbol: model.symbol
|
||||
property var totalBalance: model.totalBalance
|
||||
property var totalCurrencyBalance: model.totalCurrencyBalance
|
||||
property var decimals: model.decimals
|
||||
property var balances: model.balances
|
||||
// collectible
|
||||
property var uid: model.uid
|
||||
property var iconUrl: model.iconUrl
|
||||
property var collectionUid: model.collectionUid
|
||||
property var collectionName: model.collectionName
|
||||
property var isCollection: model.isCollection
|
||||
|
||||
sourceComponent: d.isCurrentBrowsingTypeAsset ? assetComboBoxDelegate : collectibleComboBoxDelegate
|
||||
}
|
||||
}
|
||||
|
||||
comboBoxPopupHeader: headerComponent
|
||||
itemTextFn: d.isCurrentBrowsingTypeAsset ? d.assetTextFn : d.collectibleTextFn
|
||||
itemIconSourceFn: d.isCurrentBrowsingTypeAsset ? d.assetIconSourceFn : d.collectibleIconSourceFn
|
||||
comboBoxModel: d.isCurrentBrowsingTypeAsset ? d.assetComboBoxModel : d.collectibleComboBoxModel
|
||||
|
||||
contentIconSize: d.isAsset(d.currentHoldingType) ? d.assetContentIconSize : d.collectibleContentIconSize
|
||||
contentTextSize: d.isAsset(d.currentHoldingType) ? d.assetContentTextSize : d.collectibleContentTextSize
|
||||
}
|
||||
|
||||
Component {
|
||||
id: headerComponent
|
||||
ColumnLayout {
|
||||
width: holdingItemSelector.comboBoxControl.popup.width
|
||||
Layout.topMargin: d.headerTopMargin
|
||||
spacing: -1 // Used to overlap rectangles from row components
|
||||
|
||||
StatusTabBar {
|
||||
id: tabBar
|
||||
|
||||
visible: !root.onlyAssets
|
||||
Layout.preferredHeight: d.tabBarHeight
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: d.padding
|
||||
Layout.rightMargin: d.padding
|
||||
Layout.topMargin: d.tabBarTopMargin
|
||||
Layout.bottomMargin: 6
|
||||
currentIndex: d.holdingTypes.indexOf(d.browsingHoldingType)
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
if (currentIndex >= 0) {
|
||||
d.browsingHoldingType = d.holdingTypes[currentIndex]
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: tabLabelsRepeater
|
||||
model: d.tabsModel
|
||||
|
||||
StatusTabButton {
|
||||
text: modelData
|
||||
width: implicitWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
visible: d.isBrowsingCollection
|
||||
|
||||
color: "transparent"
|
||||
border.color: Theme.palette.baseColor2
|
||||
border.width: 1
|
||||
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
|
||||
StatusIconTextButton {
|
||||
id: backButton
|
||||
|
||||
Layout.preferredWidth: d.backButtonWidth
|
||||
Layout.preferredHeight: d.backButtonHeight
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
Layout.leftMargin: d.padding
|
||||
|
||||
statusIcon: "previous"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
text: qsTr("Back")
|
||||
|
||||
onClicked: {
|
||||
if (!d.isCurrentBrowsingTypeAsset) {
|
||||
root.collectiblesModel.currentCollectionUid = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: d.padding
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignRight
|
||||
text: "%1 %2".arg(collectiblesModel.count).arg(d.currentBrowsingCollectionName)
|
||||
font.pixelSize: 13
|
||||
lineHeight: 18
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: searchInput.input.implicitHeight
|
||||
|
||||
color: "transparent"
|
||||
border.color: Theme.palette.baseColor2
|
||||
border.width: 1
|
||||
|
||||
StatusInput {
|
||||
id: searchInput
|
||||
anchors.fill: parent
|
||||
|
||||
input.showBackground: false
|
||||
placeholderText: d.searchPlaceholderText
|
||||
onTextChanged: Qt.callLater(d.updateSearchText, text)
|
||||
input.clearable: true
|
||||
input.implicitHeight: 56
|
||||
input.rightComponent: StatusFlatRoundButton {
|
||||
icon.name: "search"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: assetComboBoxDelegate
|
||||
TokenBalancePerChainDelegate {
|
||||
objectName: "AssetSelector_ItemDelegate_" + symbol
|
||||
width: holdingItemSelector.comboBoxControl.popup.width
|
||||
getNetworkIcon: root.getNetworkIcon
|
||||
onTokenSelected: {
|
||||
holdingItemSelector.selectedItem = selectedToken
|
||||
d.currentHoldingType = Constants.HoldingType.Asset
|
||||
root.itemSelected(selectedToken.symbol, Constants.HoldingType.Asset)
|
||||
holdingItemSelector.comboBoxControl.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: collectibleComboBoxDelegate
|
||||
CollectibleNestedDelegate {
|
||||
objectName: "CollectibleSelector_ItemDelegate_" + collectionUid
|
||||
width: holdingItemSelector.comboBoxControl.popup.width
|
||||
getNetworkIcon: root.getNetworkIcon
|
||||
onItemSelected: {
|
||||
if (isCollection) {
|
||||
d.currentBrowsingCollectionName = collectionName
|
||||
root.collectiblesModel.currentCollectionUid = collectionUid
|
||||
} else {
|
||||
holdingItemSelector.selectedItem = selectedItem
|
||||
d.currentHoldingType = Constants.HoldingType.Collectible
|
||||
root.itemSelected(selectedItem.uid, Constants.HoldingType.Collectible)
|
||||
holdingItemSelector.comboBoxControl.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,9 @@ Separator 1.0 Separator.qml
|
|||
SeparatorWithIcon 1.0 SeparatorWithIcon.qml
|
||||
SequenceColumnLayout 1.0 SequenceColumnLayout.qml
|
||||
SplitViewHandle 1.0 SplitViewHandle.qml
|
||||
HoldingItemSelector 1.0 HoldingItemSelector.qml
|
||||
HoldingSelector 1.0 HoldingSelector.qml
|
||||
HoldingTypes 1.0 HoldingTypes.qml
|
||||
StatusAssetSelector 1.0 StatusAssetSelector.qml
|
||||
StyledText 1.0 StyledText.qml
|
||||
TextWithLabel 1.0 TextWithLabel.qml
|
||||
|
|
|
@ -28,14 +28,19 @@ StatusDialog {
|
|||
|
||||
property string preSelectedRecipient
|
||||
property string preDefinedAmountToSend
|
||||
property var preSelectedAsset
|
||||
property var preSelectedHolding
|
||||
property string preSelectedHoldingID
|
||||
property var preSelectedHoldingType
|
||||
property bool interactive: true
|
||||
property alias onlyAssets: holdingSelector.onlyAssets
|
||||
|
||||
property alias modalHeader: modalHeader.text
|
||||
|
||||
property var store: TransactionStore{}
|
||||
property var currencyStore: store.currencyStore
|
||||
property var selectedAccount: store.selectedSenderAccount
|
||||
property var collectiblesModel: store.collectiblesModel
|
||||
property var nestedCollectiblesModel: store.nestedCollectiblesModel
|
||||
property var bestRoutes
|
||||
property alias addressText: recipientLoader.addressText
|
||||
property bool isLoading: false
|
||||
|
@ -59,9 +64,9 @@ StatusDialog {
|
|||
}
|
||||
|
||||
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
|
||||
if(!!popup.selectedAccount && !!assetSelector.selectedAsset && recipientLoader.ready && amountToSendInput.inputNumberValid) {
|
||||
if(!!popup.selectedAccount && d.isSelectedHoldingValidAsset && recipientLoader.ready && amountToSendInput.inputNumberValid) {
|
||||
popup.isLoading = true
|
||||
let amount = Math.round(amountToSendInput.cryptoValueToSend * Math.pow(10, assetSelector.selectedAsset.decimals))
|
||||
let amount = Math.round(amountToSendInput.cryptoValueToSend * Math.pow(10, d.selectedHolding.decimals))
|
||||
popup.store.suggestedRoutes(amount.toString(16), popup.sendType)
|
||||
}
|
||||
})
|
||||
|
@ -72,8 +77,8 @@ StatusDialog {
|
|||
(popup.bestRoutes && popup.bestRoutes.count === 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 maxFiatBalance: isSelectedHoldingValidAsset ? selectedHolding.totalCurrencyBalance.amount : 0
|
||||
readonly property double maxCryptoBalance: isSelectedHoldingValidAsset ? selectedHolding.totalBalance.amount : 0
|
||||
readonly property double maxInputBalance: amountToSendInput.inputIsFiat ? maxFiatBalance : maxCryptoBalance
|
||||
readonly property string selectedSymbol: store.selectedAssetSymbol
|
||||
readonly property string inputSymbol: amountToSendInput.inputIsFiat ? popup.currencyStore.currentCurrency : selectedSymbol
|
||||
|
@ -83,6 +88,37 @@ StatusDialog {
|
|||
property string totalTimeEstimate
|
||||
property double totalFeesInFiat
|
||||
property double totalAmountToReceive
|
||||
|
||||
property var selectedHolding: null
|
||||
property var selectedHoldingType: Constants.HoldingType.Unknown
|
||||
readonly property bool isSelectedHoldingValidAsset: !!selectedHolding && selectedHoldingType === Constants.HoldingType.Asset
|
||||
property var hoveredHolding: null
|
||||
property var hoveredHoldingType: Constants.HoldingType.Unknown
|
||||
readonly property bool isHoveredHoldingValidAsset: !!hoveredHolding && hoveredHoldingType === Constants.HoldingType.Asset
|
||||
|
||||
function setSelectedHoldingId(holdingId, holdingType) {
|
||||
let holding = store.getHolding(holdingId, holdingType)
|
||||
setSelectedHolding(holding, holdingType)
|
||||
}
|
||||
|
||||
function setSelectedHolding(holding, holdingType) {
|
||||
d.selectedHolding = holding
|
||||
d.selectedHoldingType = holdingType
|
||||
let selectorHolding = store.holdingToSelectorHolding(holding, holdingType)
|
||||
holdingSelector.setSelectedItem(selectorHolding, holdingType)
|
||||
}
|
||||
|
||||
function setHoveredHoldingId(holdingId, holdingType) {
|
||||
let holding = store.getHolding(holdingId, holdingType)
|
||||
setHoveredHolding(holding, holdingType)
|
||||
}
|
||||
|
||||
function setHoveredHolding(holding, holdingType) {
|
||||
d.hoveredHolding = holding
|
||||
d.hoveredHoldingType = holdingType
|
||||
let selectorHolding = store.holdingToSelectorHolding(holding, holdingType)
|
||||
holdingSelector.setHoveredItem(selectorHolding, holdingType)
|
||||
}
|
||||
}
|
||||
|
||||
width: 556
|
||||
|
@ -99,8 +135,12 @@ StatusDialog {
|
|||
onOpened: {
|
||||
amountToSendInput.input.input.edit.forceActiveFocus()
|
||||
|
||||
if(!!popup.preSelectedAsset) {
|
||||
assetSelector.selectedAsset = popup.preSelectedAsset
|
||||
if (popup.preSelectedHoldingType !== Constants.HoldingType.Unknown) {
|
||||
if(!!popup.preSelectedHolding) {
|
||||
d.setSelectedHolding(popup.preSelectedHolding, popup.preSelectedHoldingType)
|
||||
} else if (!!popup.preSelectedHoldingID) {
|
||||
d.setSelectedHoldingId(popup.preSelectedHoldingID, popup.preSelectedHoldingType)
|
||||
}
|
||||
}
|
||||
|
||||
if(!!popup.preDefinedAmountToSend) {
|
||||
|
@ -118,8 +158,6 @@ StatusDialog {
|
|||
}
|
||||
}
|
||||
|
||||
onClosed: popup.store.resetTxStoreProperties()
|
||||
|
||||
header: AccountsModalHeader {
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: -height - 18
|
||||
|
@ -176,6 +214,7 @@ StatusDialog {
|
|||
StatusBaseText {
|
||||
id: modalHeader
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: popup.isBridgeTx ? qsTr("Bridge") : qsTr("Send")
|
||||
font.pixelSize: 28
|
||||
lineHeight: 38
|
||||
|
@ -184,45 +223,29 @@ StatusDialog {
|
|||
color: Theme.palette.directColor1
|
||||
Layout.maximumWidth: contentWidth
|
||||
}
|
||||
StatusAssetSelector {
|
||||
id: assetSelector
|
||||
HoldingSelector {
|
||||
id: holdingSelector
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||
enabled: popup.interactive
|
||||
assets: popup.selectedAccount && popup.selectedAccount.assets ? popup.selectedAccount.assets : null
|
||||
defaultToken: Style.png("tokens/DEFAULT-TOKEN@3x")
|
||||
placeholderText: qsTr("Select token")
|
||||
Layout.fillHeight: true
|
||||
assetsModel: popup.selectedAccount && popup.selectedAccount.assets ? popup.selectedAccount.assets : null
|
||||
collectiblesModel: popup.selectedAccount ? popup.nestedCollectiblesModel : null
|
||||
currentCurrencySymbol: RootStore.currencyStore.currentCurrencySymbol
|
||||
tokenAssetSourceFn: function (symbol) {
|
||||
return symbol ? Style.png("tokens/%1".arg(symbol)) : defaultToken
|
||||
}
|
||||
searchTokenSymbolByAddressFn: function (address) {
|
||||
return store.findTokenSymbolByAddress(address)
|
||||
}
|
||||
visible: !!d.selectedHolding || !!d.hoveredHolding
|
||||
getNetworkIcon: function(chainId){
|
||||
return RootStore.getNetworkIcon(chainId)
|
||||
}
|
||||
onAssetsChanged: {
|
||||
// Todo we should not need to do this, this should be automatic when selected account changes
|
||||
if(!!selectedAccount && !!assetSelector.selectedAsset)
|
||||
assetSelector.selectedAsset = store.getAsset(selectedAccount.assets, assetSelector.selectedAsset.symbol)
|
||||
onItemSelected: {
|
||||
d.setSelectedHoldingId(holdingId, holdingType)
|
||||
}
|
||||
onSelectedAssetChanged: {
|
||||
store.setSelectedAssetSymbol(assetSelector.selectedAsset.symbol)
|
||||
if (!assetSelector.selectedAsset || !amountToSendInput.inputNumberValid) {
|
||||
return
|
||||
}
|
||||
popup.recalculateRoutesAndFees()
|
||||
}
|
||||
visible: !!assetSelector.selectedAsset || !!assetSelector.hoveredToken
|
||||
}
|
||||
|
||||
StatusListItemTag {
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
Layout.preferredHeight: 22
|
||||
visible: !!assetSelector.selectedAsset || !!assetSelector.hoveredToken
|
||||
visible: d.isSelectedHoldingValidAsset || d.isHoveredHoldingValidAsset
|
||||
title: {
|
||||
if(!!assetSelector.hoveredToken) {
|
||||
const balance = popup.currencyStore.formatCurrencyAmount((amountToSendInput.inputIsFiat ? assetSelector.hoveredToken.totalCurrencyBalance.amount : assetSelector.hoveredToken.totalBalance.amount) , assetSelector.hoveredToken.symbol)
|
||||
if(d.isHoveredHoldingValidAsset) {
|
||||
const balance = popup.currencyStore.formatCurrencyAmount((amountToSendInput.inputIsFiat ? d.hoveredHolding.totalCurrencyBalance.amount : d.hoveredHolding.totalBalance.amount) , d.hoveredHolding.symbol)
|
||||
return qsTr("Max: %1").arg(balance)
|
||||
}
|
||||
if (d.maxInputBalance <= 0)
|
||||
|
@ -245,7 +268,7 @@ StatusDialog {
|
|||
|
||||
Layout.fillWidth: true
|
||||
|
||||
visible: !assetSelector.selectedAsset
|
||||
visible: !d.selectedHolding
|
||||
assets: popup.selectedAccount && popup.selectedAccount.assets ? popup.selectedAccount.assets : null
|
||||
searchTokenSymbolByAddressFn: function (address) {
|
||||
return store.findTokenSymbolByAddress(address)
|
||||
|
@ -254,17 +277,18 @@ StatusDialog {
|
|||
return RootStore.getNetworkIcon(chainId)
|
||||
}
|
||||
onTokenSelected: {
|
||||
assetSelector.selectedAsset = selectedToken
|
||||
d.setSelectedHoldingId(symbol, Constants.HoldingType.Asset)
|
||||
}
|
||||
onTokenHovered: {
|
||||
if(hovered)
|
||||
assetSelector.hoveredToken = selectedToken
|
||||
else
|
||||
assetSelector.hoveredToken = null
|
||||
if(hovered) {
|
||||
d.setHoveredHoldingId(symbol, Constants.HoldingType.Asset)
|
||||
} else {
|
||||
d.setHoveredHoldingId("", Constants.HoldingType.Unknown)
|
||||
}
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
visible: !!assetSelector.selectedAsset
|
||||
visible: d.isSelectedHoldingValidAsset
|
||||
AmountToSend {
|
||||
id: amountToSendInput
|
||||
Layout.fillWidth:true
|
||||
|
@ -342,7 +366,7 @@ StatusDialog {
|
|||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.bigPadding
|
||||
anchors.rightMargin: Style.current.bigPadding
|
||||
visible: !isBridgeTx && !!assetSelector.selectedAsset
|
||||
visible: !isBridgeTx && !!d.selectedHolding
|
||||
StatusBaseText {
|
||||
id: label
|
||||
elide: Text.ElideRight
|
||||
|
@ -356,7 +380,7 @@ StatusDialog {
|
|||
store: popup.store
|
||||
isBridgeTx: popup.isBridgeTx
|
||||
interactive: popup.interactive
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
selectedAsset: d.selectedHolding
|
||||
onIsLoading: popup.isLoading = true
|
||||
onRecalculateRoutesAndFees: popup.recalculateRoutesAndFees()
|
||||
}
|
||||
|
@ -374,7 +398,7 @@ StatusDialog {
|
|||
recipientLoader.selectedRecipientType = type
|
||||
recipientLoader.selectedRecipient = recipient
|
||||
}
|
||||
visible: !recipientLoader.ready && !isBridgeTx && !!assetSelector.selectedAsset
|
||||
visible: !recipientLoader.ready && !isBridgeTx && !!d.selectedHolding
|
||||
}
|
||||
|
||||
NetworkSelector {
|
||||
|
@ -390,9 +414,9 @@ StatusDialog {
|
|||
amountToSend: amountToSendInput.cryptoValueToSend
|
||||
minSendCryptoDecimals: amountToSendInput.minSendCryptoDecimals
|
||||
minReceiveCryptoDecimals: amountToSendInput.minReceiveCryptoDecimals
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
selectedAsset: d.selectedHolding
|
||||
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
|
||||
visible: recipientLoader.ready && !!assetSelector.selectedAsset && amountToSendInput.inputNumberValid
|
||||
visible: recipientLoader.ready && !!d.selectedHolding && amountToSendInput.inputNumberValid
|
||||
errorType: d.errorType
|
||||
isLoading: popup.isLoading
|
||||
isBridgeTx: popup.isBridgeTx
|
||||
|
@ -404,7 +428,7 @@ StatusDialog {
|
|||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.bigPadding
|
||||
anchors.rightMargin: Style.current.bigPadding
|
||||
visible: recipientLoader.ready && !!assetSelector.selectedAsset && networkSelector.advancedOrCustomMode && amountToSendInput.inputNumberValid
|
||||
visible: recipientLoader.ready && !!d.selectedHolding && networkSelector.advancedOrCustomMode && amountToSendInput.inputNumberValid
|
||||
selectedTokenSymbol: d.selectedSymbol
|
||||
isLoading: popup.isLoading
|
||||
bestRoutes: popup.bestRoutes
|
||||
|
@ -439,7 +463,7 @@ StatusDialog {
|
|||
d.totalTimeEstimate = popup.store.getLabelForEstimatedTxTime(gasTimeEstimate.totalTime)
|
||||
d.totalFeesInFiat = popup.currencyStore.getFiatValue( gasTimeEstimate.totalFeesInEth, "ETH", popup.currencyStore.currentCurrency) +
|
||||
popup.currencyStore.getFiatValue(gasTimeEstimate.totalTokenFees, fees.selectedTokenSymbol, popup.currencyStore.currentCurrency)
|
||||
d.totalAmountToReceive = popup.store.getWei2Eth(txRoutes.amountToReceive, assetSelector.selectedAsset.decimals)
|
||||
d.totalAmountToReceive = popup.store.getWei2Eth(txRoutes.amountToReceive, d.selectedHolding.decimals)
|
||||
networkSelector.toNetworksList = txRoutes.toNetworksModel
|
||||
popup.isLoading = false
|
||||
}
|
||||
|
|
|
@ -202,7 +202,8 @@ Item {
|
|||
sendType: Constants.SendType.StickersBuy
|
||||
preSelectedRecipient: root.store.stickersStore.getStickersMarketAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(parseFloat(price))
|
||||
preSelectedAsset: store.getAsset(buyStickersModal.store.assets, JSON.parse(root.store.stickersStore.getStatusToken()).symbol)
|
||||
preSelectedHolding: store.getAsset(buyStickersModal.store.assets, JSON.parse(root.store.stickersStore.getStatusToken()).symbol)
|
||||
preSelectedHoldingType: Constants.HoldingType.Asset
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.count === 1) {
|
||||
let path = bestRoutes.firstItem()
|
||||
|
|
|
@ -71,7 +71,8 @@ ModalPopup {
|
|||
sendType: Constants.SendType.StickersBuy
|
||||
preSelectedRecipient: stickerPackDetailsPopup.store.stickersStore.getStickersMarketAddress()
|
||||
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(parseFloat(price))
|
||||
preSelectedAsset: store.getAsset(buyStickersPackModal.store.assets, JSON.parse(stickerPackDetailsPopup.store.stickersStore.getStatusToken()).symbol)
|
||||
preSelectedHolding: store.getAsset(buyStickersPackModal.store.assets, JSON.parse(stickerPackDetailsPopup.store.stickersStore.getStatusToken()).symbol)
|
||||
preSelectedHoldingType: Constants.HoldingType.Asset
|
||||
sendTransaction: function() {
|
||||
if(bestRoutes.count === 1) {
|
||||
let path = bestRoutes.firstItem()
|
||||
|
|
|
@ -6,6 +6,8 @@ import shared.stores 1.0
|
|||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
|
@ -19,6 +21,8 @@ QtObject {
|
|||
property var senderAccounts: walletSectionSendInst.senderAccounts
|
||||
property var selectedSenderAccount: walletSectionSendInst.selectedSenderAccount
|
||||
property var accounts: walletSectionSendInst.accounts
|
||||
property var collectiblesModel: walletSectionSendInst.collectiblesModel
|
||||
property var nestedCollectiblesModel: walletSectionSendInst.nestedCollectiblesModel
|
||||
property bool areTestNetworksEnabled: networksModule.areTestNetworksEnabled
|
||||
property var tmpActivityController: walletSection.tmpActivityController
|
||||
property var savedAddressesModel: SortFilterProxyModel {
|
||||
|
@ -105,6 +109,68 @@ QtObject {
|
|||
return {}
|
||||
}
|
||||
|
||||
function getCollectible(uid) {
|
||||
const idx = ModelUtils.indexOf(collectiblesModel, "uid", uid)
|
||||
if (idx < 0) {
|
||||
return {}
|
||||
}
|
||||
return ModelUtils.get(collectiblesModel, idx)
|
||||
}
|
||||
|
||||
function getSelectorCollectible(uid) {
|
||||
const idx = ModelUtils.indexOf(nestedCollectiblesModel, "uid", uid)
|
||||
if (idx < 0) {
|
||||
return {}
|
||||
}
|
||||
return ModelUtils.get(nestedCollectiblesModel, idx)
|
||||
}
|
||||
|
||||
function getHolding(holdingId, holdingType) {
|
||||
if (holdingType === Constants.HoldingType.Asset) {
|
||||
return getAsset(selectedSenderAccount.assets, holdingId)
|
||||
} else if (holdingType === Constants.HoldingType.Collectible) {
|
||||
return getCollectible(holdingId)
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectorHolding(holdingId, holdingType) {
|
||||
if (holdingType === Constants.HoldingType.Asset) {
|
||||
return getAsset(selectedSenderAccount.assets, holdingId)
|
||||
} else if (holdingType === Constants.HoldingType.Collectible) {
|
||||
return getSelectorCollectible(holdingId)
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function assetToSelectorAsset(asset) {
|
||||
return asset
|
||||
}
|
||||
|
||||
function collectibleToSelectorCollectible(collectible) {
|
||||
return {
|
||||
uid: collectible.uid,
|
||||
chainId: collectible.chainId,
|
||||
name: collectible.name,
|
||||
iconUrl: collectible.imageUrl,
|
||||
collectionUid: collectible.collectionUid,
|
||||
collectionName: collectible.collectionName,
|
||||
isCollection: false
|
||||
}
|
||||
}
|
||||
|
||||
function holdingToSelectorHolding(holding, holdingType) {
|
||||
if (holdingType === Constants.HoldingType.Asset) {
|
||||
return assetToSelectorAsset(holding)
|
||||
} else if (holdingType === Constants.HoldingType.Collectible) {
|
||||
return collectibleToSelectorCollectible(holding)
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function switchSenderAccount(index) {
|
||||
walletSectionSendInst.switchSenderAccount(index)
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ Item {
|
|||
id: root
|
||||
|
||||
property var assets: null
|
||||
signal tokenSelected(var selectedToken)
|
||||
signal tokenHovered(var selectedToken, bool hovered)
|
||||
signal tokenSelected(string symbol)
|
||||
signal tokenHovered(string symbol, bool hovered)
|
||||
property var searchTokenSymbolByAddressFn: function (address) {
|
||||
return ""
|
||||
}
|
||||
|
@ -84,8 +84,8 @@ Item {
|
|||
delegate: TokenBalancePerChainDelegate {
|
||||
width: ListView.view.width
|
||||
getNetworkIcon: root.getNetworkIcon
|
||||
onTokenSelected: root.tokenSelected(selectedToken)
|
||||
onTokenHovered: root.tokenHovered(selectedToken, hovered)
|
||||
onTokenSelected: root.tokenSelected(symbol)
|
||||
onTokenHovered: root.tokenHovered(symbol, hovered)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1211,4 +1211,8 @@ QtObject {
|
|||
Link = 0,
|
||||
Image = 1
|
||||
}
|
||||
|
||||
enum HoldingType {
|
||||
Unknown, Asset, Collectible
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue