Skip to content

Commit 50202cc

Browse files
authored
Merge pull request #8195 from woocommerce/issue/8080-refactor-connection-alerts-presentation
[Mobile Payments] Remove viewController from CardReaderConnectionController
2 parents 15f673c + 32cd773 commit 50202cc

File tree

5 files changed

+209
-103
lines changed

5 files changed

+209
-103
lines changed

WooCommerce/Classes/ViewRelated/CardPresentPayments/CardPresentPaymentPreflightController.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ final class CardPresentPaymentPreflightController {
2020
///
2121
private let configuration: CardPresentPaymentsConfiguration
2222

23-
/// View Controller used to present alerts.
23+
/// Alerts presenter to send alert view models
2424
///
25-
private var rootViewController: UIViewController
25+
private var alertsPresenter: CardPresentPaymentAlertsPresenting
2626

2727
/// Stores manager.
2828
///
@@ -38,32 +38,32 @@ final class CardPresentPaymentPreflightController {
3838

3939
/// Controller to connect a card reader.
4040
///
41-
private var connectionController: LegacyCardReaderConnectionController
41+
private var connectionController: CardReaderConnectionController
4242

4343

4444
private(set) var readerConnection = CurrentValueSubject<CardReaderConnectionResult?, Never>(nil)
4545

4646
init(siteID: Int64,
4747
paymentGatewayAccount: PaymentGatewayAccount,
4848
configuration: CardPresentPaymentsConfiguration,
49-
rootViewController: UIViewController,
49+
alertsPresenter: CardPresentPaymentAlertsPresenting,
5050
stores: StoresManager = ServiceLocator.stores,
5151
analytics: Analytics = ServiceLocator.analytics) {
5252
self.siteID = siteID
5353
self.paymentGatewayAccount = paymentGatewayAccount
5454
self.configuration = configuration
55-
self.rootViewController = rootViewController
55+
self.alertsPresenter = alertsPresenter
5656
self.stores = stores
5757
self.analytics = analytics
5858
self.connectedReader = nil
5959
let analyticsTracker = CardReaderConnectionAnalyticsTracker(configuration: configuration,
6060
stores: stores,
6161
analytics: analytics)
6262
// TODO: Replace this with a refactored (New)LegacyCardReaderConnectionController
63-
self.connectionController = LegacyCardReaderConnectionController(
63+
self.connectionController = CardReaderConnectionController(
6464
forSiteID: siteID,
6565
knownReaderProvider: CardReaderSettingsKnownReaderStorage(),
66-
alertsProvider: CardReaderSettingsAlerts(),
66+
alertsPresenter: alertsPresenter,
6767
configuration: configuration,
6868
analyticsTracker: analyticsTracker)
6969
}
@@ -81,7 +81,7 @@ final class CardPresentPaymentPreflightController {
8181
// TODO: Ask for a Reader type if supported by device
8282

8383
// Attempt to find a reader and connect
84-
connectionController.searchAndConnect(from: rootViewController) { result in
84+
connectionController.searchAndConnect { result in
8585
let connectionResult = result.map { connection in
8686
switch connection {
8787
case .connected:

WooCommerce/Classes/ViewRelated/CardPresentPayments/CardReaderConnectionController.swift

Lines changed: 64 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ final class CardReaderConnectionController {
8383
didSetState()
8484
}
8585
}
86-
private weak var fromController: UIViewController?
86+
8787
private let siteID: Int64
8888
private let knownCardReaderProvider: CardReaderSettingsKnownReaderProvider
89-
private let alerts: CardReaderSettingsAlertsProvider
89+
private let alertsPresenter: CardPresentPaymentAlertsPresenting
9090
private let configuration: CardPresentPaymentsConfiguration
9191

9292
/// Reader(s) discovered by the card reader service
@@ -139,7 +139,7 @@ final class CardReaderConnectionController {
139139
storageManager: StorageManagerType = ServiceLocator.storageManager,
140140
stores: StoresManager = ServiceLocator.stores,
141141
knownReaderProvider: CardReaderSettingsKnownReaderProvider,
142-
alertsProvider: CardReaderSettingsAlertsProvider,
142+
alertsPresenter: CardPresentPaymentAlertsPresenting,
143143
configuration: CardPresentPaymentsConfiguration,
144144
analyticsTracker: CardReaderConnectionAnalyticsTracker
145145
) {
@@ -148,7 +148,7 @@ final class CardReaderConnectionController {
148148
self.stores = stores
149149
state = .idle
150150
knownCardReaderProvider = knownReaderProvider
151-
alerts = alertsProvider
151+
self.alertsPresenter = alertsPresenter
152152
foundReaders = []
153153
knownReaderID = nil
154154
skippedReaderIDs = []
@@ -163,12 +163,7 @@ final class CardReaderConnectionController {
163163
subscriptions.removeAll()
164164
}
165165

166-
func searchAndConnect(from: UIViewController?, onCompletion: @escaping (Result<ConnectionResult, Error>) -> Void) {
167-
guard from != nil else {
168-
return
169-
}
170-
171-
self.fromController = from
166+
func searchAndConnect(onCompletion: @escaping (Result<ConnectionResult, Error>) -> Void) {
172167
self.onCompletion = onCompletion
173168
self.state = .initializing
174169
}
@@ -347,7 +342,7 @@ private extension CardReaderConnectionController {
347342
/// If the found-several-readers view is already presenting, update its list of found readers
348343
///
349344
if case .foundSeveralReaders = self.state {
350-
self.alerts.updateSeveralReadersList(readerIDs: self.getFoundReaderIDs())
345+
self.alertsPresenter.updateSeveralReadersList(readerIDs: self.getFoundReaderIDs())
351346
}
352347

353348
/// To avoid interrupting connecting to a known reader, ensure we are
@@ -404,10 +399,6 @@ private extension CardReaderConnectionController {
404399
/// If the user cancels the modal will trigger a transition to `.endSearch`
405400
///
406401
func onSearching() {
407-
guard let from = fromController else {
408-
return
409-
}
410-
411402
/// If we enter this state and another reader was discovered while the
412403
/// "Do you want to connect to" modal was being displayed and if that reader
413404
/// is known and the merchant tapped keep searching on the first
@@ -438,9 +429,9 @@ private extension CardReaderConnectionController {
438429
/// If all else fails, display the "scanning" modal and
439430
/// stay in this state
440431
///
441-
alerts.scanningForReader(from: from, cancel: {
432+
alertsPresenter.present(viewModel: CardPresentModalScanningForReader(cancel: {
442433
self.state = .cancel
443-
})
434+
}))
444435
}
445436

446437
/// A (unknown) reader has been found
@@ -451,37 +442,28 @@ private extension CardReaderConnectionController {
451442
return
452443
}
453444

454-
guard let from = fromController else {
455-
return
456-
}
457-
458-
alerts.foundReader(
459-
from: from,
460-
name: candidateReader.id,
461-
connect: {
462-
self.state = .connectToReader
463-
},
464-
continueSearch: {
465-
self.skippedReaderIDs.append(candidateReader.id)
466-
self.candidateReader = nil
467-
self.pruneSkippedReaders()
468-
self.state = .searching
469-
},
470-
cancelSearch: { [weak self] in
471-
self?.state = .cancel
472-
})
445+
alertsPresenter.present(
446+
viewModel: CardPresentModalFoundReader(
447+
name: candidateReader.id,
448+
connect: {
449+
self.state = .connectToReader
450+
},
451+
continueSearch: {
452+
self.skippedReaderIDs.append(candidateReader.id)
453+
self.candidateReader = nil
454+
self.pruneSkippedReaders()
455+
self.state = .searching
456+
},
457+
cancel: { [weak self] in
458+
self?.state = .cancel
459+
}))
473460
}
474461

475462
/// Several readers have been found
476463
/// Opens a continually updating list modal for the user to pick one (or cancel the search)
477464
///
478465
func onFoundSeveralReaders() {
479-
guard let from = fromController else {
480-
return
481-
}
482-
483-
alerts.foundSeveralReaders(
484-
from: from,
466+
alertsPresenter.foundSeveralReaders(
485467
readerIDs: getFoundReaderIDs(),
486468
connect: { [weak self] readerID in
487469
guard let self = self else {
@@ -499,10 +481,6 @@ private extension CardReaderConnectionController {
499481
/// A mandatory update is being installed
500482
///
501483
func onUpdateProgress(progress: Float) {
502-
guard let from = fromController else {
503-
return
504-
}
505-
506484
let cancel = softwareUpdateCancelable.map { cancelable in
507485
return { [weak self] in
508486
guard let self = self else { return }
@@ -518,16 +496,16 @@ private extension CardReaderConnectionController {
518496
}
519497
}
520498

521-
alerts.updateProgress(from: from,
522-
requiredUpdate: true,
523-
progress: progress,
524-
cancel: cancel)
499+
alertsPresenter.present(
500+
viewModel: CardPresentModalUpdateProgress(requiredUpdate: true,
501+
progress: progress,
502+
cancel: cancel))
525503
}
526504

527505
/// Retry a search for a card reader
528506
///
529507
func onRetry() {
530-
alerts.dismiss()
508+
alertsPresenter.dismiss()
531509
let action = CardPresentPaymentAction.cancelCardReaderDiscovery() { [weak self] _ in
532510
self?.state = .beginSearch
533511
}
@@ -550,10 +528,6 @@ private extension CardReaderConnectionController {
550528
return
551529
}
552530

553-
guard let from = fromController else {
554-
return
555-
}
556-
557531
analyticsTracker.setCandidateReader(candidateReader)
558532

559533
let softwareUpdateAction = CardPresentPaymentAction.observeCardReaderUpdateState { [weak self] softwareUpdateEvents in
@@ -618,7 +592,7 @@ private extension CardReaderConnectionController {
618592
}
619593
stores.dispatch(action)
620594

621-
alerts.connectingToReader(from: from)
595+
alertsPresenter.present(viewModel: CardPresentModalConnectingToReader())
622596
}
623597

624598
/// An error occurred while connecting
@@ -638,8 +612,7 @@ private extension CardReaderConnectionController {
638612
}
639613

640614
private func onUpdateFailed(error: Error) {
641-
guard let from = fromController,
642-
case CardReaderServiceError.softwareUpdate(underlyingError: let underlyingError, batteryLevel: let batteryLevel) = error else {
615+
guard case CardReaderServiceError.softwareUpdate(underlyingError: let underlyingError, batteryLevel: let batteryLevel) = error else {
643616
return
644617
}
645618

@@ -648,28 +621,20 @@ private extension CardReaderConnectionController {
648621
// Update was cancelled, don't treat this as an error
649622
return
650623
case .readerSoftwareUpdateFailedBatteryLow:
651-
alerts.updatingFailedLowBattery(
652-
from: from,
653-
batteryLevel: batteryLevel,
654-
close: {
655-
self.state = .searching
656-
}
657-
)
624+
alertsPresenter.present(
625+
viewModel: CardPresentModalUpdateFailedLowBattery(batteryLevel: batteryLevel,
626+
close: {
627+
self.state = .searching
628+
}))
658629
default:
659-
alerts.updatingFailed(
660-
from: from,
661-
tryAgain: nil,
662-
close: {
630+
alertsPresenter.present(
631+
viewModel: CardPresentModalUpdateFailedNonRetryable(close: {
663632
self.state = .searching
664-
})
633+
}))
665634
}
666635
}
667636

668637
private func showConnectionFailed(error: Error) {
669-
guard let from = fromController else {
670-
return
671-
}
672-
673638
let retrySearch = {
674639
self.state = .retry
675640
}
@@ -683,28 +648,37 @@ private extension CardReaderConnectionController {
683648
}
684649

685650
guard case CardReaderServiceError.connection(let underlyingError) = error else {
686-
return alerts.connectingFailed(from: from, continueSearch: continueSearch, cancelSearch: cancelSearch)
651+
return alertsPresenter.present(
652+
viewModel: CardPresentModalConnectingFailed(continueSearch: continueSearch, cancelSearch: cancelSearch))
687653
}
688654

689655
switch underlyingError {
690656
case .incompleteStoreAddress(let adminUrl):
691-
alerts.connectingFailedIncompleteAddress(from: from,
692-
openWCSettings: openWCSettingsAction(adminUrl: adminUrl,
693-
from: from,
694-
retrySearch: retrySearch),
695-
retrySearch: retrySearch,
696-
cancelSearch: cancelSearch)
657+
alertsPresenter.present(
658+
viewModel: CardPresentModalConnectingFailedUpdateAddress(
659+
openWCSettings: openWCSettingsAction(adminUrl: adminUrl,
660+
retrySearch: retrySearch),
661+
retrySearch: retrySearch,
662+
cancelSearch: cancelSearch))
697663
case .invalidPostalCode:
698-
alerts.connectingFailedInvalidPostalCode(from: from, retrySearch: retrySearch, cancelSearch: cancelSearch)
664+
alertsPresenter.present(
665+
viewModel: CardPresentModalConnectingFailedUpdatePostalCode(
666+
retrySearch: retrySearch,
667+
cancelSearch: cancelSearch))
699668
case .bluetoothConnectionFailedBatteryCriticallyLow:
700-
alerts.connectingFailedCriticallyLowBattery(from: from, retrySearch: retrySearch, cancelSearch: cancelSearch)
669+
alertsPresenter.present(
670+
viewModel: CardPresentModalConnectingFailedChargeReader(
671+
retrySearch: retrySearch,
672+
cancelSearch: cancelSearch))
701673
default:
702-
alerts.connectingFailed(from: from, continueSearch: continueSearch, cancelSearch: cancelSearch)
674+
alertsPresenter.present(
675+
viewModel: CardPresentModalConnectingFailed(
676+
continueSearch: continueSearch,
677+
cancelSearch: cancelSearch))
703678
}
704679
}
705680

706681
private func openWCSettingsAction(adminUrl: URL?,
707-
from viewController: UIViewController,
708682
retrySearch: @escaping () -> Void) -> ((UIViewController) -> Void)? {
709683
if let adminUrl = adminUrl {
710684
if let site = stores.sessionManager.defaultSite,
@@ -756,27 +730,24 @@ private extension CardReaderConnectionController {
756730
/// Presents the error in a modal
757731
///
758732
private func onDiscoveryFailed(error: Error) {
759-
guard let from = fromController else {
760-
return
761-
}
762-
763-
alerts.scanningFailed(from: from, error: error) { [weak self] in
733+
alertsPresenter.present(
734+
viewModel: CardPresentModalScanningFailed(error: error) { [weak self] in
764735
self?.returnFailure(error: error)
765-
}
736+
})
766737
}
767738

768739
/// Calls the completion with a success result
769740
///
770741
private func returnSuccess(result: ConnectionResult) {
771742
onCompletion?(.success(result))
772-
alerts.dismiss()
743+
alertsPresenter.dismiss()
773744
state = .idle
774745
}
775746

776747
/// Calls the completion with a failure result
777748
///
778749
private func returnFailure(error: Error) {
779-
alerts.dismiss()
750+
alertsPresenter.dismiss()
780751
onCompletion?(.failure(error))
781752
state = .idle
782753
}

0 commit comments

Comments
 (0)