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

Commit

Permalink
Split AssetIconView into AssetIcon (no sizing) and `AssetIconView…
Browse files Browse the repository at this point in the history
…` (applies dynamic sizing). Split `NetworkIcon` into `NetworkIcon` (no sizing) and `NetworkIconView` (applies dynamic sizing).

Update `MultipleCircleIconView` to apply a background instead of just a stroke for when transparent icons are used.
  • Loading branch information
StephenHeaps committed Jan 19, 2024
1 parent 6824b33 commit 0b43005
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 60 deletions.
15 changes: 3 additions & 12 deletions Sources/BraveWallet/Crypto/Accounts/AccountsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -289,20 +289,11 @@ private struct AccountCardView: View {
.redacted(reason: .placeholder)
.shimmer(true)
} else {
MultipleCircleIconView(
models: tokensWithBalances,
shape: .circle,
MultipleAssetIconsView(
tokens: tokensWithBalances,
iconSize: 24,
maxIconSize: 32
) { token in
AssetIconView(
token: token,
network: .init(), // not shown
shouldShowNetworkIcon: false,
length: 24,
maxLength: 32
)
}
)
Spacer()
Text(balance)
.font(.title3.weight(.medium))
Expand Down
82 changes: 46 additions & 36 deletions Sources/BraveWallet/Crypto/AssetIconView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,11 @@ import BraveCore
import BraveUI
import DesignSystem

/// Displays an asset's icon from the token registry
///
/// By default, creating an `AssetIconView` will result in a dynamically sized icon based
/// on the users size category. If you for some reason need to obtain a fixed size asset icon,
/// wrap this view in another frame of your desired size, for example:
///
/// AssetIconView(token: .eth)
/// .frame(width: 20, height: 20)
///
struct AssetIconView: View {
var token: BraveWallet.BlockchainToken
var network: BraveWallet.NetworkInfo
/// If we should show the network logo on non-native assets
var shouldShowNetworkIcon: Bool = false
@ScaledMetric var length: CGFloat = 40
var maxLength: CGFloat?
@ScaledMetric var networkSymbolLength: CGFloat = 15
var maxNetworkSymbolLength: CGFloat?

private var fallbackMonogram: some View {
BlockieMaterial(address: token.contractAddress)
.blur(radius: 8, opaque: true)
.clipShape(Circle())
.overlay(
Text(token.symbol.first?.uppercased() ?? "")
.font(.system(size: length / 2, weight: .bold, design: .rounded))
.foregroundColor(.white)
.shadow(color: .black.opacity(0.3), radius: 2, x: 0, y: 1)
)
}

/// Displays an asset's icon from the token registry or logo.
struct AssetIcon: View {
let token: BraveWallet.BlockchainToken
let network: BraveWallet.NetworkInfo?

var body: some View {
Group {
if let uiImage = token.localImage(network: network) {
Expand All @@ -59,13 +33,49 @@ struct AssetIconView: View {
fallbackMonogram
}
}
.frame(width: min(length, maxLength ?? length), height: min(length, maxLength ?? length))
.overlay(tokenLogo, alignment: .bottomTrailing)
.accessibilityHidden(true)
}

@ViewBuilder private var tokenLogo: some View {
if shouldShowNetworkIcon, // explicitly show/not show network logo
@State private var monogramSize: CGSize = .zero
private var fallbackMonogram: some View {
BlockieMaterial(address: token.contractAddress)
.blur(radius: 8, opaque: true)
.clipShape(Circle())
.readSize(onChange: { newSize in
monogramSize = newSize
})
.overlay(
Text(token.symbol.first?.uppercased() ?? "")
.font(.system(size: max(monogramSize.width, monogramSize.height) / 2, weight: .bold, design: .rounded))
.foregroundColor(.white)
.shadow(color: .black.opacity(0.3), radius: 2, x: 0, y: 1)
)
}
}

/// Displays an asset's icon from the token registry or logo.
///
/// By default, creating an `AssetIconView` will result in a dynamically sized icon based
/// on the users size category.
struct AssetIconView: View {
var token: BraveWallet.BlockchainToken
var network: BraveWallet.NetworkInfo?
/// If we should show the network logo on non-native assets. NetworkInfo is required.
var shouldShowNetworkIcon: Bool = false
@ScaledMetric var length: CGFloat = 40
var maxLength: CGFloat?
@ScaledMetric var networkSymbolLength: CGFloat = 15
var maxNetworkSymbolLength: CGFloat?

var body: some View {
AssetIcon(token: token, network: network)
.frame(width: min(length, maxLength ?? length), height: min(length, maxLength ?? length))
.overlay(tokenNetworkLogo, alignment: .bottomTrailing)
.accessibilityHidden(true)
}

@ViewBuilder private var tokenNetworkLogo: some View {
if let network,
shouldShowNetworkIcon, // explicitly show/not show network logo
(!network.isNativeAsset(token) || network.nativeTokenLogoName != network.networkLogoName), // non-native asset OR if the network is not the official Ethereum network, but uses ETH as gas
let image = network.networkLogoImage {
Image(uiImage: image)
Expand Down
31 changes: 31 additions & 0 deletions Sources/BraveWallet/Crypto/MultipleAssetIconsView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Copyright 2024 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import SwiftUI
import BraveCore

struct MultipleAssetIconsView: View {

let tokens: [BraveWallet.BlockchainToken]
let maxBlockies = 3
@ScaledMetric var iconSize = 24
var maxIconSize: CGFloat = 32
@ScaledMetric var blockieDotSize = 2.0

var body: some View {
MultipleCircleIconView(
models: tokens,
shape: .circle,
iconSize: iconSize,
maxIconSize: maxIconSize,
iconDotSize: blockieDotSize
) { token in
AssetIcon(
token: token,
network: nil // not shown
)
}
}
}
2 changes: 1 addition & 1 deletion Sources/BraveWallet/Crypto/MultipleNetworkIconsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ struct MultipleNetworkIconsView: View {
maxIconSize: maxIconSize,
iconDotSize: iconDotSize,
iconView: { network in
NetworkIcon(network: network, length: iconSize)
NetworkIcon(network: network)
}
)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/BraveWallet/Crypto/NetworkSelectionRootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ private struct NetworkRowView: View {

var body: some View {
HStack {
NetworkIcon(network: network)
NetworkIconView(network: network)
VStack(alignment: .leading, spacing: 0) {
Text(network.chainName)
.font(.body)
Expand Down
2 changes: 1 addition & 1 deletion Sources/BraveWallet/Crypto/Portfolio/PortfolioView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ struct PortfolioAssetGroupHeaderView: View {
VStack(spacing: 0) {
HStack {
if case let .network(networkInfo) = group.groupType {
NetworkIcon(network: networkInfo, length: 32)
NetworkIconView(network: networkInfo, length: 32)
} else if case let .account(accountInfo) = group.groupType {
Blockie(address: accountInfo.address)
.frame(width: 32, height: 32)
Expand Down
5 changes: 3 additions & 2 deletions Sources/BraveWallet/Extensions/BraveWalletExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,9 @@ extension BraveWallet.BlockchainToken {
}

/// Returns the local image asset for the `BlockchainToken`.
func localImage(network: BraveWallet.NetworkInfo) -> UIImage? {
if network.isNativeAsset(self), let uiImage = network.nativeTokenLogoImage {
func localImage(network: BraveWallet.NetworkInfo?) -> UIImage? {
if let network,
network.isNativeAsset(self), let uiImage = network.nativeTokenLogoImage {
return uiImage
}

Expand Down
10 changes: 8 additions & 2 deletions Sources/BraveWallet/MultipleCircleIconView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,15 @@ struct MultipleCircleIconView<IconView: View, Model>: View {
HStack(spacing: -(min(iconSize, maxIconSize) / 2)) {
let numberOfIcons = min(maxIcons, models.count)
ForEach(0..<numberOfIcons, id: \.self) { index in
iconView(models[index])
Color(.secondaryBraveGroupedBackground)
.frame(width: min(iconSize, maxIconSize), height: min(iconSize, maxIconSize))
.clipShape(ContainerRelativeShape())
.overlay(ContainerRelativeShape().stroke(Color(.secondaryBraveGroupedBackground), lineWidth: 1))
.overlay {
iconView(models[index])
// frame also applied on `iconView` externally
.frame(width: min(iconSize, maxIconSize) - 2, height: min(iconSize, maxIconSize) - 2)
.clipShape(ContainerRelativeShape())
}
.containerShape(ContainerShape(shape: shape))
.zIndex(Double(numberOfIcons - index))
}
Expand All @@ -69,6 +74,7 @@ struct MultipleCircleIconView<IconView: View, Model>: View {
.frame(width: iconDotSize, height: iconDotSize)
}
.foregroundColor(.white)
.containerShape(ContainerShape(shape: shape))
)
}
}
Expand Down
26 changes: 21 additions & 5 deletions Sources/BraveWallet/NetworkIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import BraveUI

struct NetworkIcon: View {

var network: BraveWallet.NetworkInfo

@ScaledMetric var length: CGFloat = 30
let network: BraveWallet.NetworkInfo

var body: some View {
Group {
Expand All @@ -36,14 +34,17 @@ struct NetworkIcon: View {
}
}
.aspectRatio(1, contentMode: .fit)
.frame(width: length, height: length)
}

@State private var monogramSize: CGSize = .zero
private var networkIconMonogram: some View {
Blockie(address: network.chainName, shape: .circle)
.readSize(onChange: { newSize in
monogramSize = newSize
})
.overlay(
Text(network.chainName.first?.uppercased() ?? "")
.font(.system(size: length / 2, weight: .bold, design: .rounded))
.font(.system(size: max(monogramSize.width, monogramSize.height) / 2, weight: .bold, design: .rounded))
.foregroundColor(.white)
.shadow(color: .black.opacity(0.3), radius: 2, x: 0, y: 1)
)
Expand All @@ -58,3 +59,18 @@ struct NetworkIcon: View {
return nil
}
}

struct NetworkIconView: View {

let network: BraveWallet.NetworkInfo
@ScaledMetric var length: CGFloat = 30
var maxLength: CGFloat?

var body: some View {
NetworkIcon(network: network)
.frame(
width: min(length, maxLength ?? length),
height: min(length, maxLength ?? length)
)
}
}

0 comments on commit 0b43005

Please sign in to comment.