From 863867c5226b650ec140be3dc6b4252ac83be719 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 18 Jan 2020 22:43:10 -0500 Subject: [PATCH] Add logging in to additional accounts and switching accounts via Preferences See #16 --- Tusker/LocalData.swift | 5 ++- Tusker/SceneDelegate.swift | 12 +++--- .../PreferencesNavigationController.swift | 39 +++++++++++++++++- .../Screens/Preferences/PreferencesView.swift | 41 +++++++++++++++---- .../Profile/ProfileTableViewController.swift | 2 +- 5 files changed, 82 insertions(+), 17 deletions(-) diff --git a/Tusker/LocalData.swift b/Tusker/LocalData.swift index 6dad3f5b..f3954fdd 100644 --- a/Tusker/LocalData.swift +++ b/Tusker/LocalData.swift @@ -7,8 +7,9 @@ // import Foundation +import Combine -class LocalData { +class LocalData: ObservableObject { static let shared = LocalData() @@ -52,6 +53,7 @@ class LocalData { } } set { + objectWillChange.send() let array = newValue.map { (info) in return [ "instanceURL": info.instanceURL.absoluteString, @@ -71,6 +73,7 @@ class LocalData { return defaults.string(forKey: mostRecentAccountKey) } set { + objectWillChange.send() defaults.set(newValue, forKey: mostRecentAccountKey) } } diff --git a/Tusker/SceneDelegate.swift b/Tusker/SceneDelegate.swift index 67c8c152..d4b939fb 100644 --- a/Tusker/SceneDelegate.swift +++ b/Tusker/SceneDelegate.swift @@ -13,8 +13,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? -// let mastodonController = MastodonController.shared - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. @@ -111,6 +109,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { DraftsManager.save() } + func activateAccount(_ account: LocalData.UserAccountInfo) { + LocalData.shared.mostRecentAccount = account.accessToken + window!.windowScene!.session.mastodonController = MastodonController.getForAccount(account) + showAppUI() + } + func showAppUI() { let mastodonController = window!.windowScene!.session.mastodonController! mastodonController.getOwnAccount() @@ -138,8 +142,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { extension SceneDelegate: OnboardingViewControllerDelegate { func didFinishOnboarding(account: LocalData.UserAccountInfo) { - LocalData.shared.mostRecentAccount = account.accessToken - window!.windowScene!.session.mastodonController = MastodonController.getForAccount(account) - showAppUI() + activateAccount(account) } } diff --git a/Tusker/Screens/Preferences/PreferencesNavigationController.swift b/Tusker/Screens/Preferences/PreferencesNavigationController.swift index db3a9349..c4a6c12e 100644 --- a/Tusker/Screens/Preferences/PreferencesNavigationController.swift +++ b/Tusker/Screens/Preferences/PreferencesNavigationController.swift @@ -12,7 +12,7 @@ import SwiftUI class PreferencesNavigationController: UINavigationController { init(mastodonController: MastodonController) { - let view = PreferencesView(currentAccount: mastodonController.accountInfo!) + let view = PreferencesView() let hostingController = UIHostingController(rootView: view) super.init(rootViewController: hostingController) hostingController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed)) @@ -21,6 +21,13 @@ class PreferencesNavigationController: UINavigationController { required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + NotificationCenter.default.addObserver(self, selector: #selector(showAddAccount), name: .addAccount, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(activateAccount(_:)), name: .activateAccount, object: nil) + } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) @@ -32,5 +39,35 @@ class PreferencesNavigationController: UINavigationController { @objc func donePressed() { dismiss(animated: true) } + + @objc func showAddAccount() { + let onboardingController = OnboardingViewController() + onboardingController.onboardingDelegate = self + onboardingController.instanceSelector.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelAddAccount)) + show(onboardingController, sender: self) + } + + @objc func cancelAddAccount() { + dismiss(animated: true) + } + + @objc func activateAccount(_ notification: Notification) { + let account = notification.userInfo!["account"] as! LocalData.UserAccountInfo + let sceneDelegate = self.view.window!.windowScene!.delegate as! SceneDelegate + dismiss(animated: true) { + sceneDelegate.activateAccount(account) + } + } } + +extension Notification.Name { + static let addAccount = Notification.Name("Tusker.addAccount") + static let activateAccount = Notification.Name("Tusker.activateAccount") +} + +extension PreferencesNavigationController: OnboardingViewControllerDelegate { + func didFinishOnboarding(account: LocalData.UserAccountInfo) { + LocalData.shared.mostRecentAccount = account.accessToken + } +} diff --git a/Tusker/Screens/Preferences/PreferencesView.swift b/Tusker/Screens/Preferences/PreferencesView.swift index 8f2078fa..38cbf993 100644 --- a/Tusker/Screens/Preferences/PreferencesView.swift +++ b/Tusker/Screens/Preferences/PreferencesView.swift @@ -7,8 +7,8 @@ import SwiftUI -struct PreferencesView : View { - var currentAccount: LocalData.UserAccountInfo +struct PreferencesView: View { + @ObservedObject var localData = LocalData.shared @State private var showingLogoutConfirmation = false var body: some View { @@ -16,12 +16,35 @@ struct PreferencesView : View { // NavigationView { List { Section { + ForEach(localData.accounts, id: \.accessToken) { (account) in + Button(action: { + NotificationCenter.default.post(name: .activateAccount, object: nil, userInfo: ["account": account]) + }) { + HStack { + Text(account.username) + .foregroundColor(.primary) + Spacer() + if account.accessToken == self.localData.mostRecentAccount { + Image(systemName: "checkmark") + .renderingMode(.template) + .foregroundColor(.secondary) + } + } + } + } Button(action: { - self.showingLogoutConfirmation = true + NotificationCenter.default.post(name: .addAccount, object: nil) }) { - Text("Logout") - }.alert(isPresented: $showingLogoutConfirmation) { - Alert(title: Text("Are you sure you want to logout?"), message: nil, primaryButton: .destructive(Text("Logout"), action: self.logoutPressed), secondaryButton: .cancel()) + Text("Add Account...") + } + if localData.mostRecentAccount != nil { + Button(action: { + self.showingLogoutConfirmation = true + }) { + Text("Logout from current") + }.alert(isPresented: $showingLogoutConfirmation) { + Alert(title: Text("Are you sure you want to logout?"), message: nil, primaryButton: .destructive(Text("Logout"), action: self.logoutPressed), secondaryButton: .cancel()) + } } } @@ -50,7 +73,8 @@ struct PreferencesView : View { } func logoutPressed() { - LocalData.shared.removeAccount(currentAccount) +// LocalData.shared.removeAccount(currentAccount) + localData.removeAccount(localData.getMostRecentAccount()!) NotificationCenter.default.post(name: .userLoggedOut, object: nil) } } @@ -58,8 +82,7 @@ struct PreferencesView : View { #if DEBUG struct PreferencesView_Previews : PreviewProvider { static var previews: some View { - let account = LocalData.UserAccountInfo(instanceURL: URL(string: "https://mastodon.social")!, clientID: "clientID", clientSecret: "clientSecret", username: "example", accessToken: "accessToken") - return PreferencesView(currentAccount: account) + return PreferencesView() } } #endif diff --git a/Tusker/Screens/Profile/ProfileTableViewController.swift b/Tusker/Screens/Profile/ProfileTableViewController.swift index 8ddb9739..8ff37b65 100644 --- a/Tusker/Screens/Profile/ProfileTableViewController.swift +++ b/Tusker/Screens/Profile/ProfileTableViewController.swift @@ -128,7 +128,7 @@ class ProfileTableViewController: EnhancedTableViewController { } @objc func updateUIForPreferences() { - guard let account = mastodonController.cache.account(for: accountID) else { fatalError("Missing cached account \(accountID!)") } + guard let accountID = accountID, let account = mastodonController.cache.account(for: accountID) else { return } navigationItem.title = account.realDisplayName }