// // WalletBalancesView.swift // Zashi // // Created by Lukáš Korba on 04-02-2024 // import SwiftUI import ComposableArchitecture import Generated import UIComponents public struct WalletBalancesView: View { @Environment(\.colorScheme) private var colorScheme @Perception.Bindable var store: StoreOf let tokenName: String let couldBeHidden: Bool let shortened: Bool public init( store: StoreOf, tokenName: String, couldBeHidden: Bool = false, shortened: Bool = false ) { self.store = store self.tokenName = tokenName self.couldBeHidden = couldBeHidden self.shortened = shortened } public var body: some View { WithPerceptionTracking { VStack(spacing: 0) { balanceContent() .padding(.top, 40) .anchorPreference( key: ExchangeRateFeaturePreferenceKey.self, value: .bounds ) { $0 } #if !SECANT_DISTRIB .accessDebugMenuWithHiddenGesture { store.send(.debugMenuStartup) } #endif if shortened { exchangeRate() } if store.migratingDatabase { Text(L10n.Home.migratingDatabases) .font(.custom(FontFamily.Inter.regular.name, size: 14)) .foregroundColor(Asset.Colors.primary.color) .padding(.top, 12) .padding(.bottom, 30) } else if store.spendability != .everything && !shortened { Button { store.send(.availableBalanceTapped) } label: { AvailableBalanceView( balance: store.shieldedBalance, showIndicator: store.isProcessingZeroAvailableBalance ) .padding(.top, 12) .padding(.bottom, 30) } } else if !shortened { Color.clear .padding(.bottom, 30) } } .foregroundColor(Asset.Colors.primary.color) .onAppear { store.send(.onAppear) } .onDisappear { store.send(.onDisappear) } } } @ViewBuilder private func balanceContent() -> some View { HStack(spacing: 0) { ZcashSymbol() .frame(width: 32, height: 32) .zForegroundColor(Design.Text.primary) if shortened { ZatoshiText(store.totalBalance, .abbreviated) .zFont(.semiBold, size: 48, style: Design.Text.primary) } else { ZatoshiRepresentationView( balance: store.totalBalance, fontName: FontFamily.Inter.semiBold.name, mostSignificantFontSize: 48, leastSignificantFontSize: 20, format: .expanded ) } } } private func exchangeRate() -> some View { Group { if store.isExchangeRateFeatureOn { if store.currencyConversion == nil && !store.isExchangeRateStale { HStack(spacing: 8) { Text(L10n.General.loading) .font(.custom(FontFamily.Inter.semiBold.name, size: 14)) .foregroundColor(Asset.Colors.primary.color) ProgressView() } .frame(height: 36) .padding(.top, 10) .padding(.vertical, 5) } if store.currencyConversion != nil || store.isExchangeRateStale { Button { store.send(.exchangeRateRefreshTapped) } label: { if store.isExchangeRateStale { HStack { Text(L10n.Tooltip.ExchangeRate.title) .font(.custom(FontFamily.Inter.semiBold.name, size: 14)) .foregroundColor(Asset.Colors.primary.color) Asset.Assets.infoCircle.image .zImage(size: 20, color: Asset.Colors.primary.color) } .frame(maxWidth: .infinity) .anchorPreference( key: ExchangeRateStaleTooltipPreferenceKey.self, value: .bounds ) { $0 } } else if store.isExchangeRateRefreshEnabled { HStack { Text(store.currencyValue) .hiddenIfSet() .font(.custom(FontFamily.Inter.semiBold.name, size: 14)) .foregroundColor(Asset.Colors.primary.color) if store.isExchangeRateUSDInFlight { ProgressView() .scaleEffect(0.7) .frame(width: 20, height: 20) } else { Asset.Assets.refreshCCW.image .zImage(size: 20, color: Asset.Colors.primary.color) } } .padding(8) .padding(.horizontal, 6) .background { RoundedRectangle(cornerRadius: Design.Radius._lg) .stroke(Design.Surfaces.strokePrimary.color(colorScheme)) .background { Design.Surfaces.bgSecondary.color(colorScheme) .cornerRadius(10) } } } else { HStack { Text(store.currencyValue) .hiddenIfSet() .font(.custom(FontFamily.Inter.semiBold.name, size: 14)) .foregroundColor(Asset.Colors.primary.color) if store.isExchangeRateUSDInFlight { ProgressView() .scaleEffect(0.7) .frame(width: 11, height: 14) } else { Asset.Assets.refreshCCW.image .zImage(size: 20, color: Asset.Colors.shade72.color) } } .padding(8) .padding(.horizontal, 6) } } .frame(height: 36) .padding(.top, 10) .padding(.vertical, 5) } } } } } // MARK: - Previews #Preview { WalletBalancesView(store: WalletBalances.initial, tokenName: "ZEC") } // MARK: - Store extension WalletBalances { public static var initial = StoreOf( initialState: .initial ) { WalletBalances() } } // MARK: - Placeholders extension WalletBalances.State { public static let initial = WalletBalances.State( shieldedBalance: .zero ) }