• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hyperwallet / hyperwallet-ios-ui-sdk / 5360366649

pending completion
5360366649

push

github

web-flow
Rename polaris.yaml to polaris.yml (#345)

2252 of 2341 relevant lines covered (96.2%)

20.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.48
/TransferMethod/Sources/SelectTransferMethodTypePresenter.swift
1
//
2
// Copyright 2018 - Present Hyperwallet
3
//
4
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5
// and associated documentation files (the "Software"), to deal in the Software without restriction,
6
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
7
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8
// furnished to do so, subject to the following conditions:
9
//
10
// The above copyright notice and this permission notice shall be included in all copies or
11
// substantial portions of the Software.
12
//
13
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18

19
import HyperwalletSDK
20

21
#if !COCOAPODS
22
import Common
23
import TransferMethodRepository
24
import UserRepository
25
#endif
26

27
protocol SelectTransferMethodTypeView: AnyObject {
28
    typealias SelectItemHandler = (_ value: GenericCellConfiguration) -> Void
29
    typealias MarkCellHandler = (_ value: GenericCellConfiguration) -> Bool
30
    typealias FilterContentHandler = ((_ items: [GenericCellConfiguration],
31
        _ searchText: String) -> [GenericCellConfiguration])
32

33
    func showGenericTableView(items: [GenericCellConfiguration],
34
                              title: String,
35
                              selectItemHandler: @escaping SelectItemHandler,
36
                              markCellHandler: @escaping MarkCellHandler,
37
                              filterContentHandler: @escaping FilterContentHandler)
38

39
    func navigateToAddTransferMethodController(country: String,
40
                                               currency: String,
41
                                               profileType: String,
42
                                               transferMethodTypeCode: String)
43
    func showAlert(message: String?)
44
    func showError(_ error: HyperwalletErrorType,
45
                   pageName: String,
46
                   pageGroup: String,
47
                   _ retry: (() -> Void)?)
48
    func showLoading()
49
    func hideLoading()
50
    func reloadTransferMethodTypeData()
51
    func reloadCountryCurrencyData()
52
}
53

54
final class SelectTransferMethodTypePresenter {
55
    // MARK: properties
56
    private weak var view: SelectTransferMethodTypeView?
57
    private (set) var countryCurrencySectionData = [String]()
11✔
58
    private (set) var selectedCountry = ""
59
    private (set) var selectedCurrency = ""
60
    private let pageName = "transfer-method:add:select-transfer-method"
61
    private let pageGroup = "transfer-method"
62
    private let linkCountry = "select-country"
63
    private let linkCurrency = "select-currency"
64
    private let linkTransferMethod = "select-transfer-method"
65
    private var selectedTransferMethodType = ""
66
    private var hyperwalletInsights: HyperwalletInsightsProtocol
67

68
    private lazy var transferMethodConfigurationRepository = {
11✔
69
        TransferMethodRepositoryFactory.shared.transferMethodConfigurationRepository()
11✔
70
    }()
11✔
71

72
    private lazy var userRepository: UserRepository = {
11✔
73
        UserRepositoryFactory.shared.userRepository()
11✔
74
    }()
11✔
75

76
    private (set) var sectionData = [HyperwalletTransferMethodType]()
11✔
77

78
    /// Initialize SelectTransferMethodPresenter
79
    init(_ view: SelectTransferMethodTypeView,
80
         _ hyperwalletInsights: HyperwalletInsightsProtocol = HyperwalletInsights.shared) {
11✔
81
        self.view = view
11✔
82
        self.hyperwalletInsights = hyperwalletInsights
11✔
83
    }
11✔
84

85
    /// Return the countryCurrency item composed by the tuple (title and value)
86
    func getCountryCurrencyConfiguration(indexPath: IndexPath) -> CountryCurrencyCellConfiguration {
1✔
87
        let title = countryCurrencySectionData[indexPath.row]
1✔
88
        return CountryCurrencyCellConfiguration(title: title.localized(),
1✔
89
                                                value: countryCurrencyValues(at: indexPath.row))
1✔
90
    }
1✔
91

92
    /// Display all the select Country or Currency based on the index
93
    func performShowSelectCountryOrCurrencyView(index: Int) {
3✔
94
        transferMethodConfigurationRepository.getKeys(completion: self.getKeysHandler(
3✔
95
            success: { (result) in
3✔
96
                if index == 0 {
3✔
97
                    self.showSelectCountryView(result?.countries())
1✔
98
                } else {
3✔
99
                    self.showSelectCurrencyView(result?.currencies(from: self.selectedCountry))
2✔
100
                }
3✔
101
            }))
3✔
102
    }
3✔
103

104
    /// Loads the transferMethodKeys from core SDK and display the default transfer methods
105
    ///
106
    /// - Parameter forceUpdate: Forces to refresh the data
107
    func loadTransferMethodKeys(_ forceUpdate: Bool = false) {
19✔
108
        view?.showLoading()
19✔
109

19✔
110
        if forceUpdate {
19✔
111
            userRepository.refreshUser()
11✔
112
            transferMethodConfigurationRepository.refreshKeys()
11✔
113
        }
19✔
114

19✔
115
        userRepository.getUser { [weak self] getUserResult in
19✔
116
            guard let strongSelf = self, let view = strongSelf.view else {
19✔
117
                return
×
118
            }
19✔
119
            switch getUserResult {
19✔
120
            case .failure(let error):
19✔
121
                strongSelf.view?.hideLoading()
3✔
122
                strongSelf.view?.showError(error,
3✔
123
                                           pageName: strongSelf.pageName,
3✔
124
                                           pageGroup: strongSelf.pageGroup) {
3✔
125
                    strongSelf.loadTransferMethodKeys()
3✔
126
                }
3✔
127

19✔
128
            case .success(let user):
19✔
129
                strongSelf.transferMethodConfigurationRepository
16✔
130
                    .getKeys(completion: strongSelf.getKeysHandler(
16✔
131
                        success: { (result) in
16✔
132
                            guard let countries = result?.countries(), countries.isNotEmpty  else {
14✔
133
                                view.hideLoading()
1✔
134
                                strongSelf.view?.showAlert(message: "no_country_available_error_message".localized())
1✔
135
                                return
1✔
136
                            }
13✔
137
                            strongSelf.countryCurrencySectionData = [
13✔
138
                                "mobileCountryRegion".localized(),
13✔
139
                                "mobileCurrencyLabel".localized()
13✔
140
                            ]
13✔
141
                            strongSelf.loadSelectedCountry(countries, with: user?.country)
13✔
142
                            strongSelf.loadCurrency(result)
13✔
143
                            strongSelf.retrieveTransferMethodTypesFeesAndProcessingTimes { (result) in
13✔
144
                                strongSelf.loadTransferMethodTypesFeesAndProcessingTimes(result)
11✔
145
                            }
11✔
146
                        },
13✔
147
                        failure: {
16✔
148
                            view.hideLoading()
2✔
149
                            strongSelf.loadTransferMethodKeys()
2✔
150
                        })
2✔
151
                )
16✔
152
            }
19✔
153
        }
19✔
154
    }
19✔
155

156
    /// Navigate to AddTransferMethodController
157
    func navigateToAddTransferMethod(_ index: Int) {
1✔
158
        if let transferMethodTypeCode = self.sectionData[index].code {
1✔
159
            self.selectedTransferMethodType = transferMethodTypeCode
1✔
160
            self.trackTransferMethodClick()
1✔
161
        }
1✔
162
        userRepository.getUser {[weak self] (getUserResult) in
1✔
163
            guard let strongSelf = self else {
1✔
164
                return
×
165
            }
1✔
166

1✔
167
            if case let .success(user) = getUserResult,
1✔
168
                let profileType = user?.profileType?.rawValue {
1✔
169
                strongSelf.view?
1✔
170
                    .navigateToAddTransferMethodController(
1✔
171
                        country: strongSelf.selectedCountry,
1✔
172
                        currency: strongSelf.selectedCurrency,
1✔
173
                        profileType: profileType,
1✔
174
                        transferMethodTypeCode: strongSelf.selectedTransferMethodType
1✔
175
                )
1✔
176
            }
1✔
177
        }
1✔
178
    }
1✔
179

180
    private func countryCurrencyValues(at index: Int) -> String {
1✔
181
        return (index == 0
1✔
182
            ? Locale.current.localizedString(forRegionCode: selectedCountry) ?? selectedCountry
1✔
183
            : selectedCurrency)
1✔
184
    }
1✔
185

186
    private func getKeysHandler(
187
        success: @escaping ((HyperwalletTransferMethodConfigurationKey?) -> Void),
188
        failure: (() -> Void)? = nil)
189
        -> (Result<HyperwalletTransferMethodConfigurationKey?, HyperwalletErrorType>) -> Void {
20✔
190
        return { [weak self] (result) in
20✔
191
            guard let strongSelf = self, let view = strongSelf.view else {
20✔
192
                return
×
193
            }
20✔
194

20✔
195
            switch result {
20✔
196
            case .failure(let error):
20✔
197
                view.showError(error, pageName: strongSelf.pageName, pageGroup: strongSelf.pageGroup, failure)
2✔
198

20✔
199
            case .success(let keyResult):
20✔
200
                success(keyResult)
18✔
201
            }
20✔
202
        }
20✔
203
    }
20✔
204

205
    /// Shows the Select Country View
206
    private func showSelectCountryView(_ countries: [GenericCellConfiguration]?) {
1✔
207
        if let countries = countries {
1✔
208
            view?.showGenericTableView(items: countries,
1✔
209
                                       title: "mobileCountryRegion".localized(),
1✔
210
                                       selectItemHandler: selectCountryHandler(),
1✔
211
                                       markCellHandler: countryMarkCellHandler(),
1✔
212
                                       filterContentHandler: filterContentHandler())
1✔
213
        }
1✔
214
    }
1✔
215

216
    /// Shows the Select Currency View
217
    private func showSelectCurrencyView(_ currencies: [GenericCellConfiguration]?) {
2✔
218
        if let currencies = currencies {
2✔
219
            view?.showGenericTableView(items: currencies,
2✔
220
                                       title: "mobileCurrencyLabel".localized(),
2✔
221
                                       selectItemHandler: selectCurrencyHandler(),
2✔
222
                                       markCellHandler: currencyMarkCellHandler(),
2✔
223
                                       filterContentHandler: filterContentHandler())
2✔
224
        }
2✔
225
    }
2✔
226

227
    private func selectCountryHandler() -> SelectTransferMethodTypeView.SelectItemHandler {
1✔
228
        return { (country) in
1✔
229
            if let country = country.value {
1✔
230
                self.selectedCountry = country
1✔
231
                self.trackCountryClick()
1✔
232
            }
1✔
233
            self.transferMethodConfigurationRepository
1✔
234
                .getKeys(completion: self.getKeysHandler(success: { (result) in
1✔
235
                    self.loadCurrency(result)
1✔
236
                    self.view?.showLoading()
1✔
237
                    self.retrieveTransferMethodTypesFeesAndProcessingTimes { (result) in
1✔
238
                        self.loadTransferMethodTypesFeesAndProcessingTimes(result)
1✔
239
                    }
1✔
240
                }))
1✔
241
        }
1✔
242
    }
1✔
243

244
    private func selectCurrencyHandler() -> SelectTransferMethodTypeView.SelectItemHandler {
2✔
245
        return { [weak self](currency) in
2✔
246
            guard let strongSelf = self
2✔
247
            else { return }
2✔
248
            if let currency = currency.value {
2✔
249
                strongSelf.selectedCurrency = currency
2✔
250
                strongSelf.trackCurrencyClick()
2✔
251
            }
2✔
252
            strongSelf.view?.showLoading()
2✔
253
            strongSelf.retrieveTransferMethodTypesFeesAndProcessingTimes { result in
2✔
254
                strongSelf.loadTransferMethodTypesFeesAndProcessingTimes(result)
1✔
255
                strongSelf.view?.reloadCountryCurrencyData()
1✔
256
            }
1✔
257
        }
2✔
258
    }
2✔
259
    
260
    private func retrieveTransferMethodTypesFeesAndProcessingTimes(
261
        completion: @escaping ([HyperwalletTransferMethodType]?) -> Void) {
16✔
262
        transferMethodConfigurationRepository
16✔
263
            .getTransferMethodTypesFeesAndProcessingTimes(country: selectedCountry,
16✔
264
                                                          currency: selectedCurrency) { [weak self] (result) in
16✔
265
                guard let strongSelf = self, let view = strongSelf.view else {
16✔
266
                    return
×
267
                }
16✔
268
                view.hideLoading()
16✔
269
                switch result {
16✔
270
                case .failure(let error):
16✔
271
                    view.showError(error, pageName: strongSelf.pageName, pageGroup: strongSelf.pageGroup) {
3✔
272
                        strongSelf.loadTransferMethodKeys()
3✔
273
                    }
3✔
274
                    
16✔
275
                case .success(let keyResult):
16✔
276
                    completion(keyResult?.transferMethodTypes(countryCode: strongSelf.selectedCountry,
13✔
277
                                                              currencyCode: strongSelf.selectedCurrency))
13✔
278
                }
16✔
279
            }
16✔
280
    }
16✔
281

282
    private func filterContentHandler() -> SelectTransferMethodTypeView.FilterContentHandler {
3✔
283
        return {(items, searchText) in
3✔
284
            items.filter {
8✔
285
                $0.title?.lowercased().contains(searchText.lowercased()) ?? false ||
8✔
286
                    $0.value?.lowercased().contains(searchText.lowercased()) ?? false
8✔
287
            }
8✔
288
        }
3✔
289
    }
3✔
290

291
    private func countryMarkCellHandler() -> SelectTransferMethodTypeView.MarkCellHandler {
1✔
292
        return { [weak self] item in
1✔
293
            self?.selectedCountry == item.value
1✔
294
        }
1✔
295
    }
1✔
296

297
    private func currencyMarkCellHandler() -> SelectTransferMethodTypeView.MarkCellHandler {
2✔
298
        return { [weak self] item in
2✔
299
            self?.selectedCurrency == item.value
2✔
300
        }
2✔
301
    }
2✔
302

303
    private func loadSelectedCountry(_ countries: [HyperwalletCountry],
304
                                     with userCountry: String?) {
13✔
305
        if let userCountry = userCountry, countries.contains(where: { $0.value == userCountry }) {
34✔
306
            selectedCountry = userCountry
10✔
307
        } else if let country = countries.first, let countryValue = country.value {
13✔
308
            selectedCountry = countryValue
3✔
309
        }
13✔
310
    }
13✔
311

312
    private func loadCurrency(_ keys: HyperwalletTransferMethodConfigurationKey?) {
14✔
313
        guard let firstCurrency = keys?.currencies(from: selectedCountry)?.first,
14✔
314
            let currencyCode = firstCurrency.code else {
14✔
315
            view?.showAlert(message: String(format: "no_currency_available_error_message".localized(), selectedCountry))
1✔
316
            return
1✔
317
        }
13✔
318
        selectedCurrency = currencyCode
13✔
319
        view?.reloadCountryCurrencyData()
13✔
320
    }
13✔
321

322
    private func loadTransferMethodTypesFeesAndProcessingTimes(
323
        _ transferMethodTypes: [HyperwalletTransferMethodType]?) {
13✔
324
        guard let transferMethodTypes = transferMethodTypes,
13✔
325
            transferMethodTypes.isNotEmpty  else {
13✔
326
            view?.showAlert(message: String(format: "no_transfer_method_available_error_message".localized(),
3✔
327
                                            selectedCountry,
3✔
328
                                            selectedCurrency))
3✔
329
            return
3✔
330
        }
10✔
331

10✔
332
        sectionData = transferMethodTypes
10✔
333
        view?.reloadTransferMethodTypeData()
10✔
334
        trackUILoadImpression()
10✔
335
    }
10✔
336

337
    private func trackUILoadImpression() {
10✔
338
        let params = [InsightsTags.country: selectedCountry, InsightsTags.currency: selectedCurrency]
10✔
339
        hyperwalletInsights.trackImpression(pageName: pageName, pageGroup: pageGroup, params: params)
10✔
340
    }
10✔
341

342
    private func trackTransferMethodClick() {
1✔
343
       let clickParams = [
1✔
344
               InsightsTags.country:
1✔
345
                   self.selectedCountry,
1✔
346
               InsightsTags.currency:
1✔
347
                   self.selectedCurrency,
1✔
348
               InsightsTags.transferMethodType:
1✔
349
                   self.selectedTransferMethodType
1✔
350
       ]
1✔
351
         hyperwalletInsights
1✔
352
            .trackClick(pageName: pageName, pageGroup: pageGroup, link: linkTransferMethod, params: clickParams)
1✔
353
     }
1✔
354

355
    private func trackCountryClick() {
1✔
356
        hyperwalletInsights
1✔
357
            .trackClick(pageName: pageName,
1✔
358
                        pageGroup: pageGroup,
1✔
359
                        link: linkCountry,
1✔
360
                        params: [InsightsTags.country: self.selectedCountry])
1✔
361
     }
1✔
362

363
    private func trackCurrencyClick() {
2✔
364
        hyperwalletInsights
2✔
365
            .trackClick(pageName: pageName,
2✔
366
                        pageGroup: pageGroup,
2✔
367
                        link: linkCurrency,
2✔
368
                        params: [InsightsTags.currency: self.selectedCurrency])
2✔
369
       }
2✔
370
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc