summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2021-04-28 10:26:01 +0200
committerAndrej Mihajlov <and@mullvad.net>2021-04-28 10:26:01 +0200
commit6f1427902092012c8e975494bb5f177861d25979 (patch)
treefa2f97d5a47a81a0016b1aa6f2485f298fe61fd8
parent65c5103bdd5c3a31fbf06d222351b3b8dcc8b2ea (diff)
parent703757b268df614ed23e63dd17e11f721447246a (diff)
downloadmullvadvpn-6f1427902092012c8e975494bb5f177861d25979.tar.xz
mullvadvpn-6f1427902092012c8e975494bb5f177861d25979.zip
Merge branch 'add-account-observer'
-rw-r--r--ios/MullvadVPN/Account.swift71
-rw-r--r--ios/MullvadVPN/AccountViewController.swift28
-rw-r--r--ios/MullvadVPN/AppStorePaymentManager.swift2
-rw-r--r--ios/MullvadVPN/SettingsViewController.swift26
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