Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ABW-3723] Resource hiding/unhiding #1290

Merged
merged 41 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
1da03ad
wip
matiasbzurovski Aug 16, 2024
688b507
Bump Sargon
matiasbzurovski Aug 16, 2024
4d93e41
wip
matiasbzurovski Aug 16, 2024
ec84bd0
hide asset (need to filter on every list now)
matiasbzurovski Aug 16, 2024
dde886d
filter fungible resources
matiasbzurovski Aug 19, 2024
d1a2fc4
show button on Pool Units and NFTs
matiasbzurovski Aug 19, 2024
dacdddd
filter pool units and nfts
matiasbzurovski Aug 19, 2024
38e2bd8
keep only NFTs with at least one visible id
matiasbzurovski Aug 19, 2024
9eca923
wip fetch nft and pool unit
matiasbzurovski Aug 19, 2024
b071023
Allow to unhide
matiasbzurovski Aug 19, 2024
9acbc93
lint
matiasbzurovski Aug 19, 2024
0ae045e
Update portfolio when assets are hidden/unhidden
matiasbzurovski Aug 19, 2024
769afa9
Merge branch 'main' into ABW-3723-resource-hiding
matiasbzurovski Aug 20, 2024
c50f6a4
comment
matiasbzurovski Aug 20, 2024
49acc2f
localisation
matiasbzurovski Aug 20, 2024
f7346bb
Helper methods
matiasbzurovski Aug 20, 2024
da12226
Display warning in TX review
matiasbzurovski Aug 20, 2024
88d57cc
Get complete details for pool units
matiasbzurovski Aug 20, 2024
4ef77f2
Merge branch 'main' into ABW-3723-resource-hiding
matiasbzurovski Aug 20, 2024
24ef5b5
localisation
matiasbzurovski Aug 20, 2024
2615cca
Get complete details for NFTs
matiasbzurovski Aug 20, 2024
445bcb9
localisation
matiasbzurovski Aug 20, 2024
539f608
Fix prices after unhiding asset
matiasbzurovski Aug 20, 2024
d7eeb34
feedback changes
matiasbzurovski Aug 21, 2024
6d801f3
[ABW-3553] Entities hiding (#1294)
matiasbzurovski Aug 22, 2024
3054e88
Merge branch 'main' into ABW-3723-resource-hiding
matiasbzurovski Aug 23, 2024
1d13824
wip
matiasbzurovski Aug 26, 2024
864f91a
WIP
matiasbzurovski Aug 26, 2024
6c870a6
Merge branch 'main' into ABW-3723-resource-hiding
matiasbzurovski Aug 26, 2024
d78aa10
update TX review message
matiasbzurovski Aug 26, 2024
52928c2
wip
matiasbzurovski Aug 26, 2024
845fb64
Merge branch 'main' into ABW-3723-resource-hiding
matiasbzurovski Aug 26, 2024
9608b67
changes
matiasbzurovski Aug 26, 2024
8b61442
Update HideResource UI
matiasbzurovski Aug 26, 2024
b95bc07
feedback from review
matiasbzurovski Aug 26, 2024
2a0c9aa
logic for nftIds count
matiasbzurovski Aug 27, 2024
71d4861
Merge branch 'main' into ABW-3723-resource-hiding
matiasbzurovski Aug 27, 2024
d68f401
show X in collection
matiasbzurovski Aug 27, 2024
1baa3d0
Update UI and include AssetRow
matiasbzurovski Aug 27, 2024
a44bd34
Update ResourceListView
matiasbzurovski Aug 27, 2024
fb99463
merged main
matiasbzurovski Aug 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 59 additions & 30 deletions RadixWallet.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,21 @@ extension AccountPortfoliosClient: DependencyKey {
}
}

/// Update when hidden resources change
Task {
for try await _ in await appPreferencesClient.appPreferenceUpdates().removeDuplicates(by: { $0.resources.hiddenResources == $1.resources.hiddenResources }) {
guard !Task.isCancelled else { return }
let accountAddresses = state.portfoliosSubject.value.wrappedValue.map { $0.map(\.key) } ?? []
_ = try await fetchAccountPortfolios(accountAddresses, forceRefreshEntities: false, forceRefreshPrices: true)
}
}

/// Fetches the pool and stake units details for a given account; Will update the portfolio accordingly
@Sendable
func fetchPoolAndStakeUnitsDetails(_ account: OnLedgerEntity.OnLedgerAccount, cachingStrategy: OnLedgerEntitiesClient.CachingStrategy) async {
func fetchPoolAndStakeUnitsDetails(_ account: OnLedgerEntity.OnLedgerAccount, hiddenResources: [ResourceIdentifier], cachingStrategy: OnLedgerEntitiesClient.CachingStrategy) async {
async let poolDetailsFetch = Task {
do {
let poolUnitDetails = try await onLedgerEntitiesClient.getOwnedPoolUnitsDetails(account, cachingStrategy: cachingStrategy)
let poolUnitDetails = try await onLedgerEntitiesClient.getOwnedPoolUnitsDetails(account, hiddenResources: hiddenResources, cachingStrategy: cachingStrategy)
await state.set(poolDetails: .success(poolUnitDetails), forAccount: account.address)
} catch {
await state.set(poolDetails: .failure(error), forAccount: account.address)
Expand Down Expand Up @@ -68,25 +77,28 @@ extension AccountPortfoliosClient: DependencyKey {
@Sendable
func fetchAccountPortfolios(
_ accountAddresses: [AccountAddress],
_ forceRefresh: Bool
forceRefreshEntities: Bool,
forceRefreshPrices: Bool
) async throws -> [AccountPortfolio] {
let gateway = await gatewaysClient.getCurrentGateway()
await state.setRadixGateway(gateway)
if forceRefresh {
if forceRefreshEntities {
for accountAddress in accountAddresses {
cacheClient.removeFolder(.init(address: accountAddress))
}
}

/// Explicetely load and set the currency target and visibility to make sure
/// it is available for usage before resources are loaded
let preferences = await appPreferencesClient.getPreferences().display
await state.setSelectedCurrency(preferences.fiatCurrencyPriceTarget)
await state.setIsCurrencyAmountVisble(preferences.isCurrencyAmountVisible)
let preferences = await appPreferencesClient.getPreferences()
let display = preferences.display
await state.setSelectedCurrency(display.fiatCurrencyPriceTarget)
await state.setIsCurrencyAmountVisble(display.isCurrencyAmountVisible)

let accounts = try await onLedgerEntitiesClient.getAccounts(accountAddresses)
let hiddenResources = preferences.resources.hiddenResources

let portfolios = accounts.map { AccountPortfolio(account: $0) }
let portfolios = accounts.map { AccountPortfolio(account: $0, hiddenResources: hiddenResources) }
await state.handlePortfoliosUpdate(portfolios)

/// Put together all resources from already fetched and new accounts
Expand Down Expand Up @@ -120,11 +132,11 @@ extension AccountPortfoliosClient: DependencyKey {
}
}()

await applyTokenPrices(Array(allResources), forceRefresh: forceRefresh)
await applyTokenPrices(Array(allResources), forceRefresh: forceRefreshPrices)

// Load additional details
_ = await accounts.map(\.nonEmptyVaults).parallelMap {
await fetchPoolAndStakeUnitsDetails($0, cachingStrategy: forceRefresh ? .forceUpdate : .useCache)
await fetchPoolAndStakeUnitsDetails($0, hiddenResources: hiddenResources, cachingStrategy: forceRefreshEntities ? .forceUpdate : .useCache)
}

return Array(state.portfoliosSubject.value.wrappedValue!.values)
Expand All @@ -140,7 +152,8 @@ extension AccountPortfoliosClient: DependencyKey {
}

let account = try await onLedgerEntitiesClient.getAccount(accountAddress)
let portfolio = AccountPortfolio(account: account)
let hiddenResources = await appPreferencesClient.getHiddenResources()
let portfolio = AccountPortfolio(account: account, hiddenResources: hiddenResources)

if case let .success(tokenPrices) = await state.tokenPrices {
await applyTokenPrices(
Expand All @@ -150,15 +163,15 @@ extension AccountPortfoliosClient: DependencyKey {
}

await state.handlePortfolioUpdate(portfolio)
await fetchPoolAndStakeUnitsDetails(account.nonEmptyVaults, cachingStrategy: forceRefresh ? .forceUpdate : .useCache)
await fetchPoolAndStakeUnitsDetails(account.nonEmptyVaults, hiddenResources: hiddenResources, cachingStrategy: forceRefresh ? .forceUpdate : .useCache)

return portfolio
}

return AccountPortfoliosClient(
fetchAccountPortfolios: { accountAddresses, forceRefresh in
try await Task.detached {
try await fetchAccountPortfolios(accountAddresses, forceRefresh)
try await fetchAccountPortfolios(accountAddresses, forceRefreshEntities: forceRefresh, forceRefreshPrices: forceRefresh)
}.value
},
fetchAccountPortfolio: { accountAddress, forceRefresh in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Foundation
extension AccountPortfoliosClient {
public struct AccountPortfolio: Sendable, Hashable, CustomDebugStringConvertible {
public var account: OnLedgerEntity.OnLedgerAccount
public let hiddenResources: [ResourceIdentifier]
public var poolUnitDetails: Loadable<[OnLedgerEntitiesClient.OwnedResourcePoolDetails]> = .idle
public var stakeUnitDetails: Loadable<IdentifiedArrayOf<OnLedgerEntitiesClient.OwnedStakeDetails>> = .idle

Expand All @@ -12,6 +13,28 @@ extension AccountPortfoliosClient {
public var debugDescription: String {
account.debugDescription
}

init(account: OnLedgerEntity.OnLedgerAccount, hiddenResources: [ResourceIdentifier]) {
var modified = account

// Remove every hidden fungible resource
modified.fungibleResources.nonXrdResources.removeAll(where: { resource in
hiddenResources.contains(.fungible(resource.resourceAddress))
})

// Remove every hidden non fungible resource
modified.nonFungibleResources.removeAll(where: { resource in
hiddenResources.contains(.nonFungible(resource.resourceAddress))
})

// Remove every hidden pool unit
modified.poolUnitResources.poolUnits.removeAll(where: { poolUnit in
hiddenResources.contains(.poolUnit(poolUnit.resourcePoolAddress))
})

self.account = modified
self.hiddenResources = hiddenResources
}
}

/// Internal state that holds all loaded portfolios.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ extension AppPreferencesClient {
display.isCurrencyAmountVisible.toggle()
}
}

public func getHiddenResources() async -> [ResourceIdentifier] {
await getPreferences().resources.hiddenResources
}

public func isResourceHidden(_ resource: ResourceIdentifier) async -> Bool {
await getHiddenResources().contains(resource)
}
}

// MARK: AppPreferencesClient.Error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,22 @@
// MARK: - EntitiesVisibilityClient
/// Controls the visibility of the entities in the Wallet
public struct EntitiesVisibilityClient: Sendable {
public var hideAccounts: HideAccounts
public var hidePersonas: HidePersonas
public var unhideAllEntities: UnhideAllEntities
public var getHiddenEntityCounts: GetHiddenEntityCounts
public var hideAccount: HideAccount
public var hidePersona: HidePersona
public var unhideAccount: UnhideAccount
public var unhidePersona: UnhidePersona
public var getHiddenEntities: GetHiddenEntities
}

extension EntitiesVisibilityClient {
public struct HiddenEntityCounts: Hashable, Sendable {
public let hiddenAccountsCount: Int
public let hiddenPersonasCount: Int
public struct HiddenEntities: Hashable, Sendable {
public let accounts: Accounts
public let personas: Personas
}

public typealias HideAccounts = @Sendable (Set<Account.ID>) async throws -> Void
public typealias HidePersonas = @Sendable (Set<Persona.ID>) async throws -> Void
public typealias UnhideAllEntities = @Sendable () async throws -> Void
public typealias GetHiddenEntityCounts = @Sendable () async throws -> HiddenEntityCounts
}

extension EntitiesVisibilityClient {
public func hideAccounts(ids: some Collection<Account.ID>) async throws {
try await hideAccounts(Set(ids))
}

public func hidePersonas(ids: some Collection<Persona.ID>) async throws {
try await hidePersonas(Set(ids))
}

public func hide(accounts: some Collection<Account>) async throws {
try await hideAccounts(ids: accounts.map(\.id))
}

public func hide(personas: some Collection<Persona>) async throws {
try await hidePersonas(ids: personas.map(\.id))
}

public func hide(account: Account) async throws {
try await hide(accounts: [account])
}

public func hide(persona: Persona) async throws {
try await hide(personas: [persona])
}
public typealias HideAccount = @Sendable (Account.ID) async throws -> Void
public typealias HidePersona = @Sendable (Persona.ID) async throws -> Void
public typealias UnhideAccount = @Sendable (Account.ID) async throws -> Void
public typealias UnhidePersona = @Sendable (Persona.ID) async throws -> Void
public typealias GetHiddenEntities = @Sendable () async throws -> HiddenEntities
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,29 @@ extension EntitiesVisibilityClient: DependencyKey {
profileStore: ProfileStore = .shared
) -> Self {
.init(
hideAccounts: { idsOfAccounts in
hideAccount: { id in
try await profileStore.updatingOnCurrentNetwork { network in
network.hideAccounts(ids: idsOfAccounts)
network.hideAccount(id: id)
}
},
hidePersonas: { idsOfPersonas in
hidePersona: { id in
try await profileStore.updatingOnCurrentNetwork { network in
network.hidePersonas(ids: idsOfPersonas)
network.hidePersona(id: id)
}
},
unhideAllEntities: {
unhideAccount: { id in
try await profileStore.updatingOnCurrentNetwork { network in
network.unhideAllEntities()
network.unhideAccount(id: id)
}
},
getHiddenEntityCounts: {
unhidePersona: { id in
try await profileStore.updatingOnCurrentNetwork { network in
network.unhidePersona(id: id)
}
},
getHiddenEntities: {
let network = try await profileStore.network()

return .init(
hiddenAccountsCount: network.getHiddenAccounts().count,
hiddenPersonasCount: network.getHiddenPersonas().count
)
return .init(accounts: network.getHiddenAccounts(), personas: network.getHiddenPersonas())
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ extension EntitiesVisibilityClient: TestDependencyKey {
public static let previewValue = Self.noop

public static let noop = Self(
hideAccounts: { _ in throw NoopError() },
hidePersonas: { _ in throw NoopError() },
unhideAllEntities: { throw NoopError() },
getHiddenEntityCounts: { throw NoopError() }
hideAccount: { _ in throw NoopError() },
hidePersona: { _ in throw NoopError() },
unhideAccount: { _ in throw NoopError() },
unhidePersona: { _ in throw NoopError() },
getHiddenEntities: { throw NoopError() }
)

public static let testValue = Self(
hideAccounts: unimplemented("\(Self.self).hideAccounts"),
hidePersonas: unimplemented("\(Self.self).hidePersonas"),
unhideAllEntities: unimplemented("\(Self.self).unhideAllEntities"),
getHiddenEntityCounts: unimplemented("\(Self.self).getHiddenEntityCounts")
hideAccount: unimplemented("\(Self.self).hideAccount"),
hidePersona: unimplemented("\(Self.self).hidePersona"),
unhideAccount: unimplemented("\(Self.self).unhideAccount"),
unhidePersona: unimplemented("\(Self.self).unhidePersona"),
getHiddenEntities: unimplemented("\(Self.self).getHiddenEntities")
)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import Algorithms
import Sargon

public typealias ResourceIdentifier = String

// MARK: - GatewayAPIClient
public struct GatewayAPIClient: Sendable, DependencyKey {
// MARK: Request
Expand Down
Loading
Loading