Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
exclude assets that is isDeletedByUser:true in edit assets list and s…
Browse files Browse the repository at this point in the history
…earch assets list. add junk label in NFT details. address some code review comments.
  • Loading branch information
nuo-xu committed Oct 13, 2023
1 parent 1f35fe7 commit 719f966
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 20 deletions.
20 changes: 20 additions & 0 deletions Sources/BraveWallet/Crypto/NFT/NFTDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ struct NFTDetailView: View {
.frame(maxWidth: .infinity, minHeight: 300)
} else {
nftImage
.overlay(alignment: .topLeading) {
if nftDetailStore.nft.isSpam {
HStack(spacing: 4) {
Text(Strings.Wallet.nftSpam)
.padding(.vertical, 4)
.padding(.leading, 6)
.foregroundColor(Color(.braveErrorLabel))
Image(braveSystemName: "leo.warning.triangle-outline")
.padding(.vertical, 4)
.padding(.trailing, 6)
.foregroundColor(Color(.braveErrorBorder))
}
.font(.system(size: 13).weight(.semibold))
.background(
Color(uiColor: WalletV2Design.spamNFTLabelBackground)
.cornerRadius(4)
)
.padding(12)
}
}
}
VStack(alignment: .leading, spacing: 8) {
Text(nftDetailStore.nft.nftTokenTitle)
Expand Down
35 changes: 34 additions & 1 deletion Sources/BraveWallet/Crypto/NFT/NFTView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct NFTView: View {
@State private var isShowingNFTDiscoveryAlert: Bool = false
@State private var isShowingAddCustomNFT: Bool = false
@State private var isNFTDiscoveryEnabled: Bool = false
@State private var nftToBeRemoved: NFTAssetViewModel?

@Environment(\.buySendSwapDestination)
private var buySendSwapDestination: Binding<BuySendSwapDestination?>
Expand Down Expand Up @@ -243,7 +244,7 @@ struct NFTView: View {
}
}
Button(action: {
nftStore.updateNFTStatus(nft.token, visible: false, isSpam: nft.token.isSpam, isDeletedByUser: true)
nftToBeRemoved = nft
}) {
Label(Strings.Wallet.nftRemoveFromWallet, braveSystemImage: "leo.trash")
}
Expand Down Expand Up @@ -331,6 +332,38 @@ struct NFTView: View {
}
)
)
.background(
WalletPromptView(
isPresented: Binding(
get: { nftToBeRemoved != nil },
set: { if !$0 { nftToBeRemoved = nil } }
),
primaryButton: .init(
title: Strings.Wallet.manageSiteConnectionsConfirmAlertRemove,
action: { _ in
guard let nft = nftToBeRemoved else { return }
nftStore.updateNFTStatus(nft.token, visible: false, isSpam: nft.token.isSpam, isDeletedByUser: true)
nftToBeRemoved = nil
}
),
secondaryButton: .init(
title: Strings.CancelString,
action: { _ in
nftToBeRemoved = nil
}
),
showCloseButton: false,
content: {
VStack(spacing: 16) {
Text(Strings.Wallet.nftRemoveFromWalletAlertTitle)
.font(.headline)
.foregroundColor(Color(.bravePrimary))
Text(Strings.Wallet.nftRemoveFromWalletAlertDescription)
.font(.footnote)
.foregroundStyle(Color(.secondaryBraveLabel))
}
})
)
.sheet(isPresented: $isShowingAddCustomNFT) {
AddCustomAssetView(
networkStore: networkStore,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class AccountActivityStore: ObservableObject, WalletObserverStore {
let tokens: [BraveWallet.BlockchainToken]
let sortOrder: Int
}
let allUserAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: networksForAccount, includingSpam: true)
let allUserAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: networksForAccount, includingUserDeleted: true)
let allTokens = await blockchainRegistry.allTokens(in: networksForAccountCoin).flatMap(\.tokens)
var updatedUserAssets: [AssetViewModel] = []
var updatedUserNFTs: [NFTAssetViewModel] = []
Expand Down
2 changes: 1 addition & 1 deletion Sources/BraveWallet/Crypto/Stores/AssetDetailStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ class AssetDetailStore: ObservableObject, WalletObserverStore {
) async -> [TransactionSummary] {
guard case let .blockchainToken(token) = assetDetailType
else { return [] }
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingSpam: true).flatMap { $0.tokens }
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingUserDeleted: true).flatMap { $0.tokens }
let allTokens = await blockchainRegistry.allTokens(network.chainId, coin: network.coin)
let allTransactions = await withTaskGroup(of: [BraveWallet.TransactionInfo].self) { @MainActor group -> [BraveWallet.TransactionInfo] in
for account in keyring.accountInfos {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore
let transactionNetworks: [BraveWallet.NetworkInfo] = Set(allTxs.map(\.chainId))
.compactMap { chainId in allNetworks.first(where: { $0.chainId == chainId }) }
for network in transactionNetworks {
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingSpam: true).flatMap { $0.tokens }
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingUserDeleted: true).flatMap { $0.tokens }
await fetchAssetRatios(for: userAssets)
}
await fetchUnknownTokens(for: unapprovedTxs)
Expand Down Expand Up @@ -307,7 +307,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore
return
}
let allTokens = await blockchainRegistry.allTokens(network.chainId, coin: coin) + tokenInfoCache.map(\.value)
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingSpam: true).flatMap { $0.tokens }
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingUserDeleted: true).flatMap { $0.tokens }
let solEstimatedTxFee: UInt64? = solEstimatedTxFeeCache[transaction.id]

if transaction.isEIP1559Transaction {
Expand Down Expand Up @@ -431,7 +431,7 @@ public class TransactionConfirmationStore: ObservableObject, WalletObserverStore
guard let network = allNetworks.first(where: { $0.chainId == BraveWallet.MainnetChainId }) else {
return
}
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingSpam: true).flatMap { $0.tokens }
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingUserDeleted: true).flatMap { $0.tokens }
let allTokens = await blockchainRegistry.allTokens(network.chainId, coin: network.coin)
let unknownTokenContractAddresses = mainnetTransactions.flatMap(\.tokenContractAddresses)
.filter { contractAddress in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class TransactionDetailsStore: ObservableObject, WalletObserverStore {
let keringId = BraveWallet.KeyringId.keyringId(for: coin, on: transaction.chainId)
let keyring = await keyringService.keyringInfo(keringId)
var allTokens: [BraveWallet.BlockchainToken] = await blockchainRegistry.allTokens(network.chainId, coin: network.coin) + tokenInfoCache.map(\.value)
let userAssets: [BraveWallet.BlockchainToken] = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingSpam: true).flatMap { $0.tokens }
let userAssets: [BraveWallet.BlockchainToken] = assetManager.getAllUserAssetsInNetworkAssets(networks: [network], includingUserDeleted: true).flatMap { $0.tokens }
let unknownTokenContractAddresses = transaction.tokenContractAddresses
.filter { contractAddress in
!userAssets.contains(where: { $0.contractAddress(in: network).caseInsensitiveCompare(contractAddress) == .orderedSame })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class TransactionsActivityStore: ObservableObject, WalletObserverStore {
let allTransactions = await txService.allTransactions(
networksForCoin: networksForCoin, for: allKeyrings
).filter { $0.txStatus != .rejected }
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: allNetworksAllCoins, includingSpam: true).flatMap(\.tokens)
let userAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: allNetworksAllCoins, includingUserDeleted: true).flatMap(\.tokens)
let allTokens = await blockchainRegistry.allTokens(
in: allNetworksAllCoins
).flatMap(\.tokens)
Expand Down
6 changes: 3 additions & 3 deletions Sources/BraveWallet/Crypto/Stores/UserAssetsStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public class UserAssetsStore: ObservableObject, WalletObserverStore {
}
}
let networks: [BraveWallet.NetworkInfo] = self.networkFilters.filter(\.isSelected).map(\.model)
let allUserAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: networks, includingSpam: true)
let allUserAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: networks, includingUserDeleted: false)
var allTokens = await self.blockchainRegistry.allTokens(in: networks)
// Filter `allTokens` to remove any tokens existing in `allUserAssets`. This is possible for ERC721 tokens in the registry without a `tokenId`, which requires the user to add as a custom token
let allUserTokens = allUserAssets.flatMap(\.tokens)
Expand Down Expand Up @@ -233,7 +233,7 @@ public class UserAssetsStore: ObservableObject, WalletObserverStore {

@MainActor func allAssets() async -> [AssetViewModel] {
let allNetworks = await rpcService.allNetworksForSupportedCoins()
let allUserAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: allNetworks, includingSpam: true)
let allUserAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: allNetworks, includingUserDeleted: false)
// Filter `allTokens` to remove any tokens existing in `allUserAssets`. This is possible for ERC721 tokens in the registry without a `tokenId`, which requires the user to add as a custom token
let allUserTokens = allUserAssets.flatMap(\.tokens)
let allBlockchainTokens = await blockchainRegistry.allTokens(in: allNetworks)
Expand Down Expand Up @@ -262,7 +262,7 @@ public class UserAssetsStore: ObservableObject, WalletObserverStore {

@MainActor func allNFTMetadata() async -> [String: NFTMetadata] {
let allNetworks = await rpcService.allNetworksForSupportedCoins()
let allUserAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: allNetworks, includingSpam: true)
let allUserAssets = assetManager.getAllUserAssetsInNetworkAssets(networks: allNetworks, includingUserDeleted: true)
// Filter `allTokens` to remove any tokens existing in `allUserAssets`. This is possible for ERC721 tokens in the registry without a `tokenId`, which requires the user to add as a custom token
let allUserTokens = allUserAssets.flatMap(\.tokens)

Expand Down
2 changes: 1 addition & 1 deletion Sources/BraveWallet/Extensions/WalletColors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ enum WalletV2Design {
static let passwordStrongGreen = UIColor(rgb: 0x31803e)

static let spamNFTLabelBackground = UIColor(
red: 255 / 255,
red: 1,
green: 209 / 255,
blue: 207 / 255,
alpha: 1
Expand Down
14 changes: 14 additions & 0 deletions Sources/BraveWallet/WalletStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4360,6 +4360,20 @@ extension Strings {
value: "Don't show in wallet",
comment: "The title of context button for user to do not show a NFT in wallet at all."
)
public static let nftRemoveFromWalletAlertTitle = NSLocalizedString(
"wallet.nftRemoveFromWalletAlertTitle",
tableName: "BraveWallet",
bundle: .module,
value: "Remove from Brave Wallet?",
comment: "The title of the alert when user attempts to remove an NFT from wallet."
)
public static let nftRemoveFromWalletAlertDescription = NSLocalizedString(
"wallet.nftRemoveFromWalletAlertDescription",
tableName: "BraveWallet",
bundle: .module,
value: "NFT will be removed from Brave Wallet but will remain on the blockchain. If you remove it, then change your mind, you'll need to import it again manually.",
comment: "The description of the alert when user attempts to remove an NFT from wallet."
)
public static let selectTokenToSendTitle = NSLocalizedString(
"wallet.selectTokenToSendTitle",
tableName: "BraveWallet",
Expand Down
16 changes: 8 additions & 8 deletions Sources/BraveWallet/WalletUserAssetManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public protocol WalletUserAssetManagerType: AnyObject {
/// Return all visible or all invisible user assets in form of `NetworkAssets`
func getAllUserAssetsInNetworkAssetsByVisibility(networks: [BraveWallet.NetworkInfo], visible: Bool) -> [NetworkAssets]
/// Return all user assets in form of `NetworkAssets`
func getAllUserAssetsInNetworkAssets(networks: [BraveWallet.NetworkInfo], includingSpam: Bool) -> [NetworkAssets]
func getAllUserAssetsInNetworkAssets(networks: [BraveWallet.NetworkInfo], includingUserDeleted: Bool) -> [NetworkAssets]
/// Return all spam or non-spam user assets in form of `NetworkAssets`
func getAllUserNFTs(networks: [BraveWallet.NetworkInfo], isSpam: Bool) -> [NetworkAssets]
/// Return all user marked deleted user assets
Expand Down Expand Up @@ -46,13 +46,13 @@ public class WalletUserAssetManager: WalletUserAssetManagerType {
}

/// Return all user's assets stored in CoreData
public func getAllUserAssetsInNetworkAssets(networks: [BraveWallet.NetworkInfo], includingSpam: Bool) -> [NetworkAssets] {
public func getAllUserAssetsInNetworkAssets(networks: [BraveWallet.NetworkInfo], includingUserDeleted: Bool) -> [NetworkAssets] {
var allUserAssets: [NetworkAssets] = []
for (index, network) in networks.enumerated() {
let groupId = network.walletUserAssetGroupId
if let walletUserAssets = WalletUserAssetGroup.getGroup(groupId: groupId)?.walletUserAssets?.filter({
if !includingSpam {
return $0.isSpam == false
if !includingUserDeleted {
return $0.isDeletedByUser == false
}
return true
}) {
Expand Down Expand Up @@ -114,7 +114,7 @@ public class WalletUserAssetManager: WalletUserAssetManagerType {
if let existedAsset = WalletUserAsset.getUserAsset(asset: asset) {
if existedAsset.isDeletedByUser { // this asset was added before but user marked as deleted after
WalletUserAsset.updateUserAsset(for: asset, visible: true, isSpam: false, isDeletedByUser: false, completion: completion)
} else { // this asset exists, either in `Collected` or `Hidden` based on its `visible` value
} else { // this asset already exists
completion?()
return
}
Expand Down Expand Up @@ -195,19 +195,19 @@ public class WalletUserAssetManager: WalletUserAssetManagerType {
#if DEBUG
public class TestableWalletUserAssetManager: WalletUserAssetManagerType {
public var _getAllUserAssetsInNetworkAssetsByVisibility: ((_ networks: [BraveWallet.NetworkInfo], _ visible: Bool) -> [NetworkAssets])?
public var _getAllUserAssetsInNetworkAssets: ((_ networks: [BraveWallet.NetworkInfo], _ includingSpam: Bool) -> [NetworkAssets])?
public var _getAllUserAssetsInNetworkAssets: ((_ networks: [BraveWallet.NetworkInfo], _ includingUserDeleted: Bool) -> [NetworkAssets])?
public var _getAllUserNFTs: ((_ networks: [BraveWallet.NetworkInfo], _ spamStatus: Bool) -> [NetworkAssets])?
public var _getAllUserDeletedNFTs: (() -> [WalletUserAsset])?

public init() {}

public func getAllUserAssetsInNetworkAssets(networks: [BraveWallet.NetworkInfo], includingSpam: Bool) -> [NetworkAssets] {
public func getAllUserAssetsInNetworkAssets(networks: [BraveWallet.NetworkInfo], includingUserDeleted: Bool) -> [NetworkAssets] {
let defaultAssets: [NetworkAssets] = [
NetworkAssets(network: .mockMainnet, tokens: [.previewToken], sortOrder: 0),
NetworkAssets(network: .mockGoerli, tokens: [.previewToken], sortOrder: 1)
]
let chainIds = networks.map { $0.chainId }
return _getAllUserAssetsInNetworkAssets?(networks, includingSpam) ?? defaultAssets.filter({
return _getAllUserAssetsInNetworkAssets?(networks, includingUserDeleted) ?? defaultAssets.filter({
chainIds.contains($0.network.chainId)
})
}
Expand Down

0 comments on commit 719f966

Please sign in to comment.