fix(@desktop/wallet): properly handle collectible groups in send modal

Fixes #14080
This commit is contained in:
Dario Gabriel Lipicar 2024-03-27 13:18:45 -03:00 committed by dlipicar
parent cb6c633e69
commit cd3a1180b0
14 changed files with 250 additions and 170 deletions

View File

@ -358,9 +358,11 @@ method filterChanged*(self: Module, addresses: seq[string], chainIds: seq[int])
self.view.switchReceiveAccountByAddress(addresses[0]) self.view.switchReceiveAccountByAddress(addresses[0])
proc updateCollectiblesFilter*(self: Module) = proc updateCollectiblesFilter*(self: Module) =
let addresses = @[self.view.getSenderAddressByIndex(self.senderCurrentAccountIndex)] let senderAddress = self.view.getSenderAddressByIndex(self.senderCurrentAccountIndex)
let addresses = @[senderAddress]
let chainIds = self.controller.getChainIds() let chainIds = self.controller.getChainIds()
self.collectiblesController.setFilterAddressesAndChains(addresses, chainIds) self.collectiblesController.setFilterAddressesAndChains(addresses, chainIds)
self.nestedCollectiblesModel.setAddress(senderAddress)
method setSelectedSenderAccountIndex*(self: Module, index: int) = method setSelectedSenderAccountIndex*(self: Module, index: int) =
self.senderCurrentAccountIndex = index self.senderCurrentAccountIndex = index

View File

@ -71,3 +71,11 @@ QtObject:
self.items = items self.items = items
self.endResetModel() self.endResetModel()
self.countChanged() self.countChanged()
proc getBalance*(self: OwnershipModel, address: string): UInt256 =
var balance = stint.u256(0)
for item in self.items:
if item.address.toUpper == address.toUpper:
balance += item.balance
break
return balance

View File

@ -234,11 +234,13 @@ QtObject:
notify = traitsChanged notify = traitsChanged
proc ownershipChanged*(self: CollectiblesEntry) {.signal.} proc ownershipChanged*(self: CollectiblesEntry) {.signal.}
proc getOwnershipModel*(self: CollectiblesEntry): QVariant {.slot.} = proc getOwnershipModel*(self: CollectiblesEntry): OwnershipModel =
return self.ownership
proc getOwnershipModelAsVariant*(self: CollectiblesEntry): QVariant {.slot.} =
return newQVariant(self.ownership) return newQVariant(self.ownership)
QtProperty[QVariant] ownership: QtProperty[QVariant] ownership:
read = getOwnershipModel read = getOwnershipModelAsVariant
notify = ownershipChanged notify = ownershipChanged
proc communityIdChanged*(self: CollectiblesEntry) {.signal.} proc communityIdChanged*(self: CollectiblesEntry) {.signal.}

View File

@ -188,7 +188,7 @@ QtObject:
of CollectibleRole.IsLoading: of CollectibleRole.IsLoading:
result = newQVariant(false) result = newQVariant(false)
of CollectibleRole.Ownership: of CollectibleRole.Ownership:
result = newQVariant(item.getOwnershipModel()) result = item.getOwnershipModelAsVariant()
of CollectibleRole.CommunityId: of CollectibleRole.CommunityId:
result = newQVariant(item.getCommunityId()) result = newQVariant(item.getCommunityId())
of CollectibleRole.CommunityName: of CollectibleRole.CommunityName:

View File

@ -1,37 +1,46 @@
import stew/shims/strformat import stew/shims/strformat
import app_service/common/types import app_service/common/types
import stint
type
ItemType* {.pure.} = enum
CommunityCollectible = 0,
NonCommunityCollectible = 1,
Collection = 2,
Community = 3
type type
Item* = object Item* = object
id: string # Collectible ID if isCollection=false, Collection Slug otherwise id: string # CollectibleID if single collectible, GroupID (CollectionID/CommunityID) otherwise
chainId: int chainId: int
name: string name: string
iconUrl: string iconUrl: string
collectionId: string groupId: string
collectionName: string groupName: string
isCollection: bool
communityId: string
tokenType: TokenType tokenType: TokenType
itemType: ItemType
count: UInt256
proc initItem*( proc initItem*(
id: string, id: string,
chainId: int, chainId: int,
name: string, name: string,
iconUrl: string, iconUrl: string,
collectionId: string, groupId: string,
collectionName: string, groupName: string,
isCollection: bool, tokenType: TokenType,
communityId: string, itemType: ItemType,
tokenType: TokenType count: UInt256,
): Item = ): Item =
result.id = id result.id = id
result.chainId = chainId result.chainId = chainId
result.name = name result.name = name
result.iconUrl = iconUrl result.iconUrl = iconUrl
result.collectionId = collectionId result.groupId = groupId
result.collectionName = collectionName result.groupName = groupName
result.isCollection = isCollection
result.tokenType = tokenType result.tokenType = tokenType
result.itemType = itemType
result.count = count
proc `$`*(self: Item): string = proc `$`*(self: Item): string =
result = fmt"""CollectiblesNestedEntry( result = fmt"""CollectiblesNestedEntry(
@ -39,11 +48,11 @@ proc `$`*(self: Item): string =
chainId: {self.chainId}, chainId: {self.chainId},
name: {self.name}, name: {self.name},
iconUrl: {self.iconUrl}, iconUrl: {self.iconUrl},
collectionId: {self.collectionId}, groupId: {self.groupId},
collectionName: {self.collectionName}, groupName: {self.groupName},
isCollection: {self.isCollection},
communityId: {self.communityId},
tokenType: {self.tokenType}, tokenType: {self.tokenType},
itemType: {self.itemType},
count: {self.count},
]""" ]"""
proc getId*(self: Item): string = proc getId*(self: Item): string =
@ -58,17 +67,20 @@ proc getName*(self: Item): string =
proc getIconUrl*(self: Item): string = proc getIconUrl*(self: Item): string =
return self.iconUrl return self.iconUrl
proc getCollectionId*(self: Item): string = proc getGroupId*(self: Item): string =
return self.collectionId return self.groupId
proc getCollectionName*(self: Item): string = proc getGroupName*(self: Item): string =
return self.collectionName return self.groupName
proc getIsCollection*(self: Item): bool =
return self.isCollection
proc getCommunityId*(self: Item): string =
return self.communityId
proc getTokenType*(self: Item): int = proc getTokenType*(self: Item): int =
return self.tokenType.int return self.tokenType.int
proc getItemType*(self: Item): int =
return self.itemType.int
proc getCount*(self: Item): UInt256 =
return self.count
proc getCountAsString*(self: Item): string =
return $self.count

View File

@ -1,5 +1,7 @@
import NimQml, Tables, strutils, stew/shims/strformat, sequtils import NimQml, Tables, strutils, stew/shims/strformat, sequtils
import stint
import ./collectible_ownership_model
import ./collectibles_model as flat_model import ./collectibles_model as flat_model
import ./collectibles_entry as flat_item import ./collectibles_entry as flat_item
import ./collectibles_nested_item as nested_item import ./collectibles_nested_item as nested_item
@ -12,18 +14,22 @@ type
ChainId ChainId
Name Name
IconUrl IconUrl
CollectionUid GroupId
CollectionName GroupName
IsCollection
CommunityId
TokenType TokenType
ItemType
Count
type
CollectiblesPerGroupId = Table[string, seq[flat_item.CollectiblesEntry]]
QtObject: QtObject:
type type
Model* = ref object of QAbstractListModel Model* = ref object of QAbstractListModel
flatModel: flat_model.Model flatModel: flat_model.Model
items: seq[nested_item.Item] items: seq[nested_item.Item]
currentCollectionUid: string currentGroupId: string
address: string
proc delete(self: Model) = proc delete(self: Model) =
self.items = @[] self.items = @[]
@ -36,7 +42,7 @@ QtObject:
new(result, delete) new(result, delete)
result.flatModel = flatModel result.flatModel = flatModel
result.items = @[] result.items = @[]
result.currentCollectionUid = "" result.currentGroupId = ""
result.setup result.setup
signalConnect(result.flatModel, "countChanged()", result, "refreshItems()") signalConnect(result.flatModel, "countChanged()", result, "refreshItems()")
@ -48,7 +54,7 @@ QtObject:
proc `$`*(self: Model): string = proc `$`*(self: Model): string =
result = fmt"""CollectiblesNestedModel( result = fmt"""CollectiblesNestedModel(
flatModel: {self.flatModel}, flatModel: {self.flatModel},
currentCollectionUid: {self.currentCollectionUid}, currentGroupId: {self.currentGroupId},
]""" ]"""
proc countChanged(self: Model) {.signal.} proc countChanged(self: Model) {.signal.}
@ -59,13 +65,13 @@ QtObject:
notify = countChanged notify = countChanged
proc getCurrentCollectionUid*(self: Model): string {.slot.} = proc getCurrentCollectionUid*(self: Model): string {.slot.} =
result = self.currentCollectionUid result = self.currentGroupId
proc currentCollectionUidChanged(self: Model) {.signal.} proc currentCollectionUidChanged(self: Model) {.signal.}
proc setCurrentCollectionUid(self: Model, currentCollectionUid: string) {.slot.} = proc setCurrentCollectionUid(self: Model, currentGroupId: string) {.slot.} =
self.currentCollectionUid = currentCollectionUid self.currentGroupId = currentGroupId
self.currentCollectionUidChanged() self.currentCollectionUidChanged()
self.refreshItems() self.refreshItems()
QtProperty[string] currentCollectionUid: QtProperty[string] currentGroupId:
read = getCurrentCollectionUid read = getCurrentCollectionUid
write = setCurrentCollectionUid write = setCurrentCollectionUid
notify = currentCollectionUidChanged notify = currentCollectionUidChanged
@ -79,11 +85,11 @@ QtObject:
CollectiblesNestedRole.ChainId.int:"chainId", CollectiblesNestedRole.ChainId.int:"chainId",
CollectiblesNestedRole.Name.int:"name", CollectiblesNestedRole.Name.int:"name",
CollectiblesNestedRole.IconUrl.int:"iconUrl", CollectiblesNestedRole.IconUrl.int:"iconUrl",
CollectiblesNestedRole.CollectionUid.int:"collectionUid", CollectiblesNestedRole.GroupId.int:"groupId",
CollectiblesNestedRole.CollectionName.int:"collectionName", CollectiblesNestedRole.GroupName.int:"groupName",
CollectiblesNestedRole.IsCollection.int:"isCollection",
CollectiblesNestedRole.CommunityId.int:"communityId",
CollectiblesNestedRole.TokenType.int:"tokenType", CollectiblesNestedRole.TokenType.int:"tokenType",
CollectiblesNestedRole.ItemType.int:"itemType",
CollectiblesNestedRole.Count.int:"count",
}.toTable }.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant = method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -105,16 +111,16 @@ QtObject:
result = newQVariant(item.getName()) result = newQVariant(item.getName())
of CollectiblesNestedRole.IconUrl: of CollectiblesNestedRole.IconUrl:
result = newQVariant(item.getIconUrl()) result = newQVariant(item.getIconUrl())
of CollectiblesNestedRole.CollectionUid: of CollectiblesNestedRole.GroupId:
result = newQVariant(item.getCollectionId()) result = newQVariant(item.getGroupId())
of CollectiblesNestedRole.CollectionName: of CollectiblesNestedRole.GroupName:
result = newQVariant(item.getCollectionName()) result = newQVariant(item.getGroupName())
of CollectiblesNestedRole.IsCollection:
result = newQVariant(item.getIsCollection())
of CollectiblesNestedRole.CommunityId:
result = newQVariant(item.getCommunityId())
of CollectiblesNestedRole.TokenType: of CollectiblesNestedRole.TokenType:
result = newQVariant(item.getTokenType()) result = newQVariant(item.getTokenType())
of CollectiblesNestedRole.ItemType:
result = newQVariant(item.getItemType())
of CollectiblesNestedRole.Count:
result = newQVariant(item.getCountAsString())
proc rowData(self: Model, index: int, column: string): string {.slot.} = proc rowData(self: Model, index: int, column: string): string {.slot.} =
if (index >= self.items.len): if (index >= self.items.len):
@ -125,12 +131,15 @@ QtObject:
of "chainId": result = $item.getChainId() of "chainId": result = $item.getChainId()
of "name": result = item.getName() of "name": result = item.getName()
of "iconUrl": result = item.getIconUrl() of "iconUrl": result = item.getIconUrl()
of "collectionUid": result = item.getCollectionId() of "groupId": result = item.getGroupId()
of "collectionName": result = item.getCollectionName() of "groupName": result = item.getGroupName()
of "isCollection": result = $item.getIsCollection() of "itemType": result = $item.getItemType()
of "communityId": result = item.getCommunityId() of "count": result = item.getCountAsString()
proc getCollectiblesPerCollectionId(items: seq[flat_item.CollectiblesEntry]): Table[string, seq[flat_item.CollectiblesEntry]] = # Groups collectibles by CommunityID if available, or CollectionID otherwise.
# Returns pair (collectiblesPerCommunity, collectiblesPerCollection)
proc getCollectiblesPerGroupId(items: seq[flat_item.CollectiblesEntry]): (CollectiblesPerGroupId, CollectiblesPerGroupId) =
var collectiblesPerCommunity = initTable[string, seq[flat_item.CollectiblesEntry]]()
var collectiblesPerCollection = initTable[string, seq[flat_item.CollectiblesEntry]]() var collectiblesPerCollection = initTable[string, seq[flat_item.CollectiblesEntry]]()
for item in items: for item in items:
@ -140,50 +149,30 @@ QtObject:
if not collectiblesPerCollection.hasKey(collectionId): if not collectiblesPerCollection.hasKey(collectionId):
collectiblesPerCollection[collectionId] = @[] collectiblesPerCollection[collectionId] = @[]
collectiblesPerCollection[collectionId].add(item) collectiblesPerCollection[collectionId].add(item)
else:
return collectiblesPerCollection
proc getCollectiblesPerCommunityId(items: seq[flat_item.CollectiblesEntry]): Table[string, seq[flat_item.CollectiblesEntry]] =
var collectiblesPerCommunity = initTable[string, seq[flat_item.CollectiblesEntry]]()
for item in items:
let communityId = item.getCommunityId()
if communityId != "":
if not collectiblesPerCommunity.hasKey(communityId): if not collectiblesPerCommunity.hasKey(communityId):
collectiblesPerCommunity[communityId] = @[] collectiblesPerCommunity[communityId] = @[]
collectiblesPerCommunity[communityId].add(item) collectiblesPerCommunity[communityId].add(item)
return (collectiblesPerCommunity, collectiblesPerCollection)
return collectiblesPerCommunity
proc getNumberOfCollectiblesInCommunity*(self: Model, commId: string): int {.slot.} =
if commId != "":
var collectiblesPerCommunity = getCollectiblesPerCommunityId(self.flatModel.getItems())
if collectiblesPerCommunity.hasKey(commId):
result = collectiblesPerCommunity[commId].len
proc getNumberOfCollectiblesInCollection*(self: Model, collUid: string): int {.slot.} =
if collUid != "":
var collectiblesPerCollection = getCollectiblesPerCollectionId(self.flatModel.getItems())
if collectiblesPerCollection.hasKey(collUid):
result = collectiblesPerCollection[collUid].len
proc refreshItems*(self: Model) {.slot.} = proc refreshItems*(self: Model) {.slot.} =
let (collectiblesPerCommunity, collectiblesPerCollection) = getCollectiblesPerGroupId(self.flatModel.getItems())
self.beginResetModel() self.beginResetModel()
self.items = @[] self.items = @[]
var addCollections = true var addCollections = true
# Add communities # Add communities
var collectiblesPerCommunity = getCollectiblesPerCommunityId(self.flatModel.getItems())
for communityId, communityCollectibles in collectiblesPerCommunity.pairs: for communityId, communityCollectibles in collectiblesPerCommunity.pairs:
if self.currentCollectionUid == "": if self.currentGroupId == "":
# No collection selected # No collection selected
if communityCollectibles.len > 0: if communityCollectibles.len > 0:
let communityItem = collectibleToCollectionNestedItem(communityCollectibles[0]) let communityItem = collectibleToCommunityNestedItem(communityCollectibles[0], stint.u256(communityCollectibles.len))
self.items.add(communityItem) self.items.add(communityItem)
else: else:
if self.currentCollectionUid == communityId: if self.currentGroupId == communityId:
for collectible in communityCollectibles: for collectible in communityCollectibles:
let collectibleItem = collectibleToCollectibleNestedItem(collectible) let collectibleItem = collectibleToCommunityCollectibleNestedItem(collectible, collectible.getOwnershipModel().getBalance(self.address))
self.items.add(collectibleItem) self.items.add(collectibleItem)
# Inside community folder we dont add collection items # Inside community folder we dont add collection items
@ -192,23 +181,22 @@ QtObject:
if addCollections: if addCollections:
# Add collections and collection items # Add collections and collection items
var collectiblesPerCollection = getCollectiblesPerCollectionId(self.flatModel.getItems())
for collectionId, collectionCollectibles in collectiblesPerCollection.pairs: for collectionId, collectionCollectibles in collectiblesPerCollection.pairs:
if self.currentCollectionUid == "": if self.currentGroupId == "":
# No collection selected # No collection selected
# If the collection contains more than 1 collectible, we add a single collection item # If the collection contains more than 1 collectible, we add a single collection item
# Otherwise, we add the collectible # Otherwise, we add the collectible
if collectionCollectibles.len > 1: if collectionCollectibles.len > 1:
let collectionItem = collectibleToCollectionNestedItem(collectionCollectibles[0]) let collectionItem = collectibleToCollectionNestedItem(collectionCollectibles[0], stint.u256(collectionCollectibles.len))
self.items.add(collectionItem) self.items.add(collectionItem)
else: else:
for collectible in collectionCollectibles: for collectible in collectionCollectibles:
let collectibleItem = collectibleToCollectibleNestedItem(collectible) let collectibleItem = collectibleToNonCommunityCollectibleNestedItem(collectible, collectible.getOwnershipModel().getBalance(self.address))
self.items.add(collectibleItem) self.items.add(collectibleItem)
else: else:
if self.currentCollectionUid == collectionId: if self.currentGroupId == collectionId:
for collectible in collectionCollectibles: for collectible in collectionCollectibles:
let collectibleItem = collectibleToCollectibleNestedItem(collectible) let collectibleItem = collectibleToNonCommunityCollectibleNestedItem(collectible, collectible.getOwnershipModel().getBalance(self.address))
self.items.add(collectibleItem) self.items.add(collectibleItem)
# No need to keep looking # No need to keep looking
break break
@ -221,3 +209,7 @@ QtObject:
self.items = @[] self.items = @[]
self.endResetModel() self.endResetModel()
self.countChanged() self.countChanged()
proc setAddress*(self: Model, address: string) {.slot.} =
self.address = address
self.refreshItems()

View File

@ -1,8 +1,36 @@
import stint
import ./collectibles_entry as flat_item import ./collectibles_entry as flat_item
import ./collectibles_nested_item as nested_item import ./collectibles_nested_item as nested_item
import app_service/common/types import app_service/common/types
proc collectibleToCollectibleNestedItem*(flatItem: flat_item.CollectiblesEntry): nested_item.Item = proc collectibleToCommunityCollectibleNestedItem*(flatItem: flat_item.CollectiblesEntry, count: UInt256): nested_item.Item =
return nested_item.initItem(
flatItem.getIDAsString(),
flatItem.getChainID(),
flatItem.getName(),
flatItem.getImageURL(),
flatItem.getCommunityId(),
flatItem.getCommunityName(),
TokenType(flatItem.getTokenType()),
ItemType.CommunityCollectible,
count
)
proc collectibleToCommunityNestedItem*(flatItem: flat_item.CollectiblesEntry, count: UInt256): nested_item.Item =
return nested_item.initItem(
flatItem.getCommunityId(),
flatItem.getChainID(),
flatItem.getCommunityName(),
flatItem.getCommunityImage(),
flatItem.getCommunityId(),
flatItem.getCommunityName(),
TokenType(flatItem.getTokenType()),
ItemType.Community,
count
)
proc collectibleToNonCommunityCollectibleNestedItem*(flatItem: flat_item.CollectiblesEntry, count: UInt256): nested_item.Item =
return nested_item.initItem( return nested_item.initItem(
flatItem.getIDAsString(), flatItem.getIDAsString(),
flatItem.getChainID(), flatItem.getChainID(),
@ -10,12 +38,12 @@ proc collectibleToCollectibleNestedItem*(flatItem: flat_item.CollectiblesEntry):
flatItem.getImageURL(), flatItem.getImageURL(),
flatItem.getCollectionIDAsString(), flatItem.getCollectionIDAsString(),
flatItem.getCollectionName(), flatItem.getCollectionName(),
false, TokenType(flatItem.getTokenType()),
flatItem.getCommunityID(), ItemType.NonCommunityCollectible,
TokenType(flatItem.getTokenType()) count
) )
proc collectibleToCollectionNestedItem*(flatItem: flat_item.CollectiblesEntry): nested_item.Item = proc collectibleToCollectionNestedItem*(flatItem: flat_item.CollectiblesEntry, count: UInt256): nested_item.Item =
return nested_item.initItem( return nested_item.initItem(
flatItem.getCollectionIDAsString(), flatItem.getCollectionIDAsString(),
flatItem.getChainID(), flatItem.getChainID(),
@ -23,7 +51,7 @@ proc collectibleToCollectionNestedItem*(flatItem: flat_item.CollectiblesEntry):
flatItem.getCollectionImageURL(), flatItem.getCollectionImageURL(),
flatItem.getCollectionIDAsString(), flatItem.getCollectionIDAsString(),
flatItem.getCollectionName(), flatItem.getCollectionName(),
true, TokenType(flatItem.getTokenType()),
flatItem.getCommunityID(), ItemType.Collection,
TokenType(flatItem.getTokenType()) count
) )

View File

@ -328,7 +328,7 @@ StatusDialog {
maxInputBalance: d.maxInputBalance maxInputBalance: d.maxInputBalance
currentCurrency: d.currencyStore.currentCurrency currentCurrency: d.currencyStore.currentCurrency
multiplierIndex: !!holdingSelector.selectedItem multiplierIndex: d.isSelectedHoldingValidAsset
? holdingSelector.selectedItem.decimals ? holdingSelector.selectedItem.decimals
: 0 : 0

View File

@ -29,7 +29,7 @@ StatusListItem {
title: name title: name
statusListItemTitleAside.font.pixelSize: 15 statusListItemTitleAside.font.pixelSize: 15
asset.name: iconUrl ? iconUrl : "" asset.name: iconUrl ?? ""
asset.isImage: true asset.isImage: true
asset.width: 32 asset.width: 32
asset.height: 32 asset.height: 32
@ -41,28 +41,26 @@ StatusListItem {
onClicked: d.selectItem() onClicked: d.selectItem()
property int numItems
components: [ components: [
StatusRoundedImage { StatusRoundedImage {
width: 20 width: 20
height: 20 height: 20
image.source: Style.svg("tiny/%1".arg(networkIconUrl)) image.source: Style.svg("tiny/%1".arg(networkIconUrl)) ?? ""
visible: !isCollection && root.sensor.containsMouse visible: !isGroup && root.sensor.containsMouse
}, },
StatusBaseText { StatusBaseText {
id: label id: label
text: root.numItems text: count
font.pixelSize: 13 font.pixelSize: 13
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
visible: isCollection visible: isGroup || (!root.sensor.containsMouse && count > 1)
}, },
StatusIcon { StatusIcon {
icon: "tiny/chevron-right" icon: "tiny/chevron-right"
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
width: 16 width: 16
height: 16 height: 16
visible: isCollection visible: isGroup
} }
] ]
} }

View File

@ -40,7 +40,7 @@ StatusListItem {
} }
title: name title: name
titleAsideText: symbol titleAsideText: symbol ?? ""
statusListItemTitleAside.font.pixelSize: 15 statusListItemTitleAside.font.pixelSize: 15
statusListItemTitleAside.width: statusListItemTitleArea.width - statusListItemTitle.width statusListItemTitleAside.width: statusListItemTitleArea.width - statusListItemTitle.width
statusListItemTitleAside.elide: Text.ElideRight statusListItemTitleAside.elide: Text.ElideRight

View File

@ -1,12 +1,7 @@
import QtQml 2.15 import QtQml 2.15
import QtQuick 2.13 import QtQuick 2.15
import QtQuick.Layouts 1.13 import QtQuick.Layouts 1.15
import shared.controls 1.0
import shared.popups 1.0
import shared.popups.send 1.0
import utils 1.0
import SortFilterProxyModel 0.2 import SortFilterProxyModel 0.2
@ -14,7 +9,13 @@ import StatusQ 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import utils 1.0
import shared.controls 1.0
import shared.popups 1.0
import shared.popups.send 1.0
import "../controls" import "../controls"
Item { Item {
@ -73,10 +74,20 @@ Item {
return type === Constants.TokenType.ERC20 return type === Constants.TokenType.ERC20
} }
function isCommunityItem(type) {
return type === Constants.CollectiblesNestedItemType.CommunityCollectible ||
type === Constants.CollectiblesNestedItemType.Community
}
function isGroupItem(type) {
return type === Constants.CollectiblesNestedItemType.Collection ||
type === Constants.CollectiblesNestedItemType.Community
}
property int browsingHoldingType: Constants.TokenType.ERC20 property int browsingHoldingType: Constants.TokenType.ERC20
readonly property bool isCurrentBrowsingTypeAsset: isAsset(browsingHoldingType) readonly property bool isCurrentBrowsingTypeAsset: isAsset(browsingHoldingType)
readonly property bool isBrowsingCollection: !isCurrentBrowsingTypeAsset && !!collectiblesModel && collectiblesModel.currentCollectionUid !== "" readonly property bool isBrowsingGroup: !isCurrentBrowsingTypeAsset && !!root.collectiblesModel && root.collectiblesModel.currentGroupId !== ""
property string currentBrowsingCollectionName property string currentBrowsingGroupName
property var currentHoldingType: Constants.TokenType.Unknown property var currentHoldingType: Constants.TokenType.Unknown
@ -92,7 +103,7 @@ Item {
property var collectibleTextFn: function (item) { property var collectibleTextFn: function (item) {
if (!!item) { if (!!item) {
return !!item.collectionName ? item.collectionName + ": " + item.name : item.name return !!item.groupName ? item.groupName + ": " + item.name : item.name
} }
return "" return ""
} }
@ -120,8 +131,13 @@ Item {
proxyRoles: [ proxyRoles: [
FastExpressionRole { FastExpressionRole {
name: "isCommunityAsset" name: "isCommunityAsset"
expression: !!model.communityId expression: d.isCommunityItem(model.itemType)
expectedRoles: ["communityId"] expectedRoles: ["itemType"]
},
FastExpressionRole {
name: "isGroup"
expression: d.isGroupItem(model.itemType)
expectedRoles: ["itemType"]
} }
] ]
filters: [ filters: [
@ -137,7 +153,7 @@ Item {
sortOrder: Qt.DescendingOrder sortOrder: Qt.DescendingOrder
}, },
RoleSorter { RoleSorter {
roleName: "isCollection" roleName: "isGroup"
sortOrder: Qt.DescendingOrder sortOrder: Qt.DescendingOrder
} }
] ]
@ -146,8 +162,8 @@ Item {
readonly property string searchPlaceholderText: { readonly property string searchPlaceholderText: {
if (isCurrentBrowsingTypeAsset) { if (isCurrentBrowsingTypeAsset) {
return qsTr("Search for token or enter token address") return qsTr("Search for token or enter token address")
} else if (isBrowsingCollection) { } else if (isBrowsingGroup) {
return qsTr("Search %1").arg(d.currentBrowsingCollectionName ?? qsTr("collectibles in collection")) return qsTr("Search %1").arg(d.currentBrowsingGroupName ?? qsTr("collectibles in collection"))
} else { } else {
return qsTr("Search collectibles") return qsTr("Search collectibles")
} }
@ -187,6 +203,7 @@ Item {
property var model: itemModel property var model: itemModel
property var chainId: model.chainId property var chainId: model.chainId
property var name: model.name property var name: model.name
property var tokenType: model.tokenType
// asset // asset
property var symbol: model.symbol property var symbol: model.symbol
property var totalBalance: model.totalBalance property var totalBalance: model.totalBalance
@ -197,10 +214,10 @@ Item {
property var uid: model.uid property var uid: model.uid
property var iconUrl: model.iconUrl property var iconUrl: model.iconUrl
property var networkIconUrl: model.networkIconUrl property var networkIconUrl: model.networkIconUrl
property var collectionUid: model.collectionUid property var groupId: model.groupId
property var communityId: model.communityId property var groupName: model.groupName
property var collectionName: model.collectionName property var isGroup: model.isGroup
property var isCollection: model.isCollection property var count: model.count
sourceComponent: d.isCurrentBrowsingTypeAsset ? assetComboBoxDelegate : collectibleComboBoxDelegate sourceComponent: d.isCurrentBrowsingTypeAsset ? assetComboBoxDelegate : collectibleComboBoxDelegate
} }
@ -223,7 +240,7 @@ Item {
height: !!text ? 52 : 0 // if we bind to some property instead of hardcoded value it wont work nice when switching tabs or going inside collection and back height: !!text ? 52 : 0 // if we bind to some property instead of hardcoded value it wont work nice when switching tabs or going inside collection and back
width: ListView.view.width width: ListView.view.width
required property bool section required property bool section
text: Helpers.assetsSectionTitle(section, holdingItemSelector.hasCommunityTokens, d.isBrowsingCollection, d.isCurrentBrowsingTypeAsset) text: Helpers.assetsSectionTitle(section, holdingItemSelector.hasCommunityTokens, d.isBrowsingGroup, d.isCurrentBrowsingTypeAsset)
onOpenInfoPopup: Global.openPopup(communityInfoPopupCmp) onOpenInfoPopup: Global.openPopup(communityInfoPopupCmp)
} }
comboBoxControl.popup.onClosed: comboBoxControl.popup.contentItem.headerItem.clear() comboBoxControl.popup.onClosed: comboBoxControl.popup.contentItem.headerItem.clear()
@ -275,13 +292,13 @@ Item {
} }
CollectibleBackButtonWithInfo { CollectibleBackButtonWithInfo {
Layout.fillWidth: true Layout.fillWidth: true
visible: d.isBrowsingCollection visible: d.isBrowsingGroup
count: collectiblesModel.count count: collectiblesModel.count
name: d.currentBrowsingCollectionName name: d.currentBrowsingGroupName
onBackClicked: { onBackClicked: {
if (!d.isCurrentBrowsingTypeAsset) { if (!d.isCurrentBrowsingTypeAsset) {
searchInput.reset() searchInput.reset()
root.collectiblesModel.currentCollectionUid = "" root.collectiblesModel.currentGroupId = ""
} }
} }
} }
@ -341,18 +358,12 @@ Item {
Component { Component {
id: collectibleComboBoxDelegate id: collectibleComboBoxDelegate
CollectibleNestedDelegate { CollectibleNestedDelegate {
objectName: "CollectibleSelector_ItemDelegate_" + collectionUid objectName: "CollectibleSelector_ItemDelegate_" + groupId
width: holdingItemSelector.comboBoxControl.popup.width width: holdingItemSelector.comboBoxControl.popup.width
numItems: isCollection ? (!!communityId ?
root.collectiblesModel.getNumberOfCollectiblesInCommunity(communityId) :
root.collectiblesModel.getNumberOfCollectiblesInCollection(collectionUid)) : 0
onItemSelected: { onItemSelected: {
if (isCollection) { if (isGroup) {
d.currentBrowsingCollectionName = collectionName d.currentBrowsingGroupName = groupName
if (!!communityId) root.collectiblesModel.currentGroupId = groupId
root.collectiblesModel.currentCollectionUid = communityId
else
root.collectiblesModel.currentCollectionUid = collectionUid
} else { } else {
holdingItemSelector.selectedItem = selectedItem holdingItemSelector.selectedItem = selectedItem
d.currentHoldingType = tokenType d.currentHoldingType = tokenType

View File

@ -1,5 +1,5 @@
import QtQuick 2.15
import QtQml 2.15 import QtQml 2.15
import QtQuick 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import SortFilterProxyModel 0.2 import SortFilterProxyModel 0.2
@ -36,8 +36,8 @@ Item {
onVisibleChanged: { onVisibleChanged: {
if(!visible) { if(!visible) {
if (root.collectibles) if (!!root.collectibles)
root.collectibles.currentCollectionUid = "" root.collectibles.currentGroupId = ""
tokenList.headerItem.input.edit.clear() tokenList.headerItem.input.edit.clear()
} }
} }
@ -62,7 +62,7 @@ Item {
[qsTr("Assets")] : [qsTr("Assets")] :
[qsTr("Assets"), qsTr("Collectibles")] [qsTr("Assets"), qsTr("Collectibles")]
property string currentBrowsingCollectionName property string currentBrowsingGroupName
readonly property RolesRenamingModel renamedAllNetworksModel: RolesRenamingModel { readonly property RolesRenamingModel renamedAllNetworksModel: RolesRenamingModel {
sourceModel: root.networksModel sourceModel: root.networksModel
@ -79,7 +79,17 @@ Item {
} }
readonly property bool isBrowsingTypeERC20: root.browsingHoldingType === Constants.TokenType.ERC20 readonly property bool isBrowsingTypeERC20: root.browsingHoldingType === Constants.TokenType.ERC20
readonly property bool isBrowsingCollection: !isBrowsingTypeERC20 && !!root.collectibles && root.collectibles.currentCollectionUid !== "" readonly property bool isBrowsingGroup: !isBrowsingTypeERC20 && !!root.collectibles && root.collectibles.currentGroupId !== ""
function isCommunityItem(type) {
return type === Constants.CollectiblesNestedItemType.CommunityCollectible ||
type === Constants.CollectiblesNestedItemType.Community
}
function isGroupItem(type) {
return type === Constants.CollectiblesNestedItemType.Collection ||
type === Constants.CollectiblesNestedItemType.Community
}
} }
StatusBaseText { StatusBaseText {
@ -151,7 +161,7 @@ Item {
required property bool section required property bool section
width: parent.width width: parent.width
height: !!text ? 52 : 0 // if we bind to some property instead of hardcoded value it wont work nice when switching tabs or going inside collection and back height: !!text ? 52 : 0 // if we bind to some property instead of hardcoded value it wont work nice when switching tabs or going inside collection and back
text: Helpers.assetsSectionTitle(section, tokenList.hasCommunityTokens, d.isBrowsingCollection, d.isBrowsingTypeERC20) text: Helpers.assetsSectionTitle(section, tokenList.hasCommunityTokens, d.isBrowsingGroup, d.isBrowsingTypeERC20)
onOpenInfoPopup: Global.openPopup(communityInfoPopupCmp) onOpenInfoPopup: Global.openPopup(communityInfoPopupCmp)
} }
} }
@ -164,8 +174,13 @@ Item {
proxyRoles: [ proxyRoles: [
FastExpressionRole { FastExpressionRole {
name: "isCommunityAsset" name: "isCommunityAsset"
expression: !!model.communityId expression: d.isCommunityItem(model.itemType)
expectedRoles: ["communityId"] expectedRoles: ["itemType"]
},
FastExpressionRole {
name: "isGroup"
expression: d.isGroupItem(model.itemType)
expectedRoles: ["itemType"]
} }
] ]
filters: [ filters: [
@ -181,7 +196,7 @@ Item {
sortOrder: Qt.DescendingOrder sortOrder: Qt.DescendingOrder
}, },
RoleSorter { RoleSorter {
roleName: "isCollection" roleName: "isGroup"
sortOrder: Qt.DescendingOrder sortOrder: Qt.DescendingOrder
} }
] ]
@ -221,17 +236,11 @@ Item {
id: collectiblesDelegate id: collectiblesDelegate
CollectibleNestedDelegate { CollectibleNestedDelegate {
width: ListView.view.width width: ListView.view.width
numItems: isCollection ? (!!communityId ?
root.collectibles.getNumberOfCollectiblesInCommunity(communityId) :
root.collectibles.getNumberOfCollectiblesInCollection(collectionUid)) : 0
onItemHovered: root.tokenHovered(selectedItem.uid, tokenType, hovered) onItemHovered: root.tokenHovered(selectedItem.uid, tokenType, hovered)
onItemSelected: { onItemSelected: {
if (isCollection) { if (isGroup) {
d.currentBrowsingCollectionName = collectionName d.currentBrowsingGroupName = groupName
if (!!communityId) root.collectibles.currentGroupId = groupId
root.collectibles.currentCollectionUid = communityId
else
root.collectibles.currentCollectionUid = collectionUid
} else { } else {
root.tokenSelected(selectedItem.uid, tokenType) root.tokenSelected(selectedItem.uid, tokenType)
} }
@ -245,12 +254,12 @@ Item {
spacing: 0 spacing: 0
CollectibleBackButtonWithInfo { CollectibleBackButtonWithInfo {
Layout.fillWidth: true Layout.fillWidth: true
visible: d.isBrowsingCollection visible: d.isBrowsingGroup
count: root.collectibles.count count: root.collectibles.count
name: d.currentBrowsingCollectionName name: d.currentBrowsingGroupName
onBackClicked: { onBackClicked: {
searchBox.reset() searchBox.reset()
root.collectibles.currentCollectionUid = "" root.collectibles.currentGroupId = ""
} }
} }
SearchBoxWithRightIcon { SearchBoxWithRightIcon {

View File

@ -157,14 +157,24 @@ QtObject {
} }
function collectibleToSelectorCollectible(collectible) { function collectibleToSelectorCollectible(collectible) {
var groupId = collectible.collectionUid
var groupName = collectible.collectionName
var itemType = Constants.CollectiblesNestedItemType.Collectible
if (collectible.communityId !== "") {
groupId = collectible.communityId
groupName = collectible.communityName
itemType = Constants.CollectiblesNestedItemType.CommunityCollectible
}
return { return {
uid: collectible.uid, uid: collectible.uid,
chainId: collectible.chainId, chainId: collectible.chainId,
name: collectible.name, name: collectible.name,
iconUrl: collectible.imageUrl, iconUrl: collectible.imageUrl,
collectionUid: collectible.collectionUid, groupId: groupId,
collectionName: collectible.collectionName, groupName: groupName,
isCollection: false tokenType: collectible.tokenType,
itemType: itemType,
count: 1 // TODO: Properly handle count
} }
} }

View File

@ -1292,4 +1292,12 @@ QtObject {
UrlUnfurlingModeEnableAll = 2, UrlUnfurlingModeEnableAll = 2,
UrlUnfurlingModeDisableAll = 3 UrlUnfurlingModeDisableAll = 3
} }
// these are in sync with src/app/modules/shared_models/collectibles_nested_item.nim ItemType
enum CollectiblesNestedItemType {
CommunityCollectible = 0,
NonCommunityCollectible = 1,
Collection = 2,
Community = 3
}
} }