diff --git a/RadixWallet/Features/AssetsFeature/AssetsView+Reducer.swift b/RadixWallet/Features/AssetsFeature/AssetsView+Reducer.swift index 1e8da4c439..f4c1145187 100644 --- a/RadixWallet/Features/AssetsFeature/AssetsView+Reducer.swift +++ b/RadixWallet/Features/AssetsFeature/AssetsView+Reducer.swift @@ -154,8 +154,9 @@ public struct AssetsView: Sendable, FeatureReducer { state.isLoadingResources = false state.isRefreshing = false portfolio.account = portfolio.account.nonEmptyVaults - updateFromPortfolio(state: &state, from: portfolio) - return .none + let nftRowsToRefresh = updateFromPortfolio(state: &state, from: portfolio) + + return !nftRowsToRefresh.isEmpty ? .send(.child(.nonFungibleTokenList(.internal(.refreshRows(nftRowsToRefresh))))) : .none } } diff --git a/RadixWallet/Features/AssetsFeature/AssetsView+Update.swift b/RadixWallet/Features/AssetsFeature/AssetsView+Update.swift index d99528fdba..a06a616638 100644 --- a/RadixWallet/Features/AssetsFeature/AssetsView+Update.swift +++ b/RadixWallet/Features/AssetsFeature/AssetsView+Update.swift @@ -2,10 +2,12 @@ import ComposableArchitecture import SwiftUI extension AssetsView { + typealias NFTRowsToRefresh = [ResourceAddress] + func updateFromPortfolio( state: inout State, from portfolio: AccountPortfoliosClient.AccountPortfolio - ) { + ) -> NFTRowsToRefresh { let mode = state.mode let xrd = portfolio.account.fungibleResources.xrdResource.map { token in let updatedRow = state.resources.fungibleTokenList?.updatedRow(token: token, for: .xrd) @@ -35,6 +37,13 @@ extension AssetsView { selectedAssets: mode.nftRowSelectedAssets(resource.resourceAddress) ) } + let nftRowsToRefresh: [ResourceAddress] = portfolio.account.nonFungibleResources.compactMap { resource in + state.resources.nonFungibleTokenList?.rows.first { + $0.id == resource.resourceAddress && + $0.resource.nonFungibleIdsCount != resource.nonFungibleIdsCount && + $0.isExpanded + }?.id + } let fungibleTokenList: FungibleAssetList.State? = { var sections: IdentifiedArrayOf = [] @@ -116,6 +125,8 @@ extension AssetsView { stakeUnitList: stakeUnitList, poolUnitsList: poolUnitList ) + + return nftRowsToRefresh } } diff --git a/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/Components/Row/NonFungbileAssetRow+Reducer.swift b/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/Components/Row/NonFungbileAssetRow+Reducer.swift index 5fd1dcd24f..f2afe80963 100644 --- a/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/Components/Row/NonFungbileAssetRow+Reducer.swift +++ b/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/Components/Row/NonFungbileAssetRow+Reducer.swift @@ -59,6 +59,7 @@ extension NonFungibleAssetList { } case tokensLoaded(TaskResult) + case refreshResources } @Dependency(\.onLedgerEntitiesClient) var onLedgerEntitiesClient @@ -80,20 +81,7 @@ extension NonFungibleAssetList { case .isExpandedToggled: state.isExpanded.toggle() if state.isExpanded { - if state.resource.nonFungibleIdsCount < State.pageSize { - state.tokens = [.init(repeating: .loading, count: state.resource.nonFungibleIdsCount)] - } else { - /// The total number of full pages - let fullPagesCount = state.resource.nonFungibleIdsCount / State.pageSize - /// Prepopulate with placeholders - state.tokens = .init(repeating: .init(repeating: .loading, count: State.pageSize), count: fullPagesCount) - /// The number of items to add to the last page - let remainder = state.resource.nonFungibleIdsCount % State.pageSize - if fullPagesCount > 0, remainder > 0 { - /// At last page placeholders also - state.tokens.append(.init(repeating: .loading, count: remainder)) - } - } + setTokensPlaceholders(&state) return loadResources(&state, pageIndex: 0) } @@ -131,10 +119,15 @@ extension NonFungibleAssetList { state.isLoadingResources = false } return .none + + case .refreshResources: + state.nextPageCursor = nil + setTokensPlaceholders(&state) + return loadResources(&state, pageIndex: 0) } } - func loadResources(_ state: inout State, pageIndex: Int) -> Effect { + private func loadResources(_ state: inout State, pageIndex: Int) -> Effect { state.isLoadingResources = true let cursor = state.nextPageCursor return .run { [resource = state.resource, accountAddress = state.accountAddress] send in @@ -145,5 +138,22 @@ extension NonFungibleAssetList { await send(.internal(.tokensLoaded(result))) } } + + private func setTokensPlaceholders(_ state: inout State) { + if state.resource.nonFungibleIdsCount < State.pageSize { + state.tokens = [.init(repeating: .loading, count: state.resource.nonFungibleIdsCount)] + } else { + /// The total number of full pages + let fullPagesCount = state.resource.nonFungibleIdsCount / State.pageSize + /// Prepopulate with placeholders + state.tokens = .init(repeating: .init(repeating: .loading, count: State.pageSize), count: fullPagesCount) + /// The number of items to add to the last page + let remainder = state.resource.nonFungibleIdsCount % State.pageSize + if fullPagesCount > 0, remainder > 0 { + /// At last page placeholders also + state.tokens.append(.init(repeating: .loading, count: remainder)) + } + } + } } } diff --git a/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/NonFungibleAssetList+Reducer.swift b/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/NonFungibleAssetList+Reducer.swift index b01682eca9..d1f291da4d 100644 --- a/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/NonFungibleAssetList+Reducer.swift +++ b/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/NonFungibleAssetList+Reducer.swift @@ -10,6 +10,10 @@ public struct NonFungibleAssetList: Sendable, FeatureReducer { case asset(NonFungibleAssetList.Row.State.ID, NonFungibleAssetList.Row.Action) } + public enum InternalAction: Sendable, Equatable { + case refreshRows([ResourceAddress]) + } + public enum DelegateAction: Sendable, Equatable { case selected(OnLedgerEntity.OwnedNonFungibleResource, token: OnLedgerEntity.NonFungibleToken) } @@ -36,4 +40,11 @@ public struct NonFungibleAssetList: Sendable, FeatureReducer { return .none } } + + public func reduce(into state: inout State, internalAction: InternalAction) -> Effect { + switch internalAction { + case let .refreshRows(rows): + .merge(rows.map { .send(.child(.asset($0, .internal(.refreshResources)))) }) + } + } }