Store an array of logged-in accounts internally, get the active
MastodonController from the current UIScene See #16
This commit is contained in:
parent
8dba15ca17
commit
3928b2e88a
|
@ -217,6 +217,8 @@
|
||||||
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E0DC8D216EDF1E00369478 /* Previewing.swift */; };
|
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E0DC8D216EDF1E00369478 /* Previewing.swift */; };
|
||||||
D6E6F26321603F8B006A8599 /* CharacterCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E6F26221603F8B006A8599 /* CharacterCounter.swift */; };
|
D6E6F26321603F8B006A8599 /* CharacterCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E6F26221603F8B006A8599 /* CharacterCounter.swift */; };
|
||||||
D6E6F26521604242006A8599 /* CharacterCounterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E6F26421604242006A8599 /* CharacterCounterTests.swift */; };
|
D6E6F26521604242006A8599 /* CharacterCounterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E6F26421604242006A8599 /* CharacterCounterTests.swift */; };
|
||||||
|
D6EBF01523C55C0900AE061B /* UIApplication+Scenes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6EBF01423C55C0900AE061B /* UIApplication+Scenes.swift */; };
|
||||||
|
D6EBF01723C55E0D00AE061B /* UISceneSession+MastodonController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6EBF01623C55E0D00AE061B /* UISceneSession+MastodonController.swift */; };
|
||||||
D6F1F84D2193B56E00F5FE67 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F1F84C2193B56E00F5FE67 /* Cache.swift */; };
|
D6F1F84D2193B56E00F5FE67 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F1F84C2193B56E00F5FE67 /* Cache.swift */; };
|
||||||
D6F953EC212519E700CF0F2B /* TimelineTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EB212519E700CF0F2B /* TimelineTableViewController.swift */; };
|
D6F953EC212519E700CF0F2B /* TimelineTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EB212519E700CF0F2B /* TimelineTableViewController.swift */; };
|
||||||
D6F953F021251A2900CF0F2B /* MastodonController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EF21251A2900CF0F2B /* MastodonController.swift */; };
|
D6F953F021251A2900CF0F2B /* MastodonController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EF21251A2900CF0F2B /* MastodonController.swift */; };
|
||||||
|
@ -494,6 +496,8 @@
|
||||||
D6E0DC8D216EDF1E00369478 /* Previewing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Previewing.swift; sourceTree = "<group>"; };
|
D6E0DC8D216EDF1E00369478 /* Previewing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Previewing.swift; sourceTree = "<group>"; };
|
||||||
D6E6F26221603F8B006A8599 /* CharacterCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterCounter.swift; sourceTree = "<group>"; };
|
D6E6F26221603F8B006A8599 /* CharacterCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterCounter.swift; sourceTree = "<group>"; };
|
||||||
D6E6F26421604242006A8599 /* CharacterCounterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterCounterTests.swift; sourceTree = "<group>"; };
|
D6E6F26421604242006A8599 /* CharacterCounterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterCounterTests.swift; sourceTree = "<group>"; };
|
||||||
|
D6EBF01423C55C0900AE061B /* UIApplication+Scenes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+Scenes.swift"; sourceTree = "<group>"; };
|
||||||
|
D6EBF01623C55E0D00AE061B /* UISceneSession+MastodonController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UISceneSession+MastodonController.swift"; sourceTree = "<group>"; };
|
||||||
D6F1F84C2193B56E00F5FE67 /* Cache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cache.swift; sourceTree = "<group>"; };
|
D6F1F84C2193B56E00F5FE67 /* Cache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cache.swift; sourceTree = "<group>"; };
|
||||||
D6F953EB212519E700CF0F2B /* TimelineTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewController.swift; sourceTree = "<group>"; };
|
D6F953EB212519E700CF0F2B /* TimelineTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewController.swift; sourceTree = "<group>"; };
|
||||||
D6F953EF21251A2900CF0F2B /* MastodonController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonController.swift; sourceTree = "<group>"; };
|
D6F953EF21251A2900CF0F2B /* MastodonController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -966,6 +970,8 @@
|
||||||
D67C57AE21E28EAD00C3118B /* Array+Uniques.swift */,
|
D67C57AE21E28EAD00C3118B /* Array+Uniques.swift */,
|
||||||
0450531E22B0097E00100BA2 /* Timline+UI.swift */,
|
0450531E22B0097E00100BA2 /* Timline+UI.swift */,
|
||||||
D66A77BA233838DC0058F1EC /* UIFont+Traits.swift */,
|
D66A77BA233838DC0058F1EC /* UIFont+Traits.swift */,
|
||||||
|
D6EBF01423C55C0900AE061B /* UIApplication+Scenes.swift */,
|
||||||
|
D6EBF01623C55E0D00AE061B /* UISceneSession+MastodonController.swift */,
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1620,6 +1626,7 @@
|
||||||
0427033A22B31269000D31B6 /* AdvancedPrefsView.swift in Sources */,
|
0427033A22B31269000D31B6 /* AdvancedPrefsView.swift in Sources */,
|
||||||
D626493C23C1000300612E6E /* AlbumTableViewCell.swift in Sources */,
|
D626493C23C1000300612E6E /* AlbumTableViewCell.swift in Sources */,
|
||||||
D6757A822157E8FA00721E32 /* XCBSession.swift in Sources */,
|
D6757A822157E8FA00721E32 /* XCBSession.swift in Sources */,
|
||||||
|
D6EBF01723C55E0D00AE061B /* UISceneSession+MastodonController.swift in Sources */,
|
||||||
04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */,
|
04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */,
|
||||||
D6AEBB412321642700E5038B /* SendMesasgeActivity.swift in Sources */,
|
D6AEBB412321642700E5038B /* SendMesasgeActivity.swift in Sources */,
|
||||||
D6BC9DB1232C61BC002CA326 /* NotificationsPageViewController.swift in Sources */,
|
D6BC9DB1232C61BC002CA326 /* NotificationsPageViewController.swift in Sources */,
|
||||||
|
@ -1680,6 +1687,7 @@
|
||||||
D64BC19223C271D9000D0238 /* MastodonActivity.swift in Sources */,
|
D64BC19223C271D9000D0238 /* MastodonActivity.swift in Sources */,
|
||||||
D6945C3A23AC75E2005C403C /* FindInstanceViewController.swift in Sources */,
|
D6945C3A23AC75E2005C403C /* FindInstanceViewController.swift in Sources */,
|
||||||
D6AEBB4523216AF800E5038B /* FollowAccountActivity.swift in Sources */,
|
D6AEBB4523216AF800E5038B /* FollowAccountActivity.swift in Sources */,
|
||||||
|
D6EBF01523C55C0900AE061B /* UIApplication+Scenes.swift in Sources */,
|
||||||
D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */,
|
D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */,
|
||||||
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */,
|
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */,
|
||||||
D6BED174212667E900F02DA0 /* TimelineStatusTableViewCell.swift in Sources */,
|
D6BED174212667E900F02DA0 /* TimelineStatusTableViewCell.swift in Sources */,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import UIKit
|
||||||
|
|
||||||
class MastodonActivity: UIActivity {
|
class MastodonActivity: UIActivity {
|
||||||
var mastodonController: MastodonController {
|
var mastodonController: MastodonController {
|
||||||
MastodonController.shared
|
let scene = UIApplication.shared.activeOrBackgroundScene!
|
||||||
|
return scene.session.mastodonController!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,54 +11,66 @@ import Pachyderm
|
||||||
|
|
||||||
class MastodonController {
|
class MastodonController {
|
||||||
|
|
||||||
@available(*, deprecated, message: "Use dependency injection to obtain an instance")
|
static private(set) var all = [LocalData.UserAccountInfo: MastodonController]()
|
||||||
static let shared = MastodonController()
|
|
||||||
|
@available(*, message: "do something less dumb")
|
||||||
|
static var first: MastodonController { all.first!.value }
|
||||||
|
|
||||||
|
static func getForAccount(_ account: LocalData.UserAccountInfo) -> MastodonController {
|
||||||
|
if let controller = all[account] {
|
||||||
|
return controller
|
||||||
|
} else {
|
||||||
|
let controller = MastodonController(instanceURL: account.instanceURL)
|
||||||
|
controller.accountInfo = account
|
||||||
|
controller.client.clientID = account.clientID
|
||||||
|
controller.client.clientSecret = account.clientSecret
|
||||||
|
controller.client.accessToken = account.accessToken
|
||||||
|
all[account] = controller
|
||||||
|
return controller
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private(set) lazy var cache = MastodonCache(mastodonController: self)
|
private(set) lazy var cache = MastodonCache(mastodonController: self)
|
||||||
|
|
||||||
private var client: Client!
|
let instanceURL: URL
|
||||||
|
private(set) var accountInfo: LocalData.UserAccountInfo?
|
||||||
|
|
||||||
|
let client: Client!
|
||||||
|
|
||||||
var account: Account!
|
var account: Account!
|
||||||
var instance: Instance!
|
var instance: Instance!
|
||||||
|
|
||||||
var accessToken: String? {
|
init(instanceURL: URL) {
|
||||||
client?.accessToken
|
self.instanceURL = instanceURL
|
||||||
}
|
self.accountInfo = nil
|
||||||
|
self.client = Client(baseURL: instanceURL)
|
||||||
func createClient(instanceURL: URL = LocalData.shared.instanceURL!) {
|
|
||||||
client = Client(baseURL: instanceURL)
|
|
||||||
|
|
||||||
if instanceURL == LocalData.shared.instanceURL {
|
|
||||||
client.clientID = LocalData.shared.clientID
|
|
||||||
client.clientSecret = LocalData.shared.clientSecret
|
|
||||||
client.accessToken = LocalData.shared.accessToken
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run<Result>(_ request: Request<Result>, completion: @escaping Client.Callback<Result>) {
|
func run<Result>(_ request: Request<Result>, completion: @escaping Client.Callback<Result>) {
|
||||||
client.run(request, completion: completion)
|
client.run(request, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerApp(completion: @escaping () -> Void) {
|
func registerApp(completion: @escaping (_ clientID: String, _ clientSecret: String) -> Void) {
|
||||||
guard LocalData.shared.clientID == nil,
|
guard client.clientID == nil,
|
||||||
LocalData.shared.clientSecret == nil else {
|
client.clientSecret == nil else {
|
||||||
completion()
|
|
||||||
|
completion(client.clientID!, client.clientSecret!)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
client.registerApp(name: "Tusker", redirectURI: "tusker://oauth", scopes: [.read, .write, .follow]) { response in
|
client.registerApp(name: "Tusker", redirectURI: "tusker://oauth", scopes: [.read, .write, .follow]) { response in
|
||||||
guard case let .success(app, _) = response else { fatalError() }
|
guard case let .success(app, _) = response else { fatalError() }
|
||||||
LocalData.shared.clientID = app.clientID
|
self.client.clientID = app.clientID
|
||||||
LocalData.shared.clientSecret = app.clientSecret
|
self.client.clientSecret = app.clientSecret
|
||||||
completion()
|
completion(app.clientID, app.clientSecret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func authorize(authorizationCode: String, completion: @escaping () -> Void) {
|
func authorize(authorizationCode: String, completion: @escaping (_ accessToken: String) -> Void) {
|
||||||
client.getAccessToken(authorizationCode: authorizationCode, redirectURI: "tusker://oauth") { response in
|
client.getAccessToken(authorizationCode: authorizationCode, redirectURI: "tusker://oauth") { response in
|
||||||
guard case let .success(settings, _) = response else { fatalError() }
|
guard case let .success(settings, _) = response else { fatalError() }
|
||||||
LocalData.shared.accessToken = settings.accessToken
|
self.client.accessToken = settings.accessToken
|
||||||
completion()
|
completion(settings.accessToken)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// UIApplication+Scenes.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 1/7/20.
|
||||||
|
// Copyright © 2020 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIApplication {
|
||||||
|
|
||||||
|
var activeScene: UIScene? {
|
||||||
|
connectedScenes.first { $0.activationState == .foregroundActive }
|
||||||
|
}
|
||||||
|
|
||||||
|
var backgroundScene: UIScene? {
|
||||||
|
connectedScenes.first { $0.activationState == .background }
|
||||||
|
}
|
||||||
|
|
||||||
|
var activeOrBackgroundScene: UIScene? {
|
||||||
|
activeScene ?? backgroundScene
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// UISceneSession+MastodonController.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 1/7/20.
|
||||||
|
// Copyright © 2020 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UISceneSession {
|
||||||
|
|
||||||
|
var mastodonController: MastodonController? {
|
||||||
|
get {
|
||||||
|
return userInfo?["mastodonController"] as? MastodonController
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if let newValue = newValue {
|
||||||
|
if userInfo == nil {
|
||||||
|
userInfo = ["mastodonController": newValue]
|
||||||
|
} else {
|
||||||
|
userInfo!["mastodonController"] = newValue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if userInfo != nil {
|
||||||
|
userInfo?.removeValue(forKey: "mastodonController")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,65 +18,99 @@ class LocalData {
|
||||||
if ProcessInfo.processInfo.environment.keys.contains("UI_TESTING") {
|
if ProcessInfo.processInfo.environment.keys.contains("UI_TESTING") {
|
||||||
defaults = UserDefaults(suiteName: "\(Bundle.main.bundleIdentifier!).uitesting")!
|
defaults = UserDefaults(suiteName: "\(Bundle.main.bundleIdentifier!).uitesting")!
|
||||||
if ProcessInfo.processInfo.environment.keys.contains("UI_TESTING_LOGIN") {
|
if ProcessInfo.processInfo.environment.keys.contains("UI_TESTING_LOGIN") {
|
||||||
defaults.set(true, forKey: onboardingCompleteKey)
|
accounts = [
|
||||||
defaults.set(URL(string: "http://localhost:8080")!, forKey: instanceURLKey)
|
UserAccountInfo(
|
||||||
defaults.set("client_id", forKey: clientIDKey)
|
instanceURL: URL(string: "http://localhost:8080")!,
|
||||||
defaults.set("client_secret", forKey: clientSecretKey)
|
clientID: "client_id",
|
||||||
defaults.set("access_token", forKey: accessTokenKey)
|
clientSecret: "client_secret",
|
||||||
|
username: "admin",
|
||||||
|
accessToken: "access_token")
|
||||||
|
]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
defaults = UserDefaults()
|
defaults = UserDefaults()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let onboardingCompleteKey = "onboardingComplete"
|
private let accountsKey = "accounts"
|
||||||
|
var accounts: [UserAccountInfo] {
|
||||||
|
get {
|
||||||
|
if let array = defaults.array(forKey: accountsKey) as? [[String: String]] {
|
||||||
|
return array.compactMap { (info) in
|
||||||
|
guard let instanceURL = info["instanceURL"],
|
||||||
|
let url = URL(string: instanceURL),
|
||||||
|
let id = info["clientID"],
|
||||||
|
let secret = info["clientSecret"],
|
||||||
|
let username = info["username"],
|
||||||
|
let accessToken = info["accessToken"] else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return UserAccountInfo(instanceURL: url, clientID: id, clientSecret: secret, username: username, accessToken: accessToken)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
let array = newValue.map { (info) in
|
||||||
|
return [
|
||||||
|
"instanceURL": info.instanceURL.absoluteString,
|
||||||
|
"clientID": info.clientID,
|
||||||
|
"clientSecret": info.clientSecret,
|
||||||
|
"username": info.username,
|
||||||
|
"accessToken": info.accessToken
|
||||||
|
]
|
||||||
|
}
|
||||||
|
defaults.set(array, forKey: accountsKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private let mostRecentAccountKey = "mostRecentAccount"
|
||||||
|
var mostRecentAccount: String? {
|
||||||
|
get {
|
||||||
|
return defaults.string(forKey: mostRecentAccountKey)
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
defaults.set(newValue, forKey: mostRecentAccountKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var onboardingComplete: Bool {
|
var onboardingComplete: Bool {
|
||||||
get {
|
return !accounts.isEmpty
|
||||||
return defaults.bool(forKey: onboardingCompleteKey)
|
}
|
||||||
|
|
||||||
|
func addAccount(instanceURL url: URL, clientID id: String, clientSecret secret: String, username: String, accessToken: String) -> UserAccountInfo {
|
||||||
|
var accounts = self.accounts
|
||||||
|
if let index = accounts.firstIndex(where: { $0.instanceURL == url && $0.username == username }) {
|
||||||
|
accounts.remove(at: index)
|
||||||
}
|
}
|
||||||
set {
|
let info = UserAccountInfo(instanceURL: url, clientID: id, clientSecret: secret, username: username, accessToken: accessToken)
|
||||||
defaults.set(newValue, forKey: onboardingCompleteKey)
|
accounts.append(info)
|
||||||
|
self.accounts = accounts
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeAccount(_ info: UserAccountInfo) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMostRecentAccount() -> UserAccountInfo? {
|
||||||
|
if let accessToken = mostRecentAccount {
|
||||||
|
return accounts.first { $0.accessToken == accessToken }
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let instanceURLKey = "instanceURL"
|
}
|
||||||
var instanceURL: URL? {
|
|
||||||
get {
|
|
||||||
return defaults.url(forKey: instanceURLKey)
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
defaults.set(newValue, forKey: instanceURLKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private let clientIDKey = "clientID"
|
extension LocalData {
|
||||||
var clientID: String? {
|
struct UserAccountInfo: Equatable, Hashable {
|
||||||
get {
|
let instanceURL: URL
|
||||||
return defaults.string(forKey: clientIDKey)
|
let clientID: String
|
||||||
}
|
let clientSecret: String
|
||||||
set {
|
let username: String
|
||||||
defaults.set(newValue, forKey: clientIDKey)
|
let accessToken: String
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private let clientSecretKey = "clientSecret"
|
|
||||||
var clientSecret: String? {
|
|
||||||
get {
|
|
||||||
return defaults.string(forKey: clientSecretKey)
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
defaults.set(newValue, forKey: clientSecretKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private let accessTokenKey = "accessToken"
|
|
||||||
var accessToken: String? {
|
|
||||||
get {
|
|
||||||
return defaults.string(forKey: accessTokenKey)
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
defaults.set(newValue, forKey: accessTokenKey)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,13 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import Pachyderm
|
||||||
|
|
||||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
|
||||||
let mastodonController = MastodonController.shared
|
// let mastodonController = MastodonController.shared
|
||||||
|
|
||||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
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`.
|
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||||
|
@ -23,6 +24,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
window = UIWindow(windowScene: windowScene)
|
window = UIWindow(windowScene: windowScene)
|
||||||
|
|
||||||
if LocalData.shared.onboardingComplete {
|
if LocalData.shared.onboardingComplete {
|
||||||
|
if session.mastodonController == nil {
|
||||||
|
let account = LocalData.shared.getMostRecentAccount()!
|
||||||
|
session.mastodonController = MastodonController.getForAccount(account)
|
||||||
|
}
|
||||||
|
|
||||||
showAppUI()
|
showAppUI()
|
||||||
} else {
|
} else {
|
||||||
showOnboardingUI()
|
showOnboardingUI()
|
||||||
|
@ -106,7 +112,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showAppUI() {
|
func showAppUI() {
|
||||||
mastodonController.createClient()
|
let mastodonController = window!.windowScene!.session.mastodonController!
|
||||||
mastodonController.getOwnAccount()
|
mastodonController.getOwnAccount()
|
||||||
mastodonController.getOwnInstance()
|
mastodonController.getOwnInstance()
|
||||||
|
|
||||||
|
@ -131,8 +137,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SceneDelegate: OnboardingViewControllerDelegate {
|
extension SceneDelegate: OnboardingViewControllerDelegate {
|
||||||
func didFinishOnboarding() {
|
func didFinishOnboarding(account: LocalData.UserAccountInfo) {
|
||||||
LocalData.shared.onboardingComplete = true
|
LocalData.shared.mostRecentAccount = account.accessToken
|
||||||
|
window!.windowScene!.session.mastodonController = MastodonController.getForAccount(account)
|
||||||
showAppUI()
|
showAppUI()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import UIKit
|
||||||
import AuthenticationServices
|
import AuthenticationServices
|
||||||
|
|
||||||
protocol OnboardingViewControllerDelegate {
|
protocol OnboardingViewControllerDelegate {
|
||||||
func didFinishOnboarding()
|
func didFinishOnboarding(account: LocalData.UserAccountInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnboardingViewController: UINavigationController {
|
class OnboardingViewController: UINavigationController {
|
||||||
|
@ -44,16 +44,13 @@ class OnboardingViewController: UINavigationController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension OnboardingViewController: InstanceSelectorTableViewControllerDelegate {
|
extension OnboardingViewController: InstanceSelectorTableViewControllerDelegate {
|
||||||
func didSelectInstance(url: URL) {
|
func didSelectInstance(url instanceURL: URL) {
|
||||||
LocalData.shared.instanceURL = url
|
let mastodonController = MastodonController(instanceURL: instanceURL)
|
||||||
let mastodonController = MastodonController.shared
|
mastodonController.registerApp { (clientID, clientSecret) in
|
||||||
mastodonController.createClient()
|
|
||||||
mastodonController.registerApp {
|
|
||||||
let clientID = LocalData.shared.clientID!
|
|
||||||
|
|
||||||
let callbackURL = "tusker://oauth"
|
let callbackURL = "tusker://oauth"
|
||||||
|
|
||||||
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)!
|
var components = URLComponents(url: instanceURL, resolvingAgainstBaseURL: false)!
|
||||||
components.path = "/oauth/authorize"
|
components.path = "/oauth/authorize"
|
||||||
components.queryItems = [
|
components.queryItems = [
|
||||||
URLQueryItem(name: "client_id", value: clientID),
|
URLQueryItem(name: "client_id", value: clientID),
|
||||||
|
@ -70,9 +67,13 @@ extension OnboardingViewController: InstanceSelectorTableViewControllerDelegate
|
||||||
let item = components.queryItems?.first(where: { $0.name == "code" }),
|
let item = components.queryItems?.first(where: { $0.name == "code" }),
|
||||||
let authCode = item.value else { return }
|
let authCode = item.value else { return }
|
||||||
|
|
||||||
mastodonController.authorize(authorizationCode: authCode) {
|
mastodonController.authorize(authorizationCode: authCode) { (accessToken) in
|
||||||
DispatchQueue.main.async {
|
mastodonController.getOwnAccount { (account) in
|
||||||
self.onboardingDelegate?.didFinishOnboarding()
|
let accountInfo = LocalData.shared.addAccount(instanceURL: instanceURL, clientID: clientID, clientSecret: clientSecret, username: account.username, accessToken: accessToken)
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.onboardingDelegate?.didFinishOnboarding(account: accountInfo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,9 @@ import SwiftUI
|
||||||
|
|
||||||
class PreferencesNavigationController: UINavigationController {
|
class PreferencesNavigationController: UINavigationController {
|
||||||
|
|
||||||
init() {
|
init(mastodonController: MastodonController) {
|
||||||
let hostingController = UIHostingController(rootView: PreferencesView())
|
let view = PreferencesView(currentAccount: mastodonController.accountInfo!)
|
||||||
|
let hostingController = UIHostingController(rootView: view)
|
||||||
super.init(rootViewController: hostingController)
|
super.init(rootViewController: hostingController)
|
||||||
hostingController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed))
|
hostingController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed))
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct PreferencesView : View {
|
struct PreferencesView : View {
|
||||||
|
var currentAccount: LocalData.UserAccountInfo
|
||||||
@State private var showingLogoutConfirmation = false
|
@State private var showingLogoutConfirmation = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
@ -49,11 +50,7 @@ struct PreferencesView : View {
|
||||||
}
|
}
|
||||||
|
|
||||||
func logoutPressed() {
|
func logoutPressed() {
|
||||||
LocalData.shared.onboardingComplete = false
|
LocalData.shared.removeAccount(currentAccount)
|
||||||
LocalData.shared.instanceURL = nil
|
|
||||||
LocalData.shared.clientID = nil
|
|
||||||
LocalData.shared.clientSecret = nil
|
|
||||||
LocalData.shared.accessToken = nil
|
|
||||||
NotificationCenter.default.post(name: .userLoggedOut, object: nil)
|
NotificationCenter.default.post(name: .userLoggedOut, object: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +58,8 @@ struct PreferencesView : View {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct PreferencesView_Previews : PreviewProvider {
|
struct PreferencesView_Previews : PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
PreferencesView()
|
let account = LocalData.UserAccountInfo(instanceURL: URL(string: "https://mastodon.social")!, clientID: "clientID", clientSecret: "clientSecret", username: "example", accessToken: "accessToken")
|
||||||
|
return PreferencesView(currentAccount: account)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -50,7 +50,7 @@ class MyProfileTableViewController: ProfileTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func preferencesPressed() {
|
@objc func preferencesPressed() {
|
||||||
present(PreferencesNavigationController(), animated: true)
|
present(PreferencesNavigationController(mastodonController: mastodonController), animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func closePreferences() {
|
@objc func closePreferences() {
|
||||||
|
|
|
@ -31,8 +31,7 @@ class InstanceTimelineViewController: TimelineTableViewController {
|
||||||
init(for url: URL) {
|
init(for url: URL) {
|
||||||
self.instanceURL = url
|
self.instanceURL = url
|
||||||
|
|
||||||
let mastodonController = MastodonController()
|
let mastodonController = MastodonController(instanceURL: url)
|
||||||
mastodonController.createClient(instanceURL: url)
|
|
||||||
|
|
||||||
super.init(for: .instance(instanceURL: url), mastodonController: mastodonController)
|
super.init(for: .instance(instanceURL: url), mastodonController: mastodonController)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,10 @@ class UserActivityManager {
|
||||||
private static let encoder = PropertyListEncoder()
|
private static let encoder = PropertyListEncoder()
|
||||||
private static let decoder = PropertyListDecoder()
|
private static let decoder = PropertyListDecoder()
|
||||||
|
|
||||||
private static var mastodonController: MastodonController { .shared }
|
private static var mastodonController: MastodonController {
|
||||||
|
let scene = UIApplication.shared.activeOrBackgroundScene!
|
||||||
|
return scene.session.mastodonController!
|
||||||
|
}
|
||||||
|
|
||||||
private static func getMainTabBarController() -> MainTabBarViewController {
|
private static func getMainTabBarController() -> MainTabBarViewController {
|
||||||
let scene = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first!
|
let scene = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first!
|
||||||
|
|
|
@ -13,13 +13,15 @@ import SwiftSoup
|
||||||
struct XCBActions {
|
struct XCBActions {
|
||||||
|
|
||||||
// MARK: - Utils
|
// MARK: - Utils
|
||||||
private static var mastodonController: MastodonController { .shared }
|
private static var mastodonController: MastodonController {
|
||||||
|
let scene = UIApplication.shared.activeOrBackgroundScene!
|
||||||
|
return scene.session.mastodonController!
|
||||||
|
}
|
||||||
|
|
||||||
private static func getMainTabBarController() -> MainTabBarViewController {
|
private static func getMainTabBarController() -> MainTabBarViewController {
|
||||||
let scene = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first!
|
let scene = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first!
|
||||||
let window = scene.windows.first { $0.isKeyWindow }!
|
let window = scene.windows.first { $0.isKeyWindow }!
|
||||||
return window.rootViewController as! MainTabBarViewController
|
return window.rootViewController as! MainTabBarViewController
|
||||||
// return (UIApplication.shared.delegate as! AppDelegate).window!.rootViewController as! MainTabBarViewController
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func show(_ vc: UIViewController) {
|
private static func show(_ vc: UIViewController) {
|
||||||
|
|
Loading…
Reference in New Issue