diff --git a/BDKSwiftExampleWallet/View/Activity/ActivityListView.swift b/BDKSwiftExampleWallet/View/Activity/ActivityListView.swift index fdab7af4..3eb894ab 100644 --- a/BDKSwiftExampleWallet/View/Activity/ActivityListView.swift +++ b/BDKSwiftExampleWallet/View/Activity/ActivityListView.swift @@ -10,7 +10,7 @@ import SwiftUI struct ActivityListView: View { @AppStorage("balanceDisplayFormat") private var balanceFormat: BalanceDisplayFormat = - .bitcoinSats + .bip177 @Bindable var viewModel: ActivityListViewModel var body: some View { diff --git a/BDKSwiftExampleWallet/View/Activity/LocalOutputItemView.swift b/BDKSwiftExampleWallet/View/Activity/LocalOutputItemView.swift index e24afacb..374c83b3 100644 --- a/BDKSwiftExampleWallet/View/Activity/LocalOutputItemView.swift +++ b/BDKSwiftExampleWallet/View/Activity/LocalOutputItemView.swift @@ -10,7 +10,7 @@ import SwiftUI struct LocalOutputItemView: View { @AppStorage("balanceDisplayFormat") private var balanceFormat: BalanceDisplayFormat = - .bitcoinSats + .bip177 @Environment(\.dynamicTypeSize) var dynamicTypeSize let isRedacted: Bool let output: LocalOutput diff --git a/BDKSwiftExampleWallet/View/Activity/TransactionDetailView.swift b/BDKSwiftExampleWallet/View/Activity/TransactionDetailView.swift index b9d1e583..3d957c76 100644 --- a/BDKSwiftExampleWallet/View/Activity/TransactionDetailView.swift +++ b/BDKSwiftExampleWallet/View/Activity/TransactionDetailView.swift @@ -11,7 +11,7 @@ import SwiftUI struct TransactionDetailView: View { @AppStorage("balanceDisplayFormat") private var balanceFormat: BalanceDisplayFormat = - .bitcoinSats + .bip177 @Bindable var viewModel: TransactionDetailViewModel @State private var isCopied = false @State private var showCheckmark = false diff --git a/BDKSwiftExampleWallet/View/Activity/TransactionItemView.swift b/BDKSwiftExampleWallet/View/Activity/TransactionItemView.swift index b843fa93..0526464b 100644 --- a/BDKSwiftExampleWallet/View/Activity/TransactionItemView.swift +++ b/BDKSwiftExampleWallet/View/Activity/TransactionItemView.swift @@ -30,7 +30,7 @@ struct TransactionItemView: View { var body: some View { - VStack(alignment: .leading, spacing: 20) { + VStack(alignment: .leading, spacing: 6) { let delta = txDetails.balanceDelta let prefix = (delta >= 0 ? "+ " : "- ").appending("\(format.displayPrefix) ") @@ -38,41 +38,41 @@ struct TransactionItemView: View { let suffix = format.displayText Text("\(prefix)\(amount) \(suffix)") - .font(.title) + .font(.title3) .fontWeight(.semibold) .fontDesign(.rounded) .lineLimit(1) .redacted(reason: isRedacted ? .placeholder : []) HStack { - if isRedacted { - Image( - systemName: - "circle.fill" - ) - .symbolRenderingMode(.palette) - .foregroundStyle( - Color.gray.opacity(0.5) - ) - } else { - ZStack { - Image( - systemName: - txDetails.balanceDelta >= 0 - ? "arrow.down" : "arrow.up" - ) - .foregroundStyle( - { - switch txDetails.chainPosition { - case .confirmed(_, _): - Color.bitcoinOrange - case .unconfirmed(_): - Color.gray.opacity(0.5) - } - }() - ) - } - } + // if isRedacted { + // Image( + // systemName: + // "circle.fill" + // ) + // .symbolRenderingMode(.palette) + // .foregroundStyle( + // Color.gray.opacity(0.5) + // ) + // } else { + // ZStack { + // Image( + // systemName: + // txDetails.balanceDelta >= 0 + // ? "arrow.down" : "arrow.up" + // ) + // .foregroundStyle( + // { + // switch txDetails.chainPosition { + // case .confirmed(_, _): + // Color.bitcoinOrange + // case .unconfirmed(_): + // Color.gray.opacity(0.5) + // } + // }() + // ) + // } + // } switch txDetails.chainPosition { case .confirmed(let confirmationBlockTime, _): @@ -103,18 +103,18 @@ struct TransactionItemView: View { } .foregroundStyle(.secondary) - .font(.callout) + .font(.caption) - HStack { - Text(txDetails.txid.description) - .truncationMode(.middle) - .lineLimit(1) - .fontDesign(.monospaced) - .font(.callout) - .foregroundStyle(.primary) - Spacer(minLength: 80) - } - .redacted(reason: isRedacted ? .placeholder : []) + // HStack { + // Text(txDetails.txid.description) + // .truncationMode(.middle) + // .lineLimit(1) + // .fontDesign(.monospaced) + // .font(.callout) + // .foregroundStyle(.primary) + // Spacer(minLength: 80) + // } + // .redacted(reason: isRedacted ? .placeholder : []) } .padding(.vertical) diff --git a/BDKSwiftExampleWallet/View/Activity/TransactionListView.swift b/BDKSwiftExampleWallet/View/Activity/TransactionListView.swift index b16c79b4..5eaa9830 100644 --- a/BDKSwiftExampleWallet/View/Activity/TransactionListView.swift +++ b/BDKSwiftExampleWallet/View/Activity/TransactionListView.swift @@ -32,7 +32,7 @@ struct TransactionListView: View { var body: some View { - List { + LazyVStack(alignment: .leading) { if transactions.isEmpty && walletSyncState == .syncing { TransactionItemView( txDetails: .mock, @@ -40,8 +40,6 @@ struct TransactionListView: View { format: format, fiatPrice: fiatPrice ) - .listRowInsets(EdgeInsets()) - .listRowSeparator(.hidden) } else if transactions.isEmpty { VStack(alignment: .leading) { @@ -94,8 +92,6 @@ struct TransactionListView: View { } } - .listRowInsets(EdgeInsets()) - .listRowSeparator(.hidden) } else { @@ -122,6 +118,14 @@ struct TransactionListView: View { format: format, fiatPrice: fiatPrice ) + .frame(maxWidth: .infinity, alignment: .leading) + .overlay(alignment: .trailing) { + Image(systemName: "chevron.right") + .font(.footnote.weight(.semibold)) + .foregroundStyle(.tertiary) + .padding(.leading, 8) + } + .padding(.trailing, 4) } } else { @@ -134,14 +138,11 @@ struct TransactionListView: View { } } - .listRowInsets(EdgeInsets()) - .listRowSeparator(.hidden) - .listRowBackground(Color.clear) } } - .listStyle(.plain) + .frame(maxWidth: .infinity, alignment: .leading) .alert(isPresented: $viewModel.showingWalletTransactionsViewErrorAlert) { Alert( title: Text("Wallet Transaction Error"), diff --git a/BDKSwiftExampleWallet/View/WalletView.swift b/BDKSwiftExampleWallet/View/WalletView.swift index 2299e8f1..495f9cfe 100644 --- a/BDKSwiftExampleWallet/View/WalletView.swift +++ b/BDKSwiftExampleWallet/View/WalletView.swift @@ -10,7 +10,7 @@ import SwiftUI struct WalletView: View { @AppStorage("balanceDisplayFormat") private var balanceFormat: BalanceDisplayFormat = - .bitcoinSats + .bip177 @AppStorage("KyotoLastBlockHeight") private var kyotoLastHeight: Int = 0 @Bindable var viewModel: WalletViewModel @Binding var sendNavigationPath: NavigationPath @@ -27,64 +27,68 @@ struct WalletView: View { Color(uiColor: .systemBackground) .ignoresSafeArea() - VStack(spacing: 20) { + ScrollView { + VStack(spacing: 20) { - BalanceView( - format: balanceFormat, - balance: viewModel.balanceTotal, - fiatPrice: viewModel.price - ).onTapGesture { - withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) { - balanceFormat = - BalanceDisplayFormat.allCases[ - (balanceFormat.index + 1) % BalanceDisplayFormat.allCases.count - ] - } - } - - VStack { - ActivityHomeHeaderView( - walletSyncState: viewModel.walletSyncState, - progress: viewModel.progress, - inspectedScripts: viewModel.inspectedScripts, - totalScripts: viewModel.totalScripts, - needsFullScan: viewModel.needsFullScan, - isKyotoClient: viewModel.isKyotoClient, - isKyotoConnected: viewModel.isKyotoConnected, - currentBlockHeight: viewModel.currentBlockHeight - ) { - showAllTransactions = true + BalanceView( + format: balanceFormat, + balance: viewModel.balanceTotal, + fiatPrice: viewModel.price + ).onTapGesture { + withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) { + balanceFormat = + BalanceDisplayFormat.allCases[ + (balanceFormat.index + 1) + % BalanceDisplayFormat + .allCases.count + ] + } } - if shouldShowKyotoInitialSyncNotice { - KyotoInitialSyncNoticeView(isConnected: viewModel.isKyotoConnected) - .transition(.opacity) - } + VStack { + ActivityHomeHeaderView( + walletSyncState: viewModel.walletSyncState, + progress: viewModel.progress, + inspectedScripts: viewModel.inspectedScripts, + totalScripts: viewModel.totalScripts, + needsFullScan: viewModel.needsFullScan, + isKyotoClient: viewModel.isKyotoClient, + isKyotoConnected: viewModel.isKyotoConnected, + currentBlockHeight: viewModel.currentBlockHeight + ) { + showAllTransactions = true + } - TransactionListView( - viewModel: .init(), - transactions: viewModel.recentTransactions, - walletSyncState: viewModel.walletSyncState, - format: balanceFormat, - fiatPrice: viewModel.price - ) - .refreshable { - if viewModel.isKyotoClient { - viewModel.getBalance() - viewModel.getTransactions() - await viewModel.getPrices() - } else { - await viewModel.syncOrFullScan() - viewModel.getBalance() - viewModel.getTransactions() - await viewModel.getPrices() + if shouldShowKyotoInitialSyncNotice { + KyotoInitialSyncNoticeView(isConnected: viewModel.isKyotoConnected) + .transition(.opacity) } + + TransactionListView( + viewModel: .init(), + transactions: viewModel.recentTransactions, + walletSyncState: viewModel.walletSyncState, + format: balanceFormat, + fiatPrice: viewModel.price + ) + } } - + .padding() + } + .refreshable { + if viewModel.isKyotoClient { + viewModel.getBalance() + viewModel.getTransactions() + await viewModel.getPrices() + } else { + await viewModel.syncOrFullScan() + viewModel.getBalance() + viewModel.getTransactions() + await viewModel.getPrices() + } } - .padding() .onReceive( NotificationCenter.default.publisher(for: Notification.Name("TransactionSent")), perform: { _ in diff --git a/Docs/wallet.png b/Docs/wallet.png new file mode 100644 index 00000000..d15c0298 Binary files /dev/null and b/Docs/wallet.png differ diff --git a/Docs/walletview.png b/Docs/walletview.png deleted file mode 100644 index 718fc772..00000000 Binary files a/Docs/walletview.png and /dev/null differ diff --git a/README.md b/README.md index 37d4d550..388a31a9 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A native iOS app example using [Bitcoin Dev Kit](https://github.com/bitcoindevkit) via [language bindings](https://github.com/bitcoindevkit/bdk-ffi). -Screenshot +Screenshot Download the app on [TestFlight](https://testflight.apple.com/join/A3nAuYvZ).