-
Notifications
You must be signed in to change notification settings - Fork 9
/
SelectFeePayer+View.swift
146 lines (132 loc) · 3.72 KB
/
SelectFeePayer+View.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import ComposableArchitecture
import SwiftUI
extension SelectFeePayer.State {
var viewState: SelectFeePayer.ViewState {
.init(
feePayerCandidates: feePayerCandidates.rawValue,
fee: transactionFee.totalFee.displayedTotalFee,
selectedPayer: feePayer
)
}
}
// MARK: - SelectFeePayer.View
extension SelectFeePayer {
public struct ViewState: Equatable {
let feePayerCandidates: Loadable<IdentifiedArrayOf<FeePayerCandidate>>
let fee: String
let selectedPayer: FeePayerCandidate?
var selectButtonControlState: ControlState {
switch feePayerCandidates {
case .idle, .loading:
.loading(.local)
case .success:
.enabled
case .failure:
.disabled
}
}
}
@MainActor
public struct View: SwiftUI.View {
private let store: StoreOf<SelectFeePayer>
public init(store: StoreOf<SelectFeePayer>) {
self.store = store
}
public var body: some SwiftUI.View {
WithViewStore(store, observe: \.viewState, send: { .view($0) }) { viewStore in
VStack {
Text(L10n.CustomizeNetworkFees.SelectFeePayer.navigationTitle)
.multilineTextAlignment(.center)
.textStyle(.sheetTitle)
.foregroundColor(.app.gray1)
.padding(.top, .medium3)
.padding(.horizontal, .medium1)
.padding(.bottom, .small2)
Text(L10n.CustomizeNetworkFees.SelectFeePayer.subtitle(viewStore.fee))
.multilineTextAlignment(.center)
.textStyle(.body1HighImportance)
.foregroundColor(.app.gray2)
.padding(.horizontal, .large3)
.padding(.bottom, .small1)
ScrollViewReader { proxy in
ScrollView {
loadable(viewStore.feePayerCandidates) {
ProgressView()
} successContent: { candidates in
VStack(spacing: .small1) {
Selection(
viewStore.binding(
get: \.selectedPayer,
send: { .selectedPayer($0) }
),
from: candidates
) { item in
SelectAccountToPayForFeeRow.View(
viewState: .init(candidate: item.value),
isSelected: item.isSelected,
action: item.action
)
.id(item.value.id)
}
}
.padding(.horizontal, .medium1)
.padding(.bottom, .medium2)
.onFirstAppear {
proxy.scrollTo(viewStore.selectedPayer?.id, anchor: .center)
}
}
}
}
.refreshable { @MainActor in
await viewStore.send(.pullToRefreshStarted).finish()
}
}
.task { @MainActor in
await viewStore.send(.task).finish()
}
.footer {
WithControlRequirements(
viewStore.selectedPayer,
forAction: { viewStore.send(.confirmedFeePayer($0)) }
) { action in
Button(L10n.CustomizeNetworkFees.SelectFeePayer.selectAccountButtonTitle, action: action)
.buttonStyle(.primaryRectangular)
.controlState(viewStore.selectButtonControlState)
}
}
}
}
}
}
// MARK: - SelectAccountToPayForFeeRow
enum SelectAccountToPayForFeeRow {
struct ViewState: Equatable {
let account: Account
let fungible: ResourceBalance.ViewState.Fungible
init(candidate: FeePayerCandidate) {
self.account = candidate.account
self.fungible = .xrd(balance: .init(nominalAmount: candidate.xrdBalance), network: account.networkID)
}
}
@MainActor
struct View: SwiftUI.View {
let viewState: ViewState
let isSelected: Bool
let action: () -> Void
var body: some SwiftUI.View {
Button(action: action) {
Card {
VStack(spacing: 0) {
SmallAccountCard(account: viewState.account)
HStack {
ResourceBalanceView(.fungible(viewState.fungible), appearance: .compact)
RadioButton(appearance: .dark, state: isSelected ? .selected : .unselected)
}
.padding(.medium3)
}
}
}
.buttonStyle(.inert)
}
}
}