diff --git a/BDKSwiftExampleWallet.xcodeproj/project.pbxproj b/BDKSwiftExampleWallet.xcodeproj/project.pbxproj index eda6edb2..ef41cd63 100644 --- a/BDKSwiftExampleWallet.xcodeproj/project.pbxproj +++ b/BDKSwiftExampleWallet.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 774586B52DB7B2BC00A631E1 /* BalanceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774586B42DB7B2BC00A631E1 /* BalanceView.swift */; }; 779E70872DB9C98A006E22D3 /* WalletSyncScriptInspector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779E70862DB9C98A006E22D3 /* WalletSyncScriptInspector.swift */; }; 779E70892DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779E70882DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift */; }; + 77AD9F062DBB031D00182E65 /* ActivityHomeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77AD9F052DBB031D00182E65 /* ActivityHomeHeaderView.swift */; }; 77F0FDC92DA9A93D00B30E4F /* Connection+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77F0FDC82DA9A93700B30E4F /* Connection+Extensions.swift */; }; A733D6D02A81113000F333B4 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = A733D6CF2A81113000F333B4 /* Localizable.xcstrings */; }; A73F7A362A3B778E00B87FC6 /* Int+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A73F7A352A3B778E00B87FC6 /* Int+Extensions.swift */; }; @@ -114,6 +115,7 @@ 774586B42DB7B2BC00A631E1 /* BalanceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceView.swift; sourceTree = ""; }; 779E70862DB9C98A006E22D3 /* WalletSyncScriptInspector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletSyncScriptInspector.swift; sourceTree = ""; }; 779E70882DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletFullScanScriptInspector.swift; sourceTree = ""; }; + 77AD9F052DBB031D00182E65 /* ActivityHomeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityHomeHeaderView.swift; sourceTree = ""; }; 77F0FDC82DA9A93700B30E4F /* Connection+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Connection+Extensions.swift"; sourceTree = ""; }; A733D6CF2A81113000F333B4 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = ""; }; A73F7A352A3B778E00B87FC6 /* Int+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Int+Extensions.swift"; sourceTree = ""; }; @@ -235,6 +237,15 @@ path = Actor; sourceTree = ""; }; + 77AD9F072DBB0DBE00182E65 /* Home */ = { + isa = PBXGroup; + children = ( + 774586B42DB7B2BC00A631E1 /* BalanceView.swift */, + 77AD9F052DBB031D00182E65 /* ActivityHomeHeaderView.swift */, + ); + path = Home; + sourceTree = ""; + }; A7FBCE392A72944C007C960E /* Resources */ = { isa = PBXGroup; children = ( @@ -283,7 +294,7 @@ AE2381B92C61255100F6B00C /* Receive */, AE2381B82C61254B00F6B00C /* Send */, AE2381B72C61254200F6B00C /* Settings */, - 774586B42DB7B2BC00A631E1 /* BalanceView.swift */, + 77AD9F072DBB0DBE00182E65 /* Home */, ); path = View; sourceTree = ""; @@ -733,6 +744,7 @@ AED4CC0C2A1D3A9400CE1831 /* OnboardingView.swift in Sources */, 77F0FDC92DA9A93D00B30E4F /* Connection+Extensions.swift in Sources */, AE6716012A9AC089005C193F /* KeyServiceError.swift in Sources */, + 77AD9F062DBB031D00182E65 /* ActivityHomeHeaderView.swift in Sources */, AE0C30FB2A804B95008F1EAE /* WalletViewModel.swift in Sources */, AE49847C2A1BBBD6009951E2 /* BDKSwiftExampleWalletApp.swift in Sources */, AE6715FF2A9AC066005C193F /* FeeServiceError.swift in Sources */, diff --git a/BDKSwiftExampleWallet/View Model/WalletViewModel.swift b/BDKSwiftExampleWallet/View Model/WalletViewModel.swift index 724713b9..d0e3a42d 100644 --- a/BDKSwiftExampleWallet/View Model/WalletViewModel.swift +++ b/BDKSwiftExampleWallet/View Model/WalletViewModel.swift @@ -39,6 +39,9 @@ class WalletViewModel { var transactions: [CanonicalTx] var walletSyncState: WalletSyncState var walletViewError: AppError? + var needsFullScan: Bool { + bdkClient.needsFullScan() + } private var updateProgress: @Sendable (UInt64, UInt64) -> Void { { [weak self] inspected, total in diff --git a/BDKSwiftExampleWallet/View/Home/ActivityHomeHeaderView.swift b/BDKSwiftExampleWallet/View/Home/ActivityHomeHeaderView.swift new file mode 100644 index 00000000..2309f52b --- /dev/null +++ b/BDKSwiftExampleWallet/View/Home/ActivityHomeHeaderView.swift @@ -0,0 +1,128 @@ +// +// TransactionListHeaderView.swift +// BDKSwiftExampleWallet +// +// Created by Rubens Machion on 24/04/25. +// + +import SwiftUI + +struct ActivityHomeHeaderView: View { + + let walletSyncState: WalletSyncState + let progress: Float + let inspectedScripts: UInt64 + let totalScripts: UInt64 + let needsFullScan: Bool + + let showAllTransactions: () -> Void + + var body: some View { + HStack { + Text("Activity") + Spacer() + + HStack { + if needsFullScan { + Text("\(inspectedScripts)") + .padding(.trailing, -5.0) + .fontWeight(.semibold) + .contentTransition(.numericText()) + .transition(.opacity) + .fontDesign(.monospaced) + .foregroundStyle(.secondary) + .font(.caption2) + .fontWeight(.thin) + .animation(.easeInOut, value: inspectedScripts) + } else if walletSyncState == .syncing { + HStack { + if progress < 1.0 { + Text("\(inspectedScripts)") + .padding(.trailing, -5.0) + .fontWeight(.semibold) + .contentTransition(.numericText()) + .transition(.opacity) + + Text("/") + .padding(.trailing, -5.0) + .transition(.opacity) + Text("\(totalScripts)") + .contentTransition(.numericText()) + .transition(.opacity) + } + + Text( + String( + format: "%.0f%%", + progress * 100 + ) + ) + .contentTransition(.numericText()) + .transition(.opacity) + } + .fontDesign(.monospaced) + .foregroundStyle(.secondary) + .font(.caption2) + .fontWeight(.thin) + .animation(.easeInOut, value: inspectedScripts) + .animation(.easeInOut, value: totalScripts) + .animation(.easeInOut, value: progress) + } + } + HStack { + HStack(spacing: 5) { + self.syncImageIndicator() + } + .contentTransition(.symbolEffect(.replace.offUp)) + + } + .foregroundStyle(.secondary) + .font(.caption) + + if walletSyncState == .synced { + Button { + self.showAllTransactions() + } label: { + HStack(spacing: 2) { + Text("Show All") + Image(systemName: "arrow.right") + } + .font(.caption) + .foregroundStyle(.secondary) + .fontWeight(.regular) + } + } + } + .fontWeight(.bold) + } + + @ViewBuilder + private func syncImageIndicator() -> some View { + switch walletSyncState { + case .synced: + AnyView( + Image(systemName: "checkmark.circle.fill") + .foregroundStyle(.green) + ) + + case .syncing: + AnyView( + Image(systemName: "slowmo") + .symbolEffect( + .variableColor.cumulative + ) + ) + + case .notStarted: + AnyView( + Image(systemName: "arrow.clockwise") + ) + default: + AnyView( + Image( + systemName: "person.crop.circle.badge.exclamationmark" + ) + ) + } + } +} diff --git a/BDKSwiftExampleWallet/View/BalanceView.swift b/BDKSwiftExampleWallet/View/Home/BalanceView.swift similarity index 100% rename from BDKSwiftExampleWallet/View/BalanceView.swift rename to BDKSwiftExampleWallet/View/Home/BalanceView.swift diff --git a/BDKSwiftExampleWallet/View/WalletView.swift b/BDKSwiftExampleWallet/View/WalletView.swift index fb184829..c6e59eff 100644 --- a/BDKSwiftExampleWallet/View/WalletView.swift +++ b/BDKSwiftExampleWallet/View/WalletView.swift @@ -42,90 +42,16 @@ struct WalletView: View { } VStack { - HStack { - Text("Activity") - Spacer() - if viewModel.walletSyncState == .syncing { - HStack { - if viewModel.progress < 1.0 { - Text("\(viewModel.inspectedScripts)") - .padding(.trailing, -5.0) - .fontWeight(.semibold) - .contentTransition(.numericText()) - .transition(.opacity) - - if !viewModel.bdkClient.needsFullScan() { - Text("/") - .padding(.trailing, -5.0) - .transition(.opacity) - Text("\(viewModel.totalScripts)") - .contentTransition(.numericText()) - .transition(.opacity) - } - } - - if !viewModel.bdkClient.needsFullScan() { - Text( - String( - format: "%.0f%%", - viewModel.progress * 100 - ) - ) - .contentTransition(.numericText()) - .transition(.opacity) - } - } - .fontDesign(.monospaced) - .foregroundStyle(.secondary) - .font(.caption2) - .fontWeight(.thin) - .animation(.easeInOut, value: viewModel.inspectedScripts) - .animation(.easeInOut, value: viewModel.totalScripts) - .animation(.easeInOut, value: viewModel.progress) - } - HStack { - HStack(spacing: 5) { - if viewModel.walletSyncState == .syncing { - Image(systemName: "slowmo") - .symbolEffect( - .variableColor.cumulative - ) - } else if viewModel.walletSyncState == .synced { - Image(systemName: "checkmark.circle.fill") - .foregroundStyle( - viewModel.walletSyncState == .synced - ? .green : .secondary - ) - } else if viewModel.walletSyncState == .notStarted { - Image(systemName: "arrow.clockwise") - } else { - Image( - systemName: "person.crop.circle.badge.exclamationmark" - ) - } - } - .contentTransition(.symbolEffect(.replace.offUp)) - - } - .foregroundStyle(.secondary) - .font(.caption) - - if viewModel.walletSyncState == .synced { - Button { - showAllTransactions = true - } label: { - HStack(spacing: 2) { - Text("Show All") - Image(systemName: "arrow.right") - } - .font(.caption) - .foregroundStyle(.secondary) - .fontWeight(.regular) - } - } - + ActivityHomeHeaderView( + walletSyncState: viewModel.walletSyncState, + progress: viewModel.progress, + inspectedScripts: viewModel.inspectedScripts, + totalScripts: viewModel.totalScripts, + needsFullScan: viewModel.needsFullScan + ) { + showAllTransactions = true } - .fontWeight(.bold) + TransactionListView( viewModel: .init(), transactions: viewModel.recentTransactions,