From cd3a1180b00dcc3ab248f02398061d8ca36cbd0b Mon Sep 17 00:00:00 2001 From: Dario Gabriel Lipicar Date: Wed, 27 Mar 2024 13:18:45 -0300 Subject: [PATCH] fix(@desktop/wallet): properly handle collectible groups in send modal Fixes #14080 --- .../main/wallet_section/send/module.nim | 4 +- .../collectible_ownership_model.nim | 8 ++ .../shared_models/collectibles_entry.nim | 6 +- .../shared_models/collectibles_model.nim | 2 +- .../collectibles_nested_item.nim | 66 ++++++---- .../collectibles_nested_model.nim | 118 ++++++++---------- .../collectibles_nested_utils.nim | 46 +++++-- ui/imports/shared/popups/send/SendModal.qml | 2 +- .../controls/CollectibleNestedDelegate.qml | 14 +-- .../controls/TokenBalancePerChainDelegate.qml | 2 +- .../popups/send/panels/HoldingSelector.qml | 77 +++++++----- .../popups/send/views/TokenListView.qml | 51 ++++---- .../shared/stores/send/TransactionStore.qml | 16 ++- ui/imports/utils/Constants.qml | 8 ++ 14 files changed, 250 insertions(+), 170 deletions(-) diff --git a/src/app/modules/main/wallet_section/send/module.nim b/src/app/modules/main/wallet_section/send/module.nim index 2798b200ac..0ad06ce7c6 100644 --- a/src/app/modules/main/wallet_section/send/module.nim +++ b/src/app/modules/main/wallet_section/send/module.nim @@ -358,9 +358,11 @@ method filterChanged*(self: Module, addresses: seq[string], chainIds: seq[int]) self.view.switchReceiveAccountByAddress(addresses[0]) 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() self.collectiblesController.setFilterAddressesAndChains(addresses, chainIds) + self.nestedCollectiblesModel.setAddress(senderAddress) method setSelectedSenderAccountIndex*(self: Module, index: int) = self.senderCurrentAccountIndex = index diff --git a/src/app/modules/shared_models/collectible_ownership_model.nim b/src/app/modules/shared_models/collectible_ownership_model.nim index cec64c6b1b..d4810c8443 100644 --- a/src/app/modules/shared_models/collectible_ownership_model.nim +++ b/src/app/modules/shared_models/collectible_ownership_model.nim @@ -71,3 +71,11 @@ QtObject: self.items = items self.endResetModel() 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 diff --git a/src/app/modules/shared_models/collectibles_entry.nim b/src/app/modules/shared_models/collectibles_entry.nim index d818d36a89..d60d7ed406 100644 --- a/src/app/modules/shared_models/collectibles_entry.nim +++ b/src/app/modules/shared_models/collectibles_entry.nim @@ -234,11 +234,13 @@ QtObject: notify = traitsChanged 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) QtProperty[QVariant] ownership: - read = getOwnershipModel + read = getOwnershipModelAsVariant notify = ownershipChanged proc communityIdChanged*(self: CollectiblesEntry) {.signal.} diff --git a/src/app/modules/shared_models/collectibles_model.nim b/src/app/modules/shared_models/collectibles_model.nim index 7c0e349a89..4e6f85d216 100644 --- a/src/app/modules/shared_models/collectibles_model.nim +++ b/src/app/modules/shared_models/collectibles_model.nim @@ -188,7 +188,7 @@ QtObject: of CollectibleRole.IsLoading: result = newQVariant(false) of CollectibleRole.Ownership: - result = newQVariant(item.getOwnershipModel()) + result = item.getOwnershipModelAsVariant() of CollectibleRole.CommunityId: result = newQVariant(item.getCommunityId()) of CollectibleRole.CommunityName: diff --git a/src/app/modules/shared_models/collectibles_nested_item.nim b/src/app/modules/shared_models/collectibles_nested_item.nim index 03898916fe..099630e946 100644 --- a/src/app/modules/shared_models/collectibles_nested_item.nim +++ b/src/app/modules/shared_models/collectibles_nested_item.nim @@ -1,37 +1,46 @@ import stew/shims/strformat import app_service/common/types +import stint + +type + ItemType* {.pure.} = enum + CommunityCollectible = 0, + NonCommunityCollectible = 1, + Collection = 2, + Community = 3 type Item* = object - id: string # Collectible ID if isCollection=false, Collection Slug otherwise + id: string # CollectibleID if single collectible, GroupID (CollectionID/CommunityID) otherwise chainId: int name: string iconUrl: string - collectionId: string - collectionName: string - isCollection: bool - communityId: string + groupId: string + groupName: string tokenType: TokenType + itemType: ItemType + count: UInt256 proc initItem*( id: string, chainId: int, name: string, iconUrl: string, - collectionId: string, - collectionName: string, - isCollection: bool, - communityId: string, - tokenType: TokenType + groupId: string, + groupName: string, + tokenType: TokenType, + itemType: ItemType, + count: UInt256, ): Item = result.id = id result.chainId = chainId result.name = name result.iconUrl = iconUrl - result.collectionId = collectionId - result.collectionName = collectionName - result.isCollection = isCollection + result.groupId = groupId + result.groupName = groupName result.tokenType = tokenType + result.itemType = itemType + result.count = count proc `$`*(self: Item): string = result = fmt"""CollectiblesNestedEntry( @@ -39,11 +48,11 @@ proc `$`*(self: Item): string = chainId: {self.chainId}, name: {self.name}, iconUrl: {self.iconUrl}, - collectionId: {self.collectionId}, - collectionName: {self.collectionName}, - isCollection: {self.isCollection}, - communityId: {self.communityId}, + groupId: {self.groupId}, + groupName: {self.groupName}, tokenType: {self.tokenType}, + itemType: {self.itemType}, + count: {self.count}, ]""" proc getId*(self: Item): string = @@ -58,17 +67,20 @@ proc getName*(self: Item): string = proc getIconUrl*(self: Item): string = return self.iconUrl -proc getCollectionId*(self: Item): string = - return self.collectionId +proc getGroupId*(self: Item): string = + return self.groupId -proc getCollectionName*(self: Item): string = - return self.collectionName - -proc getIsCollection*(self: Item): bool = - return self.isCollection - -proc getCommunityId*(self: Item): string = - return self.communityId +proc getGroupName*(self: Item): string = + return self.groupName proc getTokenType*(self: Item): 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 diff --git a/src/app/modules/shared_models/collectibles_nested_model.nim b/src/app/modules/shared_models/collectibles_nested_model.nim index 5aab306239..1589832161 100644 --- a/src/app/modules/shared_models/collectibles_nested_model.nim +++ b/src/app/modules/shared_models/collectibles_nested_model.nim @@ -1,5 +1,7 @@ import NimQml, Tables, strutils, stew/shims/strformat, sequtils +import stint +import ./collectible_ownership_model import ./collectibles_model as flat_model import ./collectibles_entry as flat_item import ./collectibles_nested_item as nested_item @@ -12,18 +14,22 @@ type ChainId Name IconUrl - CollectionUid - CollectionName - IsCollection - CommunityId + GroupId + GroupName TokenType + ItemType + Count + +type + CollectiblesPerGroupId = Table[string, seq[flat_item.CollectiblesEntry]] QtObject: type Model* = ref object of QAbstractListModel flatModel: flat_model.Model items: seq[nested_item.Item] - currentCollectionUid: string + currentGroupId: string + address: string proc delete(self: Model) = self.items = @[] @@ -36,7 +42,7 @@ QtObject: new(result, delete) result.flatModel = flatModel result.items = @[] - result.currentCollectionUid = "" + result.currentGroupId = "" result.setup signalConnect(result.flatModel, "countChanged()", result, "refreshItems()") @@ -48,7 +54,7 @@ QtObject: proc `$`*(self: Model): string = result = fmt"""CollectiblesNestedModel( flatModel: {self.flatModel}, - currentCollectionUid: {self.currentCollectionUid}, + currentGroupId: {self.currentGroupId}, ]""" proc countChanged(self: Model) {.signal.} @@ -59,13 +65,13 @@ QtObject: notify = countChanged proc getCurrentCollectionUid*(self: Model): string {.slot.} = - result = self.currentCollectionUid + result = self.currentGroupId proc currentCollectionUidChanged(self: Model) {.signal.} - proc setCurrentCollectionUid(self: Model, currentCollectionUid: string) {.slot.} = - self.currentCollectionUid = currentCollectionUid + proc setCurrentCollectionUid(self: Model, currentGroupId: string) {.slot.} = + self.currentGroupId = currentGroupId self.currentCollectionUidChanged() self.refreshItems() - QtProperty[string] currentCollectionUid: + QtProperty[string] currentGroupId: read = getCurrentCollectionUid write = setCurrentCollectionUid notify = currentCollectionUidChanged @@ -79,11 +85,11 @@ QtObject: CollectiblesNestedRole.ChainId.int:"chainId", CollectiblesNestedRole.Name.int:"name", CollectiblesNestedRole.IconUrl.int:"iconUrl", - CollectiblesNestedRole.CollectionUid.int:"collectionUid", - CollectiblesNestedRole.CollectionName.int:"collectionName", - CollectiblesNestedRole.IsCollection.int:"isCollection", - CollectiblesNestedRole.CommunityId.int:"communityId", + CollectiblesNestedRole.GroupId.int:"groupId", + CollectiblesNestedRole.GroupName.int:"groupName", CollectiblesNestedRole.TokenType.int:"tokenType", + CollectiblesNestedRole.ItemType.int:"itemType", + CollectiblesNestedRole.Count.int:"count", }.toTable method data(self: Model, index: QModelIndex, role: int): QVariant = @@ -105,16 +111,16 @@ QtObject: result = newQVariant(item.getName()) of CollectiblesNestedRole.IconUrl: result = newQVariant(item.getIconUrl()) - of CollectiblesNestedRole.CollectionUid: - result = newQVariant(item.getCollectionId()) - of CollectiblesNestedRole.CollectionName: - result = newQVariant(item.getCollectionName()) - of CollectiblesNestedRole.IsCollection: - result = newQVariant(item.getIsCollection()) - of CollectiblesNestedRole.CommunityId: - result = newQVariant(item.getCommunityId()) + of CollectiblesNestedRole.GroupId: + result = newQVariant(item.getGroupId()) + of CollectiblesNestedRole.GroupName: + result = newQVariant(item.getGroupName()) 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.} = if (index >= self.items.len): @@ -125,12 +131,15 @@ QtObject: of "chainId": result = $item.getChainId() of "name": result = item.getName() of "iconUrl": result = item.getIconUrl() - of "collectionUid": result = item.getCollectionId() - of "collectionName": result = item.getCollectionName() - of "isCollection": result = $item.getIsCollection() - of "communityId": result = item.getCommunityId() + of "groupId": result = item.getGroupId() + of "groupName": result = item.getGroupName() + of "itemType": result = $item.getItemType() + 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]]() for item in items: @@ -140,50 +149,30 @@ QtObject: if not collectiblesPerCollection.hasKey(collectionId): collectiblesPerCollection[collectionId] = @[] collectiblesPerCollection[collectionId].add(item) - - 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 != "": + else: if not collectiblesPerCommunity.hasKey(communityId): collectiblesPerCommunity[communityId] = @[] collectiblesPerCommunity[communityId].add(item) - - 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 + return (collectiblesPerCommunity, collectiblesPerCollection) proc refreshItems*(self: Model) {.slot.} = + let (collectiblesPerCommunity, collectiblesPerCollection) = getCollectiblesPerGroupId(self.flatModel.getItems()) + self.beginResetModel() self.items = @[] var addCollections = true # Add communities - var collectiblesPerCommunity = getCollectiblesPerCommunityId(self.flatModel.getItems()) for communityId, communityCollectibles in collectiblesPerCommunity.pairs: - if self.currentCollectionUid == "": + if self.currentGroupId == "": # No collection selected if communityCollectibles.len > 0: - let communityItem = collectibleToCollectionNestedItem(communityCollectibles[0]) + let communityItem = collectibleToCommunityNestedItem(communityCollectibles[0], stint.u256(communityCollectibles.len)) self.items.add(communityItem) else: - if self.currentCollectionUid == communityId: + if self.currentGroupId == communityId: for collectible in communityCollectibles: - let collectibleItem = collectibleToCollectibleNestedItem(collectible) + let collectibleItem = collectibleToCommunityCollectibleNestedItem(collectible, collectible.getOwnershipModel().getBalance(self.address)) self.items.add(collectibleItem) # Inside community folder we dont add collection items @@ -192,23 +181,22 @@ QtObject: if addCollections: # Add collections and collection items - var collectiblesPerCollection = getCollectiblesPerCollectionId(self.flatModel.getItems()) for collectionId, collectionCollectibles in collectiblesPerCollection.pairs: - if self.currentCollectionUid == "": + if self.currentGroupId == "": # No collection selected # If the collection contains more than 1 collectible, we add a single collection item # Otherwise, we add the collectible if collectionCollectibles.len > 1: - let collectionItem = collectibleToCollectionNestedItem(collectionCollectibles[0]) + let collectionItem = collectibleToCollectionNestedItem(collectionCollectibles[0], stint.u256(collectionCollectibles.len)) self.items.add(collectionItem) else: for collectible in collectionCollectibles: - let collectibleItem = collectibleToCollectibleNestedItem(collectible) + let collectibleItem = collectibleToNonCommunityCollectibleNestedItem(collectible, collectible.getOwnershipModel().getBalance(self.address)) self.items.add(collectibleItem) else: - if self.currentCollectionUid == collectionId: + if self.currentGroupId == collectionId: for collectible in collectionCollectibles: - let collectibleItem = collectibleToCollectibleNestedItem(collectible) + let collectibleItem = collectibleToNonCommunityCollectibleNestedItem(collectible, collectible.getOwnershipModel().getBalance(self.address)) self.items.add(collectibleItem) # No need to keep looking break @@ -221,3 +209,7 @@ QtObject: self.items = @[] self.endResetModel() self.countChanged() + + proc setAddress*(self: Model, address: string) {.slot.} = + self.address = address + self.refreshItems() \ No newline at end of file diff --git a/src/app/modules/shared_models/collectibles_nested_utils.nim b/src/app/modules/shared_models/collectibles_nested_utils.nim index 7b0e2cd54b..0d5ec8cc97 100644 --- a/src/app/modules/shared_models/collectibles_nested_utils.nim +++ b/src/app/modules/shared_models/collectibles_nested_utils.nim @@ -1,8 +1,36 @@ +import stint + import ./collectibles_entry as flat_item import ./collectibles_nested_item as nested_item 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( flatItem.getIDAsString(), flatItem.getChainID(), @@ -10,12 +38,12 @@ proc collectibleToCollectibleNestedItem*(flatItem: flat_item.CollectiblesEntry): flatItem.getImageURL(), flatItem.getCollectionIDAsString(), flatItem.getCollectionName(), - false, - flatItem.getCommunityID(), - TokenType(flatItem.getTokenType()) + TokenType(flatItem.getTokenType()), + ItemType.NonCommunityCollectible, + 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( flatItem.getCollectionIDAsString(), flatItem.getChainID(), @@ -23,7 +51,7 @@ proc collectibleToCollectionNestedItem*(flatItem: flat_item.CollectiblesEntry): flatItem.getCollectionImageURL(), flatItem.getCollectionIDAsString(), flatItem.getCollectionName(), - true, - flatItem.getCommunityID(), - TokenType(flatItem.getTokenType()) - ) + TokenType(flatItem.getTokenType()), + ItemType.Collection, + count + ) \ No newline at end of file diff --git a/ui/imports/shared/popups/send/SendModal.qml b/ui/imports/shared/popups/send/SendModal.qml index 20bee4ba50..c36dd070f7 100644 --- a/ui/imports/shared/popups/send/SendModal.qml +++ b/ui/imports/shared/popups/send/SendModal.qml @@ -328,7 +328,7 @@ StatusDialog { maxInputBalance: d.maxInputBalance currentCurrency: d.currencyStore.currentCurrency - multiplierIndex: !!holdingSelector.selectedItem + multiplierIndex: d.isSelectedHoldingValidAsset ? holdingSelector.selectedItem.decimals : 0 diff --git a/ui/imports/shared/popups/send/controls/CollectibleNestedDelegate.qml b/ui/imports/shared/popups/send/controls/CollectibleNestedDelegate.qml index d7a872bdb9..213a2fc2ad 100644 --- a/ui/imports/shared/popups/send/controls/CollectibleNestedDelegate.qml +++ b/ui/imports/shared/popups/send/controls/CollectibleNestedDelegate.qml @@ -29,7 +29,7 @@ StatusListItem { title: name statusListItemTitleAside.font.pixelSize: 15 - asset.name: iconUrl ? iconUrl : "" + asset.name: iconUrl ?? "" asset.isImage: true asset.width: 32 asset.height: 32 @@ -41,28 +41,26 @@ StatusListItem { onClicked: d.selectItem() - property int numItems - components: [ StatusRoundedImage { width: 20 height: 20 - image.source: Style.svg("tiny/%1".arg(networkIconUrl)) - visible: !isCollection && root.sensor.containsMouse + image.source: Style.svg("tiny/%1".arg(networkIconUrl)) ?? "" + visible: !isGroup && root.sensor.containsMouse }, StatusBaseText { id: label - text: root.numItems + text: count font.pixelSize: 13 color: Theme.palette.baseColor1 - visible: isCollection + visible: isGroup || (!root.sensor.containsMouse && count > 1) }, StatusIcon { icon: "tiny/chevron-right" color: Theme.palette.baseColor1 width: 16 height: 16 - visible: isCollection + visible: isGroup } ] } diff --git a/ui/imports/shared/popups/send/controls/TokenBalancePerChainDelegate.qml b/ui/imports/shared/popups/send/controls/TokenBalancePerChainDelegate.qml index bf876e6925..fa3ac531ff 100644 --- a/ui/imports/shared/popups/send/controls/TokenBalancePerChainDelegate.qml +++ b/ui/imports/shared/popups/send/controls/TokenBalancePerChainDelegate.qml @@ -40,7 +40,7 @@ StatusListItem { } title: name - titleAsideText: symbol + titleAsideText: symbol ?? "" statusListItemTitleAside.font.pixelSize: 15 statusListItemTitleAside.width: statusListItemTitleArea.width - statusListItemTitle.width statusListItemTitleAside.elide: Text.ElideRight diff --git a/ui/imports/shared/popups/send/panels/HoldingSelector.qml b/ui/imports/shared/popups/send/panels/HoldingSelector.qml index ea1a9f5bc9..5a39e0afd1 100644 --- a/ui/imports/shared/popups/send/panels/HoldingSelector.qml +++ b/ui/imports/shared/popups/send/panels/HoldingSelector.qml @@ -1,12 +1,7 @@ import QtQml 2.15 -import QtQuick 2.13 -import QtQuick.Layouts 1.13 - -import shared.controls 1.0 -import shared.popups 1.0 -import shared.popups.send 1.0 -import utils 1.0 +import QtQuick 2.15 +import QtQuick.Layouts 1.15 import SortFilterProxyModel 0.2 @@ -14,7 +9,13 @@ import StatusQ 0.1 import StatusQ.Controls 0.1 import StatusQ.Core 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" Item { @@ -73,10 +74,20 @@ Item { 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 readonly property bool isCurrentBrowsingTypeAsset: isAsset(browsingHoldingType) - readonly property bool isBrowsingCollection: !isCurrentBrowsingTypeAsset && !!collectiblesModel && collectiblesModel.currentCollectionUid !== "" - property string currentBrowsingCollectionName + readonly property bool isBrowsingGroup: !isCurrentBrowsingTypeAsset && !!root.collectiblesModel && root.collectiblesModel.currentGroupId !== "" + property string currentBrowsingGroupName property var currentHoldingType: Constants.TokenType.Unknown @@ -92,7 +103,7 @@ Item { property var collectibleTextFn: function (item) { if (!!item) { - return !!item.collectionName ? item.collectionName + ": " + item.name : item.name + return !!item.groupName ? item.groupName + ": " + item.name : item.name } return "" } @@ -120,8 +131,13 @@ Item { proxyRoles: [ FastExpressionRole { name: "isCommunityAsset" - expression: !!model.communityId - expectedRoles: ["communityId"] + expression: d.isCommunityItem(model.itemType) + expectedRoles: ["itemType"] + }, + FastExpressionRole { + name: "isGroup" + expression: d.isGroupItem(model.itemType) + expectedRoles: ["itemType"] } ] filters: [ @@ -137,7 +153,7 @@ Item { sortOrder: Qt.DescendingOrder }, RoleSorter { - roleName: "isCollection" + roleName: "isGroup" sortOrder: Qt.DescendingOrder } ] @@ -146,8 +162,8 @@ Item { 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 if (isBrowsingGroup) { + return qsTr("Search %1").arg(d.currentBrowsingGroupName ?? qsTr("collectibles in collection")) } else { return qsTr("Search collectibles") } @@ -187,6 +203,7 @@ Item { property var model: itemModel property var chainId: model.chainId property var name: model.name + property var tokenType: model.tokenType // asset property var symbol: model.symbol property var totalBalance: model.totalBalance @@ -197,10 +214,10 @@ Item { property var uid: model.uid property var iconUrl: model.iconUrl property var networkIconUrl: model.networkIconUrl - property var collectionUid: model.collectionUid - property var communityId: model.communityId - property var collectionName: model.collectionName - property var isCollection: model.isCollection + property var groupId: model.groupId + property var groupName: model.groupName + property var isGroup: model.isGroup + property var count: model.count 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 width: ListView.view.width 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) } comboBoxControl.popup.onClosed: comboBoxControl.popup.contentItem.headerItem.clear() @@ -275,13 +292,13 @@ Item { } CollectibleBackButtonWithInfo { Layout.fillWidth: true - visible: d.isBrowsingCollection + visible: d.isBrowsingGroup count: collectiblesModel.count - name: d.currentBrowsingCollectionName + name: d.currentBrowsingGroupName onBackClicked: { if (!d.isCurrentBrowsingTypeAsset) { searchInput.reset() - root.collectiblesModel.currentCollectionUid = "" + root.collectiblesModel.currentGroupId = "" } } } @@ -341,18 +358,12 @@ Item { Component { id: collectibleComboBoxDelegate CollectibleNestedDelegate { - objectName: "CollectibleSelector_ItemDelegate_" + collectionUid + objectName: "CollectibleSelector_ItemDelegate_" + groupId width: holdingItemSelector.comboBoxControl.popup.width - numItems: isCollection ? (!!communityId ? - root.collectiblesModel.getNumberOfCollectiblesInCommunity(communityId) : - root.collectiblesModel.getNumberOfCollectiblesInCollection(collectionUid)) : 0 onItemSelected: { - if (isCollection) { - d.currentBrowsingCollectionName = collectionName - if (!!communityId) - root.collectiblesModel.currentCollectionUid = communityId - else - root.collectiblesModel.currentCollectionUid = collectionUid + if (isGroup) { + d.currentBrowsingGroupName = groupName + root.collectiblesModel.currentGroupId = groupId } else { holdingItemSelector.selectedItem = selectedItem d.currentHoldingType = tokenType diff --git a/ui/imports/shared/popups/send/views/TokenListView.qml b/ui/imports/shared/popups/send/views/TokenListView.qml index 067d8c97d1..9d6a685986 100644 --- a/ui/imports/shared/popups/send/views/TokenListView.qml +++ b/ui/imports/shared/popups/send/views/TokenListView.qml @@ -1,5 +1,5 @@ -import QtQuick 2.15 import QtQml 2.15 +import QtQuick 2.15 import QtQuick.Layouts 1.15 import SortFilterProxyModel 0.2 @@ -36,8 +36,8 @@ Item { onVisibleChanged: { if(!visible) { - if (root.collectibles) - root.collectibles.currentCollectionUid = "" + if (!!root.collectibles) + root.collectibles.currentGroupId = "" tokenList.headerItem.input.edit.clear() } } @@ -62,7 +62,7 @@ Item { [qsTr("Assets")] : [qsTr("Assets"), qsTr("Collectibles")] - property string currentBrowsingCollectionName + property string currentBrowsingGroupName readonly property RolesRenamingModel renamedAllNetworksModel: RolesRenamingModel { sourceModel: root.networksModel @@ -79,7 +79,17 @@ Item { } 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 { @@ -151,7 +161,7 @@ Item { required property bool section 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 - text: Helpers.assetsSectionTitle(section, tokenList.hasCommunityTokens, d.isBrowsingCollection, d.isBrowsingTypeERC20) + text: Helpers.assetsSectionTitle(section, tokenList.hasCommunityTokens, d.isBrowsingGroup, d.isBrowsingTypeERC20) onOpenInfoPopup: Global.openPopup(communityInfoPopupCmp) } } @@ -164,8 +174,13 @@ Item { proxyRoles: [ FastExpressionRole { name: "isCommunityAsset" - expression: !!model.communityId - expectedRoles: ["communityId"] + expression: d.isCommunityItem(model.itemType) + expectedRoles: ["itemType"] + }, + FastExpressionRole { + name: "isGroup" + expression: d.isGroupItem(model.itemType) + expectedRoles: ["itemType"] } ] filters: [ @@ -181,7 +196,7 @@ Item { sortOrder: Qt.DescendingOrder }, RoleSorter { - roleName: "isCollection" + roleName: "isGroup" sortOrder: Qt.DescendingOrder } ] @@ -221,17 +236,11 @@ Item { id: collectiblesDelegate CollectibleNestedDelegate { width: ListView.view.width - numItems: isCollection ? (!!communityId ? - root.collectibles.getNumberOfCollectiblesInCommunity(communityId) : - root.collectibles.getNumberOfCollectiblesInCollection(collectionUid)) : 0 onItemHovered: root.tokenHovered(selectedItem.uid, tokenType, hovered) onItemSelected: { - if (isCollection) { - d.currentBrowsingCollectionName = collectionName - if (!!communityId) - root.collectibles.currentCollectionUid = communityId - else - root.collectibles.currentCollectionUid = collectionUid + if (isGroup) { + d.currentBrowsingGroupName = groupName + root.collectibles.currentGroupId = groupId } else { root.tokenSelected(selectedItem.uid, tokenType) } @@ -245,12 +254,12 @@ Item { spacing: 0 CollectibleBackButtonWithInfo { Layout.fillWidth: true - visible: d.isBrowsingCollection + visible: d.isBrowsingGroup count: root.collectibles.count - name: d.currentBrowsingCollectionName + name: d.currentBrowsingGroupName onBackClicked: { searchBox.reset() - root.collectibles.currentCollectionUid = "" + root.collectibles.currentGroupId = "" } } SearchBoxWithRightIcon { diff --git a/ui/imports/shared/stores/send/TransactionStore.qml b/ui/imports/shared/stores/send/TransactionStore.qml index 2af3b8d040..7cc219ba32 100644 --- a/ui/imports/shared/stores/send/TransactionStore.qml +++ b/ui/imports/shared/stores/send/TransactionStore.qml @@ -157,14 +157,24 @@ QtObject { } 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 { uid: collectible.uid, chainId: collectible.chainId, name: collectible.name, iconUrl: collectible.imageUrl, - collectionUid: collectible.collectionUid, - collectionName: collectible.collectionName, - isCollection: false + groupId: groupId, + groupName: groupName, + tokenType: collectible.tokenType, + itemType: itemType, + count: 1 // TODO: Properly handle count } } diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index 1257d2619b..c88c283e15 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -1292,4 +1292,12 @@ QtObject { UrlUnfurlingModeEnableAll = 2, 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 + } }