diff --git a/src/app/modules/shared_models/collectibles_model.nim b/src/app/modules/shared_models/collectibles_model.nim index cdc05fd098..f429ac6ee3 100644 --- a/src/app/modules/shared_models/collectibles_model.nim +++ b/src/app/modules/shared_models/collectibles_model.nim @@ -31,8 +31,6 @@ type CommunityColor CommunityPrivilegesLevel -const loadingItemsCount = 10 - QtObject: type Model* = ref object of QAbstractListModel @@ -41,11 +39,6 @@ QtObject: isFetching: bool isUpdating: bool isError: bool - hasLoadingItems: bool - - proc appendLoadingItems(self: Model) - proc removeLoadingItems(self: Model) - proc checkLoadingItems(self: Model) proc delete(self: Model) = self.items = @[] @@ -62,21 +55,14 @@ QtObject: result.isUpdating = false result.isFetching = false result.isError = false - result.hasLoadingItems = true proc `$`*(self: Model): string = for i in 0 ..< self.items.len: result &= fmt"""[{i}]:({$self.items[i]})""" - proc getCollectiblesCount*(self: Model): int = - return self.items.len - proc countChanged(self: Model) {.signal.} proc getCount*(self: Model): int {.slot.} = - var count = self.items.len - if self.hasLoadingItems: - count += loadingItemsCount - return count + return self.items.len QtProperty[int] count: read = getCount @@ -93,7 +79,6 @@ QtObject: return self.isFetching = value self.isFetchingChanged() - self.checkLoadingItems() proc isUpdatingChanged(self: Model) {.signal.} proc getIsUpdating*(self: Model): bool {.slot.} = @@ -106,7 +91,6 @@ QtObject: return self.isUpdating = isUpdating self.isUpdatingChanged() - self.checkLoadingItems() proc isErrorChanged(self: Model) {.signal.} proc getIsError*(self: Model): bool {.slot.} = @@ -131,7 +115,6 @@ QtObject: return self.hasMore = hasMore self.hasMoreChanged() - self.checkLoadingItems() method canFetchMore*(self: Model, parent: QModelIndex): bool = return self.hasMore @@ -220,14 +203,6 @@ QtObject: result = newQVariant(item.getCommunityColor()) of CollectibleRole.CommunityPrivilegesLevel: result = newQVariant(item.getCommunityPrivilegesLevel()) - else: - # Loading item - case enumRole: - of CollectibleRole.IsLoading: - result = newQVariant(true) - else: - error "Invalid role for loading item" - result = newQVariant() proc rowData(self: Model, index: int, column: string): string {.slot.} = if (index >= self.items.len): @@ -287,48 +262,6 @@ QtObject: self.endRemoveRows() self.countChanged() - proc appendLoadingItems(self: Model) = - if self.hasLoadingItems: - return - - let parentModelIndex = newQModelIndex() - defer: parentModelIndex.delete - - # Start after the last real item - let startIdx = self.items.len - # End after loadingItemsCount - let endIdx = startIdx + loadingItemsCount - 1 - - self.beginInsertRows(parentModelIndex, startIdx, endIdx) - self.hasLoadingItems = true - self.endInsertRows() - self.countChanged() - - proc removeLoadingItems(self: Model) = - if not self.hasLoadingItems: - return - - let parentModelIndex = newQModelIndex() - defer: parentModelIndex.delete - - # Start after the last real item - let startIdx = self.items.len - # End after loadingItemsCount - let endIdx = startIdx + loadingItemsCount - 1 - - self.beginRemoveRows(parentModelIndex, startIdx, endIdx) - self.hasLoadingItems = false - self.endRemoveRows() - self.countChanged() - - proc checkLoadingItems(self: Model) = - # If fetch is in progress or we have more items in the DB, show loading items - let showLoadingItems = self.isUpdating or self.isFetching or self.hasMore - if showLoadingItems: - self.appendLoadingItems() - else: - self.removeLoadingItems() - proc getItems*(self: Model): seq[CollectiblesEntry] = return self.items @@ -341,7 +274,7 @@ QtObject: proc setItems*(self: Model, newItems: seq[CollectiblesEntry], offset: int, hasMore: bool) = if offset == 0: self.removeCollectibleItems() - elif offset != self.getCollectiblesCount(): + elif offset != self.getCount(): error "invalid offset" return diff --git a/src/app/modules/shared_modules/collectibles/controller.nim b/src/app/modules/shared_modules/collectibles/controller.nim index ff3ba5efe3..b875b0395d 100644 --- a/src/app/modules/shared_modules/collectibles/controller.nim +++ b/src/app/modules/shared_modules/collectibles/controller.nim @@ -130,7 +130,7 @@ QtObject: var offset = 0 if not self.fetchFromStart: if self.loadType.isPaginated(): - offset = self.model.getCollectiblesCount() + offset = self.model.getCount() else: offset = self.tempItems.len self.fetchFromStart = false diff --git a/storybook/pages/CollectiblesViewPage.qml b/storybook/pages/CollectiblesViewPage.qml index eb134f5504..de30950da4 100644 --- a/storybook/pages/CollectiblesViewPage.qml +++ b/storybook/pages/CollectiblesViewPage.qml @@ -102,6 +102,9 @@ SplitView { onReceiveRequested: logs.logEvent("onReceiveRequested", ["symbol"], arguments) onSwitchToCommunityRequested: logs.logEvent("onSwitchToCommunityRequested", ["communityId"], arguments) onManageTokensRequested: logs.logEvent("onManageTokensRequested") + isUpdating: ctrlUpdatingCheckbox.checked + isFetching: ctrlFetchingCheckbox.checked + isError: ctrlErrorCheckbox.checked } LogsAndControlsPanel { @@ -133,9 +136,19 @@ SplitView { } CheckBox { - id: loadingCheckbox + id: ctrlUpdatingCheckbox checked: false - text: "loading" + text: "isUpdating" + } + CheckBox { + id: ctrlFetchingCheckbox + checked: false + text: "isFetching" + } + CheckBox { + id: ctrlErrorCheckbox + checked: false + text: "isError" } ColumnLayout { diff --git a/ui/app/AppLayouts/Wallet/stores/CollectiblesStore.qml b/ui/app/AppLayouts/Wallet/stores/CollectiblesStore.qml index 4bfb81d473..e0a12302d8 100644 --- a/ui/app/AppLayouts/Wallet/stores/CollectiblesStore.qml +++ b/ui/app/AppLayouts/Wallet/stores/CollectiblesStore.qml @@ -38,6 +38,10 @@ QtObject { qsTr("%1 community collectibles are now visible").arg(communityName), "", "checkmark-circle", false, Constants.ephemeralNotificationType.success, "") } + readonly property bool areCollectiblesFetching: !!root._allCollectiblesModel ? root._allCollectiblesModel.isFetching : true + readonly property bool areCollectiblesUpdating: !!root._allCollectiblesModel ? root._allCollectiblesModel.isUpdating : false + readonly property bool areCollectiblesError: !!root._allCollectiblesModel ? root._allCollectiblesModel.isError : false + /* The following are used to display the detailed view of a collectible */ readonly property var detailedCollectible: Global.appIsReady ? walletSection.collectibleDetailsController.detailedEntry : null diff --git a/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml b/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml index 3457b4c538..f4ada31283 100644 --- a/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml +++ b/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml @@ -34,6 +34,9 @@ ColumnLayout { required property string networkFilters property bool sendEnabled: true property bool filterVisible + property bool isFetching: false // Indicates if a collectibles page is being loaded from the backend + property bool isUpdating: false // Indicates if the collectibles list is being updated + property bool isError: false // Indicates an error occurred while updating/fetching the collectibles list signal collectibleClicked(int chainId, string contractAddress, string tokenId, string uid) signal sendRequested(string symbol) @@ -53,8 +56,68 @@ ColumnLayout { readonly property bool isCustomView: cmbTokenOrder.currentValue === SortOrderComboBox.TokenOrderCustom - readonly property bool hasCollectibles: nonCommunityModel.count - readonly property bool hasCommunityCollectibles: communityModel.count + readonly property var sourceModel: root.controller.sourceModel + readonly property bool isLoading: root.isUpdating || root.isFetching + + onIsLoadingChanged: { + d.loadingItemsModel.refresh() + } + + readonly property var loadingItemsModel: ListModel { + Component.onCompleted: { + refresh() + } + + function refresh() { + clear() + if (d.isLoading) { + for (let i = 0; i < 10; i++) { + append({ isLoading: true }) + } + } + } + } + + readonly property var communityModel: CustomSFPM { + isCommunity: true + } + + readonly property var communityModelWithLoadingItems: ConcatModel { + sources: [ + SourceModel { + model: d.communityModel + markerRoleValue: "communityModel" + }, + SourceModel { + model: d.loadingItemsModel + markerRoleValue: "loadingItemsModel" + } + ] + + markerRoleName: "sourceGroup" + } + + readonly property var nonCommunityModel: CustomSFPM { + isCommunity: false + } + + readonly property var nonCommunityModelWithLoadingItems: ConcatModel { + sources: [ + SourceModel { + model: d.nonCommunityModel + markerRoleValue: "nonCommunityModel" + }, + SourceModel { + model: d.loadingItemsModel + markerRoleValue: "loadingItemsModel" + } + ] + + markerRoleName: "sourceGroup" + } + + readonly property bool hasCollectibles: d.nonCommunityModel.count || d.loadingItemsModel.count + readonly property bool hasCommunityCollectibles: d.communityModel.count || d.loadingItemsModel.count readonly property bool onlyOneType: !hasCollectibles || !hasCommunityCollectibles @@ -75,7 +138,7 @@ ColumnLayout { id: customFilter property bool isCommunity - sourceModel: root.controller.sourceModel + sourceModel: d.sourceModel proxyRoles: JoinRole { name: "groupName" roleNames: ["collectionName", "communityName"] @@ -125,16 +188,6 @@ ColumnLayout { ] } - CustomSFPM { - id: communityModel - - isCommunity: true - } - - CustomSFPM { - id: nonCommunityModel - } - Settings { id: settings category: "CollectiblesViewSortSettings" @@ -268,7 +321,7 @@ ColumnLayout { width: doubleFlickable.width cellHeight: d.communityCellHeight - model: communityModel + model: d.communityModelWithLoadingItems } flickable2: CustomGridView { @@ -302,7 +355,7 @@ ColumnLayout { width: doubleFlickable.width cellHeight: d.cellHeight - model: nonCommunityModel + model: d.nonCommunityModelWithLoadingItems } } diff --git a/ui/app/AppLayouts/Wallet/views/RightTabView.qml b/ui/app/AppLayouts/Wallet/views/RightTabView.qml index bd64b3bc7e..8362d0e33f 100644 --- a/ui/app/AppLayouts/Wallet/views/RightTabView.qml +++ b/ui/app/AppLayouts/Wallet/views/RightTabView.qml @@ -186,6 +186,9 @@ RightTabBaseView { onSwitchToCommunityRequested: (communityId) => Global.switchToCommunity(communityId) onManageTokensRequested: Global.changeAppSectionBySectionType(Constants.appSection.profile, Constants.settingsSubsection.wallet, Constants.walletSettingsSubsection.manageCollectibles) + isFetching: RootStore.collectiblesStore.areCollectiblesFetching + isUpdating: RootStore.collectiblesStore.areCollectiblesUpdating + isError: RootStore.collectiblesStore.areCollectiblesError } } Component {