diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2021-04-28 10:26:01 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2021-04-28 10:26:01 +0200 |
| commit | 6f1427902092012c8e975494bb5f177861d25979 (patch) | |
| tree | fa2f97d5a47a81a0016b1aa6f2485f298fe61fd8 | |
| parent | 65c5103bdd5c3a31fbf06d222351b3b8dcc8b2ea (diff) | |
| parent | 703757b268df614ed23e63dd17e11f721447246a (diff) | |
| download | mullvadvpn-6f1427902092012c8e975494bb5f177861d25979.tar.xz mullvadvpn-6f1427902092012c8e975494bb5f177861d25979.zip | |
Merge branch 'add-account-observer'
| -rw-r--r-- | ios/MullvadVPN/Account.swift | 71 | ||||
| -rw-r--r-- | ios/MullvadVPN/AccountViewController.swift | 28 | ||||
| -rw-r--r-- | ios/MullvadVPN/AppStorePaymentManager.swift | 2 | ||||
| -rw-r--r-- | ios/MullvadVPN/SettingsViewController.swift | 26 |
4 files changed, 92 insertions, 35 deletions
diff --git a/ios/MullvadVPN/Account.swift b/ios/MullvadVPN/Account.swift index 2146c65a2f..a3eea5157c 100644 --- a/ios/MullvadVPN/Account.swift +++ b/ios/MullvadVPN/Account.swift @@ -18,6 +18,37 @@ private enum UserDefaultsKeys: String { case accountExpiry = "accountExpiry" } +protocol AccountObserver: class { + func account(_ account: Account, didUpdateExpiry expiry: Date) + func account(_ account: Account, didLoginWithToken token: String, expiry: Date) + func accountDidLogout(_ account: Account) +} + +/// A type-erasing weak container for `AccountObserver` +private class AnyAccountObserver: AccountObserver, WeakObserverBox, Equatable { + private(set) weak var inner: AccountObserver? + + init<T: AccountObserver>(_ inner: T) { + self.inner = inner + } + + func account(_ account: Account, didUpdateExpiry expiry: Date) { + inner?.account(account, didUpdateExpiry: expiry) + } + + func account(_ account: Account, didLoginWithToken token: String, expiry: Date) { + inner?.account(account, didLoginWithToken: token, expiry: expiry) + } + + func accountDidLogout(_ account: Account) { + inner?.accountDidLogout(account) + } + + static func == (lhs: AnyAccountObserver, rhs: AnyAccountObserver) -> Bool { + return lhs.inner === rhs.inner + } +} + /// A class that groups the account related operations class Account { @@ -32,16 +63,11 @@ class Account { case tunnelConfiguration(TunnelManager.Error) } - /// A notification name used to broadcast the changes to account expiry - static let didUpdateAccountExpiryNotification = Notification.Name("didUpdateAccountExpiry") - - /// A notification userInfo key that holds the `Date` with the new account expiry - static let newAccountExpiryUserInfoKey = "newAccountExpiry" - /// A shared instance of `Account` static let shared = Account() private let logger = Logger(label: "Account") + private var observerList = ObserverList<AnyAccountObserver>() /// Returns true if user agreed to terms of service, otherwise false var isAgreedToTermsOfService: Bool { @@ -96,6 +122,11 @@ class Account { switch result { case .success(let response): self.setupTunnel(accountToken: response.token, expiry: response.expires) { (result) in + if case .success = result { + self.observerList.forEach { (observer) in + observer.account(self, didLoginWithToken: response.token, expiry: response.expires) + } + } completionHandler(result.map { response }) } @@ -117,6 +148,11 @@ class Account { switch result { case .success(let response): self.setupTunnel(accountToken: response.token, expiry: response.expires) { (result) in + if case .success = result { + self.observerList.forEach { (observer) in + observer.account(self, didLoginWithToken: response.token, expiry: response.expires) + } + } completionHandler(result.map { response }) } @@ -136,6 +172,9 @@ class Account { switch result { case .success: self.removeFromPreferences() + self.observerList.forEach { (observer) in + observer.accountDidLogout(self) + } finish(.success(())) @@ -168,7 +207,9 @@ class Account { switch result { case .success(let response): self.expiry = response.expires - self.postExpiryUpdateNotification(newExpiry: response.expires) + self.observerList.forEach { (observer) in + observer.account(self, didUpdateExpiry: response.expires) + } case .failure(let error): self.logger.error(chainedError: error, message: "Failed to update account expiry") @@ -200,14 +241,16 @@ class Account { preferences.removeObject(forKey: UserDefaultsKeys.accountToken.rawValue) preferences.removeObject(forKey: UserDefaultsKeys.accountExpiry.rawValue) + } + // MARK: - Account observation + + func addObserver<T: AccountObserver>(_ observer: T) { + observerList.append(AnyAccountObserver(observer)) } - fileprivate func postExpiryUpdateNotification(newExpiry: Date) { - NotificationCenter.default.post( - name: Self.didUpdateAccountExpiryNotification, - object: self, userInfo: [Self.newAccountExpiryUserInfoKey: newExpiry] - ) + func removeObserver<T: AccountObserver>(_ observer: T) { + observerList.remove(AnyAccountObserver(observer)) } } @@ -229,7 +272,9 @@ extension Account: AppStorePaymentObserver { // Make sure that payment corresponds to the active account token if self.token == accountToken { self.expiry = newExpiry - self.postExpiryUpdateNotification(newExpiry: newExpiry) + self.observerList.forEach { (observer) in + observer.account(self, didUpdateExpiry: newExpiry) + } } finish() diff --git a/ios/MullvadVPN/AccountViewController.swift b/ios/MullvadVPN/AccountViewController.swift index 03263ff6f1..dffa1cda48 100644 --- a/ios/MullvadVPN/AccountViewController.swift +++ b/ios/MullvadVPN/AccountViewController.swift @@ -14,7 +14,7 @@ protocol AccountViewControllerDelegate: class { func accountViewControllerDidLogout(_ controller: AccountViewController) } -class AccountViewController: UIViewController, AppStorePaymentObserver { +class AccountViewController: UIViewController, AppStorePaymentObserver, AccountObserver { @IBOutlet var accountTokenButton: UIButton! @IBOutlet var purchaseButton: InAppPurchaseButton! @@ -24,7 +24,6 @@ class AccountViewController: UIViewController, AppStorePaymentObserver { @IBOutlet var activityIndicator: SpinnerActivityIndicatorView! private var copyToPasteboardWork: DispatchWorkItem? - private var accountExpiryObserver: NSObjectProtocol? private var pendingPayment: SKPayment? private let alertPresenter = AlertPresenter() @@ -59,16 +58,7 @@ class AccountViewController: UIViewController, AppStorePaymentObserver { navigationItem.title = NSLocalizedString("Account", comment: "Navigation title") AppStorePaymentManager.shared.addPaymentObserver(self) - - accountExpiryObserver = NotificationCenter.default.addObserver( - forName: Account.didUpdateAccountExpiryNotification, - object: Account.shared, - queue: OperationQueue.main) { [weak self] (note) in - guard let newExpiryDate = note - .userInfo?[Account.newAccountExpiryUserInfoKey] as? Date else { return } - - self?.updateAccountExpiry(expiryDate: newExpiryDate) - } + Account.shared.addObserver(self) accountTokenButton.setTitle(Account.shared.formattedToken, for: .normal) @@ -266,6 +256,20 @@ class AccountViewController: UIViewController, AppStorePaymentObserver { } } + // MARK: - AccountObserver + + func account(_ account: Account, didUpdateExpiry expiry: Date) { + updateAccountExpiry(expiryDate: expiry) + } + + func account(_ account: Account, didLoginWithToken token: String, expiry: Date) { + // no-op + } + + func accountDidLogout(_ account: Account) { + // no-op + } + // MARK: - AppStorePaymentObserver func appStorePaymentManager(_ manager: AppStorePaymentManager, transaction: SKPaymentTransaction, accountToken: String?, didFailWithError error: AppStorePaymentManager.Error) { diff --git a/ios/MullvadVPN/AppStorePaymentManager.swift b/ios/MullvadVPN/AppStorePaymentManager.swift index ed8a1ad1f9..08d52a9ec1 100644 --- a/ios/MullvadVPN/AppStorePaymentManager.swift +++ b/ios/MullvadVPN/AppStorePaymentManager.swift @@ -49,7 +49,7 @@ protocol AppStorePaymentObserver: class { } /// A type-erasing weak container for `AppStorePaymentObserver` -private class AnyAppStorePaymentObserver: WeakObserverBox, Equatable { +private class AnyAppStorePaymentObserver: AppStorePaymentObserver, WeakObserverBox, Equatable { private(set) weak var inner: AppStorePaymentObserver? init<T: AppStorePaymentObserver>(_ inner: T) { diff --git a/ios/MullvadVPN/SettingsViewController.swift b/ios/MullvadVPN/SettingsViewController.swift index 58a382e60e..723f3c1828 100644 --- a/ios/MullvadVPN/SettingsViewController.swift +++ b/ios/MullvadVPN/SettingsViewController.swift @@ -13,7 +13,7 @@ protocol SettingsViewControllerDelegate: class { func settingsViewControllerDidFinish(_ controller: SettingsViewController) } -class SettingsViewController: UITableViewController { +class SettingsViewController: UITableViewController, AccountObserver { weak var delegate: SettingsViewControllerDelegate? @@ -59,16 +59,24 @@ class SettingsViewController: UITableViewController { navigationItem.largeTitleDisplayMode = .always navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleDismiss)) - accountExpiryObserver = NotificationCenter.default.addObserver( - forName: Account.didUpdateAccountExpiryNotification, - object: Account.shared, - queue: OperationQueue.main) { [weak self] (note) in - guard let accountRow = self?.accountRow else { return } + Account.shared.addObserver(self) + setupDataSource() + } - self?.staticDataSource.reloadRows([accountRow], with: .none) - } + // MARK: - AccountObserver - setupDataSource() + func account(_ account: Account, didUpdateExpiry expiry: Date) { + guard let accountRow = accountRow else { return } + + staticDataSource.reloadRows([accountRow], with: .none) + } + + func account(_ account: Account, didLoginWithToken token: String, expiry: Date) { + // no-op + } + + func accountDidLogout(_ account: Account) { + // no-op } // MARK: - IBActions |
