diff --git a/Reader/FervorController.swift b/Reader/FervorController.swift index af96d66..3e14c68 100644 --- a/Reader/FervorController.swift +++ b/Reader/FervorController.swift @@ -18,6 +18,7 @@ class FervorController { private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "FervorController") let client: FervorClient + private(set) var account: LocalData.Account? private(set) var clientID: String? private(set) var clientSecret: String? private(set) var accessToken: String? @@ -31,6 +32,7 @@ class FervorController { convenience init(account: LocalData.Account) { self.init(instanceURL: account.instanceURL) + self.account = account self.clientID = account.clientID self.clientSecret = account.clientSecret self.accessToken = account.accessToken diff --git a/Reader/LocalData.swift b/Reader/LocalData.swift index 769e779..bf696e4 100644 --- a/Reader/LocalData.swift +++ b/Reader/LocalData.swift @@ -14,19 +14,39 @@ struct LocalData { private static let encoder = JSONEncoder() private static let decoder = JSONDecoder() - static var account: Account? { + static var accounts: [Account] { get { - guard let data = UserDefaults.standard.data(forKey: "account") else { - return nil + guard let data = UserDefaults.standard.data(forKey: "accounts"), + let accounts = try? decoder.decode([Account].self, from: data) else { + return [] } - return try? decoder.decode(Account.self, from: data) + return accounts } set { let data = try! encoder.encode(newValue) - UserDefaults.standard.set(data, forKey: "account") + UserDefaults.standard.set(data, forKey: "accounts") } } + static var mostRecentAccountID: UUID? { + get { + guard let str = UserDefaults.standard.string(forKey: "mostRecentAccountID") else { + return nil + } + return UUID(uuidString: str) + } + set { + UserDefaults.standard.set(newValue?.uuidString, forKey: "mostRecentAccountID") + } + } + + static func mostRecentAccount() -> Account? { + guard let id = mostRecentAccountID else { + return nil + } + return accounts.first(where: { $0.id == id }) + } + struct Account: Codable { let id: UUID let instanceURL: URL diff --git a/Reader/SceneDelegate.swift b/Reader/SceneDelegate.swift index 3988d49..c6adc12 100644 --- a/Reader/SceneDelegate.swift +++ b/Reader/SceneDelegate.swift @@ -22,7 +22,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window = UIWindow(windowScene: windowScene) window!.tintColor = .appTintColor - if let account = LocalData.account { + if let account = LocalData.mostRecentAccount() { fervorController = FervorController(account: account) createAppUI() } else { @@ -68,6 +68,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { private func createAppUI() { let home = HomeViewController(fervorController: fervorController) + home.delegate = self let nav = AppNavigationController(rootViewController: home) nav.navigationBar.prefersLargeTitles = true window!.rootViewController = nav @@ -81,8 +82,18 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { extension SceneDelegate: LoginViewControllerDelegate { func didLogin(with controller: FervorController) { - LocalData.account = .init(instanceURL: controller.instanceURL, clientID: controller.clientID!, clientSecret: controller.clientSecret!, accessToken: controller.accessToken!) - fervorController = FervorController(account: LocalData.account!) + let account = LocalData.Account(instanceURL: controller.instanceURL, clientID: controller.clientID!, clientSecret: controller.clientSecret!, accessToken: controller.accessToken!) + LocalData.accounts.append(account) + LocalData.mostRecentAccountID = account.id + fervorController = FervorController(account: account) + createAppUI() + } +} + +extension SceneDelegate: HomeViewControllerDelegate { + func switchToAccount(_ account: LocalData.Account) { + LocalData.mostRecentAccountID = account.id + fervorController = FervorController(account: account) createAppUI() } } diff --git a/Reader/Screens/Home/HomeViewController.swift b/Reader/Screens/Home/HomeViewController.swift index 0f0ad9b..607348a 100644 --- a/Reader/Screens/Home/HomeViewController.swift +++ b/Reader/Screens/Home/HomeViewController.swift @@ -8,8 +8,14 @@ import UIKit import CoreData +protocol HomeViewControllerDelegate: AnyObject { + func switchToAccount(_ account: LocalData.Account) +} + class HomeViewController: UIViewController { + weak var delegate: HomeViewControllerDelegate? + let fervorController: FervorController private var collectionView: UICollectionView! @@ -246,13 +252,33 @@ extension HomeViewController: StretchyMenuInteractionDelegate { return "Switch Accounts" } func stretchyMenuItems() -> [StretchyMenuItem] { - return [ - StretchyMenuItem(title: "foo", subtitle: "bar", action: { - print("foo") - }), - StretchyMenuItem(title: "baz", subtitle: "qux", action: { - print("baz") - }), - ] + var items: [StretchyMenuItem] = LocalData.accounts.map { account in + var title = account.instanceURL.host! + if let port = account.instanceURL.port, port != 80 && port != 443 { + title += ":\(port)" + } + let subtitle = account.id == fervorController.account!.id ? "Currently logged in" : nil + return StretchyMenuItem(title: title, subtitle: subtitle) { [unowned self] in + guard account.id != self.fervorController.account!.id else { return } + self.delegate?.switchToAccount(account) + } + } + items.append(StretchyMenuItem(title: "Add Account", subtitle: nil, action: { [unowned self] in + let login = LoginViewController() + login.delegate = self + login.navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .cancel, primaryAction: UIAction(handler: { (_) in + self.dismiss(animated: true) + }), menu: nil) + let nav = UINavigationController(rootViewController: login) + self.present(nav, animated: true) + })) + return items + } +} + +extension HomeViewController: LoginViewControllerDelegate { + func didLogin(with controller: FervorController) { + self.dismiss(animated: true) + (view.window!.windowScene!.delegate as! SceneDelegate).didLogin(with: controller) } }