-
Notifications
You must be signed in to change notification settings - Fork 9
/
ReceivingAccount+Reducer.swift
129 lines (110 loc) · 2.93 KB
/
ReceivingAccount+Reducer.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
import ComposableArchitecture
import Sargon
import SwiftUI
// MARK: - ReceivingAccount
struct ReceivingAccount: Sendable, FeatureReducer {
struct State: Sendable, Hashable, Identifiable {
typealias ID = UUID
let id = ID()
var recipient: AccountOrAddressOf?
var assets: IdentifiedArrayOf<ResourceAsset.State>
var canBeRemoved: Bool
init(
recipient: AccountOrAddressOf?,
assets: IdentifiedArrayOf<ResourceAsset.State>,
canBeRemovedWhenEmpty: Bool
) {
self.recipient = recipient
self.assets = assets
self.canBeRemoved = canBeRemovedWhenEmpty
}
static func empty(canBeRemovedWhenEmpty: Bool) -> Self {
.init(recipient: nil, assets: [], canBeRemovedWhenEmpty: canBeRemovedWhenEmpty)
}
}
enum ViewAction: Sendable, Equatable {
case chooseAccountTapped
case addAssetTapped
case removeTapped
}
enum DelegateAction: Sendable, Equatable {
case remove
case chooseAccount
case addAssets
}
@CasePathable
enum ChildAction: Sendable, Equatable {
case row(id: ResourceAsset.State.ID, child: ResourceAsset.Action)
}
var body: some ReducerOf<Self> {
Reduce(core)
.forEach(\.assets, action: /Action.child .. ChildAction.row) {
ResourceAsset()
}
}
func reduce(into state: inout State, viewAction: ViewAction) -> Effect<Action> {
switch viewAction {
case .removeTapped:
.send(.delegate(.remove))
case .addAssetTapped:
.send(.delegate(.addAssets))
case .chooseAccountTapped:
.send(.delegate(.chooseAccount))
}
}
func reduce(into state: inout State, childAction: ChildAction) -> Effect<Action> {
switch childAction {
case let .row(id: id, child: .delegate(.removed)):
state.assets.remove(id: id)
return .none
default:
return .none
}
}
}
extension ReceivingAccount.State {
var isDepositEnabled: Bool {
assets.allSatisfy(\.isDepositEnabled)
}
var isLoadingDepositStatus: Bool {
assets.contains(where: { $0.depositStatus == .loading })
}
mutating func setAllDepositStatus(_ status: Loadable<DepositStatus>) {
assets.mutateAll { asset in
asset.depositStatus = status
}
}
mutating func updateDepositStatus(values: DepositStatusPerResources) {
assets.mutateAll { asset in
if let value = values[id: asset.resourceAddress] {
asset.depositStatus = .success(value.depositStatus)
}
}
}
}
extension AccountOrAddressOf {
var isUserAccount: Bool {
guard case .profileAccount = self else {
return false
}
return true
}
}
extension ResourceAsset.State {
var resourceAddress: ResourceAddress {
switch kind {
case let .fungibleAsset(state):
state.resource.resourceAddress
case let .nonFungibleAsset(state):
state.resource.resourceAddress
}
}
}
extension Collection<ResourceAsset.State> {
var fungibleAssets: [FungibleResourceAsset.State] {
map(\.kind).compactMap(/ResourceAsset.State.Kind.fungibleAsset)
}
var nonFungibleAssets: [NonFungibleResourceAsset.State] {
map(\.kind).compactMap(/ResourceAsset.State.Kind.nonFungibleAsset)
}
}