Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.

Commit d1a90f0

Browse files
committed
Balance view
1 parent def53c9 commit d1a90f0

File tree

2 files changed

+103
-24
lines changed

2 files changed

+103
-24
lines changed

Shared/Components/Controls.swift

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,31 @@ struct AmountField: View {
5454
}
5555
}
5656

57+
struct Copyable<Label>: View where Label: View {
58+
let text: String
59+
var useSpacer: Bool
60+
let content: Label
61+
62+
public init(text: String, useSpacer: Bool = true, @ViewBuilder content: () -> Label) {
63+
self.text = text
64+
self.useSpacer = useSpacer
65+
self.content = content()
66+
}
67+
68+
var body: some View {
69+
Button(action: { My_Citadel.clipboardCopy(text: text) }) {
70+
HStack {
71+
content
72+
if useSpacer {
73+
Spacer()
74+
}
75+
Image(systemName: "doc.on.doc")
76+
}
77+
}
78+
.foregroundColor(.primary)
79+
}
80+
}
81+
5782
struct CopyableText: View {
5883
let text: String
5984
var copyable: Bool = false
@@ -62,18 +87,11 @@ struct CopyableText: View {
6287

6388
var body: some View {
6489
if copyable {
65-
Button(action: { My_Citadel.clipboardCopy(text: text) }) {
66-
HStack {
67-
Text(text)
68-
.font(.body)
69-
.multilineTextAlignment(multilineTextAlignment)
70-
if useSpacer {
71-
Spacer()
72-
}
73-
Image(systemName: "doc.on.doc")
74-
}
75-
}
76-
.foregroundColor(.primary)
90+
Copyable(text: text, useSpacer: useSpacer, content: {
91+
Text(text)
92+
.font(.body)
93+
.multilineTextAlignment(multilineTextAlignment)
94+
})
7795
} else {
7896
Text(text)
7997
.font(.body)

Shared/Wallet/TransactionView.swift

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ struct TransactionCell: View {
5353
struct TransactionView: View {
5454
var wallet: WalletContract
5555
var assetId: String = CitadelVault.embedded.nativeAsset.id
56+
var asset: Asset {
57+
CitadelVault.embedded.assets[assetId]!
58+
}
59+
60+
private struct AddressBalance: Identifiable {
61+
public var id: String { address }
62+
public let address: String
63+
public var amount: Double
64+
public var utxo: [(OutPoint, Double)]
65+
}
5666

5767
private var assetIdModified: String? {
5868
assetId == CitadelVault.embedded.nativeAsset.id ? nil : assetId
@@ -65,35 +75,86 @@ struct TransactionView: View {
6575
}
6676
return wallet.operations.filter { $0.assetId == assetIdModified }
6777
}
78+
private var addressBalances: [AddressBalance] {
79+
Array((wallet.balance(of: assetId)?.unspentAllocations.reduce(into: [String: AddressBalance]()) { ( balances: inout [String: AddressBalance], allocation) in
80+
guard let address = allocation.address else { return }
81+
var balance = balances[address] ?? AddressBalance(address: address, amount: 0, utxo: [])
82+
balance.amount += allocation.amount
83+
balance.utxo.append((allocation.outpoint, allocation.amount))
84+
balances[address] = balance
85+
} ?? [:]).values)
86+
}
6887

88+
enum SelectedTab: Hashable {
89+
case history, balance
90+
91+
var title: String {
92+
switch self {
93+
case .balance: return "Balance"
94+
case .history: return "History"
95+
}
96+
}
97+
}
98+
99+
@State private var selectedTab: SelectedTab = .history
69100
@State private var scannedInvoice: Invoice? = nil
70101
@State private var scannedString: String = ""
71102
@State var presentedSheet: PresentedSheet?
72-
private let placement: ToolbarItemPlacement = {
73-
#if os(iOS)
74-
return ToolbarItemPlacement.navigationBarLeading
75-
#else
76-
return ToolbarItemPlacement.primaryAction
77-
#endif
78-
}()
79103

80104
var body: some View {
81-
List(operations) { transaction in
82-
TransactionCell(transaction: transaction)
105+
List{
106+
if selectedTab == .history {
107+
ForEach(operations) { transaction in
108+
TransactionCell(transaction: transaction)
109+
}
110+
} else {
111+
ForEach(addressBalances) { balance in
112+
Section(header: Text("Address")) {
113+
Copyable(text: balance.address) {
114+
BechBrief(text: balance.address)
115+
}
116+
DetailsCell(title: "Balance:", details: "\(balance.amount) \(asset.ticker)", clipboardCopy: true)
117+
ForEach(balance.utxo, id: \.0) { (outpoint, amount) in
118+
HStack(alignment: .center) {
119+
VStack(alignment: .leading) {
120+
Text(outpoint.txid)
121+
.font(.subheadline)
122+
.truncationMode(.middle)
123+
.lineLimit(1)
124+
HStack(alignment: .lastTextBaseline) {
125+
Text("Output number:").font(.caption).foregroundColor(.secondary)
126+
Text("\(outpoint.vout)").font(.subheadline)
127+
}
128+
}
129+
Spacer()
130+
Text("\(amount) \(asset.ticker)").font(.subheadline)
131+
}.padding(.leading)
132+
}
133+
}
134+
}
135+
}
83136
}
84-
.navigationTitle("History")
137+
.listStyle(GroupedListStyle())
138+
.navigationTitle(selectedTab.title)
85139
.toolbar {
86-
ToolbarItemGroup(placement: placement) {
140+
ToolbarItem(placement: .confirmationAction) {
87141
Button("Receive") { presentedSheet = .invoice(wallet, assetId) }
88142
.background(Color.accentColor)
89143
.foregroundColor(.white)
90144
.cornerRadius(13)
91-
Spacer()
145+
}
146+
ToolbarItem(placement: .cancellationAction) {
92147
Button("Send") { presentedSheet = .scan("invoice", .invoice) }
93148
.background(Color.accentColor)
94149
.foregroundColor(.white)
95150
.cornerRadius(13)
96151
}
152+
ToolbarItem(placement: .principal) {
153+
Picker(selection: $selectedTab, label: EmptyView()) {
154+
Text("History").tag(SelectedTab.history)
155+
Text("Balance").tag(SelectedTab.balance)
156+
}.pickerStyle(SegmentedPickerStyle())
157+
}
97158
}
98159
.sheet(item: $presentedSheet) { item in
99160
switch item {

0 commit comments

Comments
 (0)