-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathCancelPledgeViewModel.swift
183 lines (154 loc) · 6.45 KB
/
CancelPledgeViewModel.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import KsApi
import Prelude
import ReactiveSwift
import UIKit
public struct CancelPledgeViewData {
public let project: Project // TODO: remove once tracking is updated.
public let projectName: String
public let omitUSCurrencyCode: Bool
public let backingId: String
public let pledgeAmount: Double
}
public protocol CancelPledgeViewModelInputs {
func cancelPledgeButtonTapped()
func configure(with data: CancelPledgeViewData)
func goBackButtonTapped()
func textFieldDidEndEditing(with text: String?)
func textFieldShouldReturn()
func traitCollectionDidChange()
func viewDidLoad()
func viewTapped()
}
public protocol CancelPledgeViewModelOutputs {
var cancellationDetailsAttributedText: Signal<NSAttributedString, Never> { get }
var cancelPledgeButtonEnabled: Signal<Bool, Never> { get }
var cancelPledgeError: Signal<String, Never> { get }
var dismissKeyboard: Signal<Void, Never> { get }
var isLoading: Signal<Bool, Never> { get }
var notifyDelegateCancelPledgeSuccess: Signal<String, Never> { get }
var popCancelPledgeViewController: Signal<Void, Never> { get }
}
public protocol CancelPledgeViewModelType {
var inputs: CancelPledgeViewModelInputs { get }
var outputs: CancelPledgeViewModelOutputs { get }
}
public final class CancelPledgeViewModel: CancelPledgeViewModelType, CancelPledgeViewModelInputs,
CancelPledgeViewModelOutputs {
public init() {
let data = Signal.combineLatest(
self.configureWithDataProperty.signal.skipNil(),
self.viewDidLoadProperty.signal
)
.map(first)
self.cancellationDetailsAttributedText = Signal.merge(
data,
data.takeWhen(self.traitCollectionDidChangeProperty.signal)
)
.map { data in
let projectCurrencyCountry = projectCountry(forCurrency: data.project.stats.currency) ?? data.project
.country
let formattedAmount = Format.currency(
data.pledgeAmount,
country: projectCurrencyCountry,
omitCurrencyCode: data.omitUSCurrencyCode
)
return (formattedAmount, data.projectName)
}
.map(createCancellationDetailsAttributedText(with:projectName:))
self.popCancelPledgeViewController = self.goBackButtonTappedProperty.signal
self.dismissKeyboard = Signal.merge(
self.textFieldShouldReturnProperty.signal,
self.viewTappedProperty.signal
)
let cancellationNote = Signal.merge(
self.viewDidLoadProperty.signal.mapConst(nil),
self.textFieldDidEndEditingTextProperty.signal
)
let cancelPledgeSubmit = Signal.combineLatest(
data.map { $0.backingId },
cancellationNote
)
.takeWhen(self.cancelPledgeButtonTappedProperty.signal)
let cancelPledgeEvent = cancelPledgeSubmit
.map(CancelBackingInput.init(backingId:cancellationReason:))
.switchMap { input in
AppEnvironment.current.apiService.cancelBacking(input: input)
.ksr_delay(AppEnvironment.current.apiDelayInterval, on: AppEnvironment.current.scheduler)
.materialize()
}
self.isLoading = Signal.merge(
self.cancelPledgeButtonTappedProperty.signal.mapConst(true),
cancelPledgeEvent.filter { $0.isTerminating }.mapConst(false)
)
self.notifyDelegateCancelPledgeSuccess = cancelPledgeEvent.values()
.map { _ in Strings.Youve_canceled_your_pledge() }
self.cancelPledgeError = cancelPledgeEvent
.errors()
.map { $0.localizedDescription }
self.cancelPledgeButtonEnabled = Signal.merge(
data.mapConst(true),
cancelPledgeSubmit.mapConst(false),
cancelPledgeEvent.map { $0.isTerminating }.mapConst(true)
)
.skipRepeats()
}
private let cancelPledgeButtonTappedProperty = MutableProperty(())
public func cancelPledgeButtonTapped() {
self.cancelPledgeButtonTappedProperty.value = ()
}
private let configureWithDataProperty = MutableProperty<CancelPledgeViewData?>(nil)
public func configure(with data: CancelPledgeViewData) {
self.configureWithDataProperty.value = data
}
private let goBackButtonTappedProperty = MutableProperty(())
public func goBackButtonTapped() {
self.goBackButtonTappedProperty.value = ()
}
private let textFieldDidEndEditingTextProperty = MutableProperty<String?>(nil)
public func textFieldDidEndEditing(with text: String?) {
self.textFieldDidEndEditingTextProperty.value = text
}
private let textFieldShouldReturnProperty = MutableProperty(())
public func textFieldShouldReturn() {
self.textFieldShouldReturnProperty.value = ()
}
private let traitCollectionDidChangeProperty = MutableProperty(())
public func traitCollectionDidChange() {
self.traitCollectionDidChangeProperty.value = ()
}
private let viewDidLoadProperty = MutableProperty(())
public func viewDidLoad() {
self.viewDidLoadProperty.value = ()
}
private let viewTappedProperty = MutableProperty(())
public func viewTapped() {
self.viewTappedProperty.value = ()
}
public let cancellationDetailsAttributedText: Signal<NSAttributedString, Never>
public let cancelPledgeButtonEnabled: Signal<Bool, Never>
public let cancelPledgeError: Signal<String, Never>
public let dismissKeyboard: Signal<Void, Never>
public let isLoading: Signal<Bool, Never>
public let notifyDelegateCancelPledgeSuccess: Signal<String, Never>
public let popCancelPledgeViewController: Signal<Void, Never>
public var inputs: CancelPledgeViewModelInputs { return self }
public var outputs: CancelPledgeViewModelOutputs { return self }
}
private func createCancellationDetailsAttributedText(with amount: String, projectName: String)
-> NSAttributedString {
let fullString = Strings
.Are_you_sure_you_wish_to_cancel_your_amount_pledge_to_project_name(
amount: amount,
project_name: projectName
)
let attributedString: NSMutableAttributedString = NSMutableAttributedString.init(string: fullString)
let regularFontAttribute = [NSAttributedString.Key.font: UIFont.ksr_callout()]
let boldFontAttribute = [NSAttributedString.Key.font: UIFont.ksr_callout().bolded]
let fullRange = (fullString as NSString).localizedStandardRange(of: fullString)
let rangeAmount: NSRange = (fullString as NSString).localizedStandardRange(of: amount)
let rangeProjectName: NSRange = (fullString as NSString).localizedStandardRange(of: projectName)
attributedString.addAttributes(regularFontAttribute, range: fullRange)
attributedString.addAttributes(boldFontAttribute, range: rangeAmount)
attributedString.addAttributes(boldFontAttribute, range: rangeProjectName)
return attributedString
}