Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion BDKSwiftExampleWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -114,6 +115,7 @@
774586B42DB7B2BC00A631E1 /* BalanceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceView.swift; sourceTree = "<group>"; };
779E70862DB9C98A006E22D3 /* WalletSyncScriptInspector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletSyncScriptInspector.swift; sourceTree = "<group>"; };
779E70882DB9C9AB006E22D3 /* WalletFullScanScriptInspector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletFullScanScriptInspector.swift; sourceTree = "<group>"; };
77AD9F052DBB031D00182E65 /* ActivityHomeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityHomeHeaderView.swift; sourceTree = "<group>"; };
77F0FDC82DA9A93700B30E4F /* Connection+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Connection+Extensions.swift"; sourceTree = "<group>"; };
A733D6CF2A81113000F333B4 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
A73F7A352A3B778E00B87FC6 /* Int+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Int+Extensions.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -235,6 +237,15 @@
path = Actor;
sourceTree = "<group>";
};
77AD9F072DBB0DBE00182E65 /* Home */ = {
isa = PBXGroup;
children = (
774586B42DB7B2BC00A631E1 /* BalanceView.swift */,
77AD9F052DBB031D00182E65 /* ActivityHomeHeaderView.swift */,
);
path = Home;
sourceTree = "<group>";
};
A7FBCE392A72944C007C960E /* Resources */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -283,7 +294,7 @@
AE2381B92C61255100F6B00C /* Receive */,
AE2381B82C61254B00F6B00C /* Send */,
AE2381B72C61254200F6B00C /* Settings */,
774586B42DB7B2BC00A631E1 /* BalanceView.swift */,
77AD9F072DBB0DBE00182E65 /* Home */,
);
path = View;
sourceTree = "<group>";
Expand Down Expand Up @@ -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 */,
Expand Down
3 changes: 3 additions & 0 deletions BDKSwiftExampleWallet/View Model/WalletViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
128 changes: 128 additions & 0 deletions BDKSwiftExampleWallet/View/Home/ActivityHomeHeaderView.swift
Original file line number Diff line number Diff line change
@@ -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"
)
)
}
}
}
92 changes: 9 additions & 83 deletions BDKSwiftExampleWallet/View/WalletView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down