diff --git a/Bitkit/Components/Activity/ActivityBanner.swift b/Bitkit/Components/Activity/ActivityBanner.swift new file mode 100644 index 00000000..e97eec15 --- /dev/null +++ b/Bitkit/Components/Activity/ActivityBanner.swift @@ -0,0 +1,82 @@ +import BitkitCore +import SwiftUI + +enum ActivityBannerType { + case spending + case savings +} + +struct ActivityBanner: View { + let type: ActivityBannerType + + @State private var innerShadowOpacity: Double = 0.32 + @State private var dropShadowOpacity: Double = 1.0 + @State private var radialGradientOpacity: Double = 0.4 + @State private var borderOpacity: Double = 0.32 + + private var accentColor: Color { + type == .spending ? .purpleAccent : .brandAccent + } + + var body: some View { + HStack(spacing: 8) { + Image("transfer") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .foregroundColor(accentColor) + + Text(tTodo("TRANSFER IN PROGRESS")) + .font(Fonts.black(size: 20)) + .foregroundColor(.textPrimary) + .kerning(0) + .lineLimit(1) + } + .frame(maxWidth: .infinity, alignment: .center) + .frame(height: 72) + .padding(.horizontal, 16) + .background( + ZStack { + // Inner shadow + RoundedRectangle(cornerRadius: 16) + .fill(.shadow(.inner(color: accentColor.opacity(innerShadowOpacity), radius: 40))) + .foregroundColor(.black) + + // Linear gradient background + RoundedRectangle(cornerRadius: 16) + .fill( + LinearGradient( + gradient: Gradient(colors: [accentColor.opacity(0.24), accentColor.opacity(0)]), + startPoint: .top, + endPoint: .bottom + ) + ) + + // Radial gradient in top left corner + RadialGradient( + gradient: Gradient(stops: [ + .init(color: accentColor.opacity(radialGradientOpacity), location: 0.0), + .init(color: accentColor.opacity(0.0), location: 1.0), + ]), + center: UnitPoint(x: 0, y: 0), + startRadius: 0, + endRadius: 160 + ) + } + .clipShape(RoundedRectangle(cornerRadius: 16)) + ) + .overlay( + RoundedRectangle(cornerRadius: 16) + .stroke(accentColor.opacity(borderOpacity), lineWidth: 1) + ) + .shadow(color: accentColor.opacity(dropShadowOpacity), radius: 12) + .task { + withAnimation(.easeInOut(duration: 1.2).repeatForever(autoreverses: true)) { + innerShadowOpacity = 0.64 + dropShadowOpacity = 0.0 + radialGradientOpacity = 0.0 + borderOpacity = 1.0 + } + } + } +} diff --git a/Bitkit/Components/WalletBalanceView.swift b/Bitkit/Components/WalletBalanceView.swift index 8ec14268..ff90655c 100644 --- a/Bitkit/Components/WalletBalanceView.swift +++ b/Bitkit/Components/WalletBalanceView.swift @@ -3,7 +3,6 @@ import SwiftUI struct WalletBalanceView: View { let type: WalletType let sats: UInt64 - var showTransferIcon: Bool = false @EnvironmentObject var currency: CurrencyViewModel @@ -21,13 +20,6 @@ struct WalletBalanceView: View { .padding(.trailing, 4) SubtitleText(btcComponents.value) - - if showTransferIcon { - Image("transfer") - .resizable() - .frame(width: 16, height: 16) - .foregroundColor(.white64) - } } } else { HStack(spacing: 4) { @@ -38,13 +30,6 @@ struct WalletBalanceView: View { SubtitleText(converted.symbol) .frame(maxWidth: 12) SubtitleText(converted.formatted) - - if showTransferIcon { - Image("transfer") - .resizable() - .frame(width: 16, height: 16) - .foregroundColor(.white64) - } } } } @@ -82,20 +67,12 @@ struct WalletBalanceView: View { // Bitcoin display (modern) - with transfer icon HStack { - WalletBalanceView( - type: .onchain, - sats: 123_456, - showTransferIcon: true - ) + WalletBalanceView(type: .onchain, sats: 123_456) Divider() .frame(height: 50) - WalletBalanceView( - type: .lightning, - sats: 123_456, - showTransferIcon: true - ) + WalletBalanceView(type: .lightning, sats: 123_456) } .environmentObject( { @@ -110,18 +87,12 @@ struct WalletBalanceView: View { // USD display HStack { - WalletBalanceView( - type: .onchain, - sats: 123_456 - ) + WalletBalanceView(type: .onchain, sats: 123_456) Divider() .frame(height: 50) - WalletBalanceView( - type: .lightning, - sats: 123_456 - ) + WalletBalanceView(type: .lightning, sats: 123_456) } .environmentObject( { @@ -137,18 +108,12 @@ struct WalletBalanceView: View { // EUR display HStack { - WalletBalanceView( - type: .onchain, - sats: 123_456 - ) + WalletBalanceView(type: .onchain, sats: 123_456) Divider() .frame(height: 50) - WalletBalanceView( - type: .lightning, - sats: 123_456 - ) + WalletBalanceView(type: .lightning, sats: 123_456) } .environmentObject( { @@ -164,18 +129,12 @@ struct WalletBalanceView: View { // Bitcoin display with classic unit HStack { - WalletBalanceView( - type: .onchain, - sats: 123_456 - ) + WalletBalanceView(type: .onchain, sats: 123_456) Divider() .frame(height: 50) - WalletBalanceView( - type: .lightning, - sats: 123_456 - ) + WalletBalanceView(type: .lightning, sats: 123_456) } .environmentObject( { diff --git a/Bitkit/Views/Wallets/Activity/ActivityLatest.swift b/Bitkit/Views/Wallets/Activity/ActivityLatest.swift index 2aab4f22..aad4ead9 100644 --- a/Bitkit/Views/Wallets/Activity/ActivityLatest.swift +++ b/Bitkit/Views/Wallets/Activity/ActivityLatest.swift @@ -4,6 +4,19 @@ struct ActivityLatest: View { @EnvironmentObject private var activity: ActivityListViewModel @EnvironmentObject private var navigation: NavigationViewModel @EnvironmentObject private var sheets: SheetViewModel + @EnvironmentObject private var wallet: WalletViewModel + + private var shouldShowBanner: Bool { + wallet.balanceInTransferToSavings > 0 || wallet.balanceInTransferToSpending > 0 + } + + private var bannerType: ActivityBannerType { + if wallet.balanceInTransferToSpending > 0 { + return .spending + } else { + return .savings + } + } var body: some View { VStack(spacing: 0) { @@ -11,6 +24,12 @@ struct ActivityLatest: View { .frame(maxWidth: .infinity, alignment: .leading) .padding(.bottom, 16) + if shouldShowBanner { + ActivityBanner(type: bannerType) + .padding(.bottom, 16) + .transition(.opacity) + } + if let items = activity.latestActivities { LazyVStack(alignment: .leading, spacing: 16) { ForEach(Array(zip(items.indices, items)), id: \.1) { index, item in @@ -40,5 +59,6 @@ struct ActivityLatest: View { EmptyView() } } + .animation(.spring(response: 0.4, dampingFraction: 0.8), value: shouldShowBanner) } } diff --git a/Bitkit/Views/Wallets/HomeView.swift b/Bitkit/Views/Wallets/HomeView.swift index 6c69fb11..264c5555 100644 --- a/Bitkit/Views/Wallets/HomeView.swift +++ b/Bitkit/Views/Wallets/HomeView.swift @@ -26,11 +26,7 @@ struct HomeView: View { VStack(spacing: 0) { HStack(spacing: 0) { NavigationLink(value: Route.savingsWallet) { - WalletBalanceView( - type: .onchain, - sats: UInt64(wallet.totalOnchainSats), - showTransferIcon: wallet.balanceInTransferToSavings > 0 - ) + WalletBalanceView(type: .onchain, sats: UInt64(wallet.totalOnchainSats)) } Divider() @@ -40,11 +36,7 @@ struct HomeView: View { .padding(.leading, 16) NavigationLink(value: Route.spendingWallet) { - WalletBalanceView( - type: .lightning, - sats: UInt64(wallet.totalLightningSats), - showTransferIcon: wallet.balanceInTransferToSpending > 0 - ) + WalletBalanceView(type: .lightning, sats: UInt64(wallet.totalLightningSats)) } } .frame(maxWidth: .infinity, alignment: .leading)