From 2bdcb9b7f8fe4db1a26adaa3b820eca3f6303d52 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 5 Jan 2020 15:25:07 -0500 Subject: [PATCH] Replace global shared MastodonController instance with (mostly) dependency injection The places still using the .shared property are cases where there is no view controller from which to (easily) get the appropriate instance, such as user activity and X-Callback-URL handling. These uses will need to be revisited once there are multiple MastodonControllers. See #16 --- Tusker.xcodeproj/project.pbxproj | 4 ++ .../Account Activities/AccountActivity.swift | 2 +- .../FollowAccountActivity.swift | 2 +- .../SendMesasgeActivity.swift | 2 +- .../UnfollowAccountActivity.swift | 2 +- Tusker/Activities/MastodonActivity.swift | 15 ++++++++ .../BookmarkStatusActivity.swift | 2 +- .../Status Activities/PinStatusActivity.swift | 2 +- .../Status Activities/StatusActivity.swift | 2 +- .../UnbookmarkStatusActivity.swift | 2 +- .../UnpinStatusActivity.swift | 2 +- Tusker/AppDelegate.swift | 10 +++-- Tusker/Controllers/MastodonController.swift | 37 ++++++++++--------- Tusker/MastodonCache.swift | 8 ++-- .../AccountListTableViewController.swift | 9 ++++- .../BookmarksTableViewController.swift | 16 +++++--- .../Compose/ComposeViewController.swift | 22 ++++++----- .../ConversationTableViewController.swift | 8 +++- .../Explore/ExploreViewController.swift | 24 +++++++----- .../EditListAccountsViewController.swift | 15 +++++--- .../Lists/ListTimelineViewController.swift | 6 +-- .../Main/MainTabBarViewController.swift | 26 +++++++++---- .../NotificationsPageViewController.swift | 10 +++-- .../NotificationsTableViewController.swift | 14 ++++--- .../Onboarding/OnboardingViewController.swift | 7 ++-- .../MyProfileTableViewController.swift | 6 +-- .../Profile/ProfileTableViewController.swift | 12 ++++-- .../Search/SearchResultsViewController.swift | 9 ++++- ...ActionAccountListTableViewController.swift | 10 ++++- .../HashtagTimelineViewController.swift | 4 +- .../InstanceTimelineViewController.swift | 5 ++- .../TimelineTableViewController.swift | 14 ++++--- .../TimelinesPageViewController.swift | 12 ++++-- Tusker/Shortcuts/UserActivityManager.swift | 10 +++-- Tusker/TuskerNavigationDelegate.swift | 20 +++++----- .../Account Cell/AccountTableViewCell.swift | 8 +++- Tusker/Views/ContentLabel.swift | 14 ++++--- .../Hashtag Cell/HashtagTableViewCell.swift | 2 +- ...FollowNotificationGroupTableViewCell.swift | 6 ++- ...llowRequestNotificationTableViewCell.swift | 8 ++-- .../ProfileHeaderTableViewCell.swift | 3 +- .../Status/BaseStatusTableViewCell.swift | 13 +++++-- .../Status/TimelineStatusTableViewCell.swift | 8 ++-- Tusker/XCallbackURL/XCBActions.swift | 30 ++++++++------- 44 files changed, 286 insertions(+), 157 deletions(-) create mode 100644 Tusker/Activities/MastodonActivity.swift diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index 9dd15d8b..44d85d1e 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -118,6 +118,7 @@ D64BC18A23C16487000D0238 /* UnpinStatusActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18923C16487000D0238 /* UnpinStatusActivity.swift */; }; D64BC18F23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */; }; D64BC19023C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */; }; + D64BC19223C271D9000D0238 /* MastodonActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC19123C271D9000D0238 /* MastodonActivity.swift */; }; D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; }; D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; }; D64F80E2215875CC00BEF393 /* XCBActionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64F80E1215875CC00BEF393 /* XCBActionType.swift */; }; @@ -388,6 +389,7 @@ D64BC18923C16487000D0238 /* UnpinStatusActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnpinStatusActivity.swift; sourceTree = ""; }; D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowRequestNotificationTableViewCell.swift; sourceTree = ""; }; D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FollowRequestNotificationTableViewCell.xib; sourceTree = ""; }; + D64BC19123C271D9000D0238 /* MastodonActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonActivity.swift; sourceTree = ""; }; D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = ""; }; D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = ""; }; D64F80E1215875CC00BEF393 /* XCBActionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBActionType.swift; sourceTree = ""; }; @@ -1056,6 +1058,7 @@ children = ( D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */, D6AEBB422321685E00E5038B /* OpenInSafariActivity.swift */, + D64BC19123C271D9000D0238 /* MastodonActivity.swift */, D6AEBB4623216B0C00E5038B /* Account Activities */, D627943323A5523800D38C68 /* Status Activities */, ); @@ -1670,6 +1673,7 @@ D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */, D6B053A223BD2C0600A066FA /* AssetPickerViewController.swift in Sources */, D627944A23A6AD6100D38C68 /* BookmarksTableViewController.swift in Sources */, + D64BC19223C271D9000D0238 /* MastodonActivity.swift in Sources */, D6945C3A23AC75E2005C403C /* FindInstanceViewController.swift in Sources */, D6AEBB4523216AF800E5038B /* FollowAccountActivity.swift in Sources */, D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */, diff --git a/Tusker/Activities/Account Activities/AccountActivity.swift b/Tusker/Activities/Account Activities/AccountActivity.swift index e12e2233..1b91a98e 100644 --- a/Tusker/Activities/Account Activities/AccountActivity.swift +++ b/Tusker/Activities/Account Activities/AccountActivity.swift @@ -9,7 +9,7 @@ import UIKit import Pachyderm -class AccountActivity: UIActivity { +class AccountActivity: MastodonActivity { override class var activityCategory: UIActivity.Category { return .action diff --git a/Tusker/Activities/Account Activities/FollowAccountActivity.swift b/Tusker/Activities/Account Activities/FollowAccountActivity.swift index f0dc74f2..7beb3523 100644 --- a/Tusker/Activities/Account Activities/FollowAccountActivity.swift +++ b/Tusker/Activities/Account Activities/FollowAccountActivity.swift @@ -28,7 +28,7 @@ class FollowAccountActivity: AccountActivity { UIImpactFeedbackGenerator(style: .medium).impactOccurred() let request = Account.follow(account.id) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(relationship, _) = response { MastodonCache.add(relationship: relationship) } else { diff --git a/Tusker/Activities/Account Activities/SendMesasgeActivity.swift b/Tusker/Activities/Account Activities/SendMesasgeActivity.swift index 0238b0ab..ea67c0b0 100644 --- a/Tusker/Activities/Account Activities/SendMesasgeActivity.swift +++ b/Tusker/Activities/Account Activities/SendMesasgeActivity.swift @@ -28,7 +28,7 @@ class SendMessageActivity: AccountActivity { override var activityViewController: UIViewController? { guard let account = account else { return nil } - return UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct)) + return UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct, mastodonController: mastodonController)) } } diff --git a/Tusker/Activities/Account Activities/UnfollowAccountActivity.swift b/Tusker/Activities/Account Activities/UnfollowAccountActivity.swift index 94daf756..344387d7 100644 --- a/Tusker/Activities/Account Activities/UnfollowAccountActivity.swift +++ b/Tusker/Activities/Account Activities/UnfollowAccountActivity.swift @@ -28,7 +28,7 @@ class UnfollowAccountActivity: AccountActivity { UIImpactFeedbackGenerator(style: .medium).impactOccurred() let request = Account.unfollow(account.id) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(relationship, _) = response { MastodonCache.add(relationship: relationship) } else { diff --git a/Tusker/Activities/MastodonActivity.swift b/Tusker/Activities/MastodonActivity.swift new file mode 100644 index 00000000..32275951 --- /dev/null +++ b/Tusker/Activities/MastodonActivity.swift @@ -0,0 +1,15 @@ +// +// MastodonActivity.swift +// Tusker +// +// Created by Shadowfacts on 1/5/20. +// Copyright © 2020 Shadowfacts. All rights reserved. +// + +import UIKit + +class MastodonActivity: UIActivity { + var mastodonController: MastodonController { + MastodonController.shared + } +} diff --git a/Tusker/Activities/Status Activities/BookmarkStatusActivity.swift b/Tusker/Activities/Status Activities/BookmarkStatusActivity.swift index df1fcfc9..8c64f007 100644 --- a/Tusker/Activities/Status Activities/BookmarkStatusActivity.swift +++ b/Tusker/Activities/Status Activities/BookmarkStatusActivity.swift @@ -27,7 +27,7 @@ class BookmarkStatusActivity: StatusActivity { guard let status = status else { return } let request = Status.bookmark(status) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(status, _) = response { MastodonCache.add(status: status) } else { diff --git a/Tusker/Activities/Status Activities/PinStatusActivity.swift b/Tusker/Activities/Status Activities/PinStatusActivity.swift index f73d0474..3714a453 100644 --- a/Tusker/Activities/Status Activities/PinStatusActivity.swift +++ b/Tusker/Activities/Status Activities/PinStatusActivity.swift @@ -26,7 +26,7 @@ class PinStatusActivity: StatusActivity { guard let status = status else { return } let request = Status.pin(status) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(status, _) = response { MastodonCache.add(status: status) } else { diff --git a/Tusker/Activities/Status Activities/StatusActivity.swift b/Tusker/Activities/Status Activities/StatusActivity.swift index 715b0a6e..3469b789 100644 --- a/Tusker/Activities/Status Activities/StatusActivity.swift +++ b/Tusker/Activities/Status Activities/StatusActivity.swift @@ -9,7 +9,7 @@ import UIKit import Pachyderm -class StatusActivity: UIActivity { +class StatusActivity: MastodonActivity { override class var activityCategory: UIActivity.Category { return .action diff --git a/Tusker/Activities/Status Activities/UnbookmarkStatusActivity.swift b/Tusker/Activities/Status Activities/UnbookmarkStatusActivity.swift index e88a3549..be22c5e1 100644 --- a/Tusker/Activities/Status Activities/UnbookmarkStatusActivity.swift +++ b/Tusker/Activities/Status Activities/UnbookmarkStatusActivity.swift @@ -27,7 +27,7 @@ class UnbookmarkStatusActivity: StatusActivity { guard let status = status else { return } let request = Status.unbookmark(status) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(status, _) = response { MastodonCache.add(status: status) } else { diff --git a/Tusker/Activities/Status Activities/UnpinStatusActivity.swift b/Tusker/Activities/Status Activities/UnpinStatusActivity.swift index 134e852d..cbb717cb 100644 --- a/Tusker/Activities/Status Activities/UnpinStatusActivity.swift +++ b/Tusker/Activities/Status Activities/UnpinStatusActivity.swift @@ -26,7 +26,7 @@ class UnpinStatusActivity: StatusActivity { guard let status = status else { return } let request = Status.unpin(status) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(status, _) = response { MastodonCache.add(status: status) } else { diff --git a/Tusker/AppDelegate.swift b/Tusker/AppDelegate.swift index 68e6c4a8..6f7521aa 100644 --- a/Tusker/AppDelegate.swift +++ b/Tusker/AppDelegate.swift @@ -12,6 +12,8 @@ import UIKit class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? + + let mastodonController = MastodonController.shared func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { AppShortcutItem.createItems(for: application) @@ -95,11 +97,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } func showAppUI() { - MastodonController.createClient() - MastodonController.getOwnAccount() - MastodonController.getOwnInstance() + mastodonController.createClient() + mastodonController.getOwnAccount() + mastodonController.getOwnInstance() - let tabBarController = MainTabBarViewController() + let tabBarController = MainTabBarViewController(mastodonController: mastodonController) window!.rootViewController = tabBarController } diff --git a/Tusker/Controllers/MastodonController.swift b/Tusker/Controllers/MastodonController.swift index 6c841c49..a916d777 100644 --- a/Tusker/Controllers/MastodonController.swift +++ b/Tusker/Controllers/MastodonController.swift @@ -11,32 +11,33 @@ import Pachyderm class MastodonController { - private static var client: Client! + @available(*, deprecated, message: "Use dependency injection to obtain an instance") + static let shared = MastodonController() - static var account: Account! - static var instance: Instance! + private var client: Client! - static var accessToken: String? { + var account: Account! + var instance: Instance! + + var accessToken: String? { client?.accessToken } - private init() {} - - static func createClient() { - guard let url = LocalData.shared.instanceURL else { fatalError("Can't connect without instance URL") } + func createClient(instanceURL: URL = LocalData.shared.instanceURL!) { + client = Client(baseURL: instanceURL) - client = Client(baseURL: url) - - client.clientID = LocalData.shared.clientID - client.clientSecret = LocalData.shared.clientSecret - client.accessToken = LocalData.shared.accessToken + if instanceURL == LocalData.shared.instanceURL { + client.clientID = LocalData.shared.clientID + client.clientSecret = LocalData.shared.clientSecret + client.accessToken = LocalData.shared.accessToken + } } - static func run(_ request: Request, completion: @escaping Client.Callback) { + func run(_ request: Request, completion: @escaping Client.Callback) { client.run(request, completion: completion) } - static func registerApp(completion: @escaping () -> Void) { + func registerApp(completion: @escaping () -> Void) { guard LocalData.shared.clientID == nil, LocalData.shared.clientSecret == nil else { completion() @@ -51,7 +52,7 @@ class MastodonController { } } - static func authorize(authorizationCode: String, completion: @escaping () -> Void) { + func authorize(authorizationCode: String, completion: @escaping () -> Void) { client.getAccessToken(authorizationCode: authorizationCode, redirectURI: "tusker://oauth") { response in guard case let .success(settings, _) = response else { fatalError() } LocalData.shared.accessToken = settings.accessToken @@ -59,7 +60,7 @@ class MastodonController { } } - static func getOwnAccount(completion: ((Account) -> Void)? = nil) { + func getOwnAccount(completion: ((Account) -> Void)? = nil) { if account != nil { completion?(account) } else { @@ -73,7 +74,7 @@ class MastodonController { } } - static func getOwnInstance() { + func getOwnInstance() { let request = Client.getInstance() run(request) { (response) in guard case let .success(instance, _) = response else { fatalError() } diff --git a/Tusker/MastodonCache.swift b/Tusker/MastodonCache.swift index 70b5482d..1ac5eddf 100644 --- a/Tusker/MastodonCache.swift +++ b/Tusker/MastodonCache.swift @@ -20,6 +20,8 @@ class MastodonCache { static let statusSubject = PassthroughSubject() static let accountSubject = PassthroughSubject() + static var mastodonController: MastodonController { .shared } + // MARK: - Statuses static func status(for id: String) -> Status? { return statuses[id] @@ -38,7 +40,7 @@ class MastodonCache { static func status(for id: String, completion: @escaping (Status?) -> Void) { let request = Client.getStatus(id: id) - MastodonController.run(request) { response in + mastodonController.run(request) { response in guard case let .success(status, _) = response else { completion(nil) return @@ -68,7 +70,7 @@ class MastodonCache { static func account(for id: String, completion: @escaping (Account?) -> Void) { let request = Client.getAccount(id: id) - MastodonController.run(request) { response in + mastodonController.run(request) { response in guard case let .success(account, _) = response else { completion(nil) return @@ -97,7 +99,7 @@ class MastodonCache { static func relationship(for id: String, completion: @escaping (Relationship?) -> Void) { let request = Client.getRelationships(accounts: [id]) - MastodonController.run(request) { response in + mastodonController.run(request) { response in guard case let .success(relationships, _) = response, let relationship = relationships.first else { completion(nil) diff --git a/Tusker/Screens/Account List/AccountListTableViewController.swift b/Tusker/Screens/Account List/AccountListTableViewController.swift index 8635a017..36fe72e2 100644 --- a/Tusker/Screens/Account List/AccountListTableViewController.swift +++ b/Tusker/Screens/Account List/AccountListTableViewController.swift @@ -12,10 +12,13 @@ class AccountListTableViewController: EnhancedTableViewController { private let accountCell = "accountCell" + let mastodonController: MastodonController + let accountIDs: [String] - init(accountIDs: [String]) { + init(accountIDs: [String], mastodonController: MastodonController) { self.accountIDs = accountIDs + self.mastodonController = mastodonController super.init(style: .grouped) } @@ -58,4 +61,6 @@ class AccountListTableViewController: EnhancedTableViewController { } -extension AccountListTableViewController: TuskerNavigationDelegate {} +extension AccountListTableViewController: TuskerNavigationDelegate { + var apiController: MastodonController { mastodonController } +} diff --git a/Tusker/Screens/Bookmarks/BookmarksTableViewController.swift b/Tusker/Screens/Bookmarks/BookmarksTableViewController.swift index 142213af..a4370c05 100644 --- a/Tusker/Screens/Bookmarks/BookmarksTableViewController.swift +++ b/Tusker/Screens/Bookmarks/BookmarksTableViewController.swift @@ -13,6 +13,8 @@ class BookmarksTableViewController: EnhancedTableViewController { private let statusCell = "statusCell" + let mastodonController: MastodonController + var statuses: [(id: String, state: StatusState)] = [] { didSet { DispatchQueue.main.async { @@ -24,7 +26,9 @@ class BookmarksTableViewController: EnhancedTableViewController { var newer: RequestRange? var older: RequestRange? - init() { + init(mastodonController: MastodonController) { + self.mastodonController = mastodonController + super.init(style: .plain) title = NSLocalizedString("Bookmarks", comment: "bookmarks screen title") @@ -45,7 +49,7 @@ class BookmarksTableViewController: EnhancedTableViewController { tableView.prefetchDataSource = self let request = Client.getBookmarks() - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in guard case let .success(statuses, pagination) = response else { fatalError() } MastodonCache.addAll(statuses: statuses) self.statuses.append(contentsOf: statuses.map { ($0.id, .unknown) }) @@ -82,7 +86,7 @@ class BookmarksTableViewController: EnhancedTableViewController { } let request = Client.getBookmarks(range: older) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in guard case let .success(newStatuses, pagination) = response else { fatalError() } self.older = pagination?.older MastodonCache.addAll(statuses: newStatuses) @@ -107,7 +111,7 @@ class BookmarksTableViewController: EnhancedTableViewController { let unbookmarkAction = UIContextualAction(style: .destructive, title: NSLocalizedString("Unbookmark", comment: "unbookmark action title")) { (action, view, completion) in let request = Status.unbookmark(status) - MastodonController.run(request) { (response) in + self.mastodonController.run(request) { (response) in guard case let .success(newStatus, _) = response else { fatalError() } MastodonCache.add(status: newStatus) self.statuses.remove(at: indexPath.row) @@ -131,7 +135,7 @@ class BookmarksTableViewController: EnhancedTableViewController { return [ UIAction(title: NSLocalizedString("Unbookmark", comment: "unbookmark action title"), image: UIImage(systemName: "bookmark.fill"), identifier: .init("unbookmark"), discoverabilityTitle: nil, attributes: [], state: .off, handler: { (_) in let request = Status.unbookmark(status) - MastodonController.run(request) { (response) in + self.mastodonController.run(request) { (response) in guard case let .success(newStatus, _) = response else { fatalError() } MastodonCache.add(status: newStatus) self.statuses.remove(at: indexPath.row) @@ -143,6 +147,8 @@ class BookmarksTableViewController: EnhancedTableViewController { } extension BookmarksTableViewController: StatusTableViewCellDelegate { + var apiController: MastodonController { mastodonController } + func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { tableView.beginUpdates() tableView.endUpdates() diff --git a/Tusker/Screens/Compose/ComposeViewController.swift b/Tusker/Screens/Compose/ComposeViewController.swift index 6dbabc22..07a68169 100644 --- a/Tusker/Screens/Compose/ComposeViewController.swift +++ b/Tusker/Screens/Compose/ComposeViewController.swift @@ -12,6 +12,8 @@ import Intents class ComposeViewController: UIViewController { + let mastodonController: MastodonController + var inReplyToID: String? var accountsToMention: [String] var initialText: String? @@ -64,7 +66,9 @@ class ComposeViewController: UIViewController { @IBOutlet weak var postProgressView: SteppedProgressView! - init(inReplyTo inReplyToID: String? = nil, mentioningAcct: String? = nil, text: String? = nil) { + init(inReplyTo inReplyToID: String? = nil, mentioningAcct: String? = nil, text: String? = nil, mastodonController: MastodonController) { + self.mastodonController = mastodonController + self.inReplyToID = inReplyToID if let inReplyToID = inReplyToID, let inReplyTo = MastodonCache.status(for: inReplyToID) { accountsToMention = [inReplyTo.account.acct] + inReplyTo.mentions.map { $0.acct } @@ -73,7 +77,7 @@ class ComposeViewController: UIViewController { } else { accountsToMention = [] } - if let ownAccount = MastodonController.account { + if let ownAccount = mastodonController.account { accountsToMention.removeAll(where: { acct in ownAccount.acct == acct }) } accountsToMention = accountsToMention.uniques() @@ -120,7 +124,7 @@ class ComposeViewController: UIViewController { statusTextView.text = accountsToMention.map({ acct in "@\(acct) " }).joined() initialText = statusTextView.text - MastodonController.getOwnAccount { (account) in + mastodonController.getOwnAccount { (account) in DispatchQueue.main.async { self.selfDetailView.update(account: account) } @@ -270,7 +274,7 @@ class ComposeViewController: UIViewController { // TODO: include CW char count let count = CharacterCounter.count(text: statusTextView.text) let cwCount = contentWarningEnabled ? (contentWarningTextField.text?.count ?? 0) : 0 - let remaining = (MastodonController.instance.maxStatusCharacters ?? 500) - count - cwCount + let remaining = (mastodonController.instance.maxStatusCharacters ?? 500) - count - cwCount if remaining < 0 { charactersRemainingLabel.textColor = .red postBarButtonItem.isEnabled = false @@ -296,7 +300,7 @@ class ComposeViewController: UIViewController { } func updateAddAttachmentButton() { - switch MastodonController.instance.instanceType { + switch mastodonController.instance.instanceType { case .pleroma: addAttachmentButton.isEnabled = true case .mastodon: @@ -481,7 +485,7 @@ class ComposeViewController: UIViewController { self.postProgressView.step() let request = Client.upload(attachment: FormAttachment(mimeType: mimeType, data: data, fileName: "file"), description: description) - MastodonController.run(request) { (response) in + self.mastodonController.run(request) { (response) in guard case let .success(attachment, _) = response else { fatalError() } attachments[index] = attachment @@ -507,7 +511,7 @@ class ComposeViewController: UIViewController { spoilerText: contentWarning, visibility: visibility, language: nil) - MastodonController.run(request) { (response) in + self.mastodonController.run(request) { (response) in guard case let .success(status, _) = response else { fatalError() } self.postedStatus = status MastodonCache.add(status: status) @@ -520,7 +524,7 @@ class ComposeViewController: UIViewController { self.postProgressView.step() self.dismiss(animated: true) - let conversationVC = ConversationTableViewController(for: status.id) + let conversationVC = ConversationTableViewController(for: status.id, mastodonController: self.mastodonController) self.show(conversationVC, sender: self) self.xcbSession?.complete(with: .success, additionalData: [ @@ -561,7 +565,7 @@ extension ComposeViewController: UITextViewDelegate { extension ComposeViewController: AssetPickerViewControllerDelegate { func assetPicker(_ assetPicker: AssetPickerViewController, shouldAllowAssetOfType type: CompositionAttachment.AttachmentType) -> Bool { - switch MastodonController.instance.instanceType { + switch mastodonController.instance.instanceType { case .pleroma: return true case .mastodon: diff --git a/Tusker/Screens/Conversation/ConversationTableViewController.swift b/Tusker/Screens/Conversation/ConversationTableViewController.swift index 92410f58..31bbc061 100644 --- a/Tusker/Screens/Conversation/ConversationTableViewController.swift +++ b/Tusker/Screens/Conversation/ConversationTableViewController.swift @@ -15,6 +15,8 @@ class ConversationTableViewController: EnhancedTableViewController { static let showPostsImage = UIImage(systemName: "eye.fill")! static let hidePostsImage = UIImage(systemName: "eye.slash.fill")! + let mastodonController: MastodonController + let mainStatusID: String let mainStatusState: StatusState var statuses: [(id: String, state: StatusState)] = [] { @@ -28,9 +30,10 @@ class ConversationTableViewController: EnhancedTableViewController { var showStatusesAutomatically = false var visibilityBarButtonItem: UIBarButtonItem! - init(for mainStatusID: String, state: StatusState = .unknown) { + init(for mainStatusID: String, state: StatusState = .unknown, mastodonController: MastodonController) { self.mainStatusID = mainStatusID self.mainStatusState = state + self.mastodonController = mastodonController super.init(style: .plain) } @@ -58,7 +61,7 @@ class ConversationTableViewController: EnhancedTableViewController { guard let mainStatus = MastodonCache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID)") } let request = Status.getContext(mainStatus) - MastodonController.run(request) { response in + mastodonController.run(request) { response in guard case let .success(context, _) = response else { fatalError() } let parents = self.getDirectParents(of: mainStatus, from: context.ancestors) MastodonCache.addAll(statuses: parents) @@ -155,6 +158,7 @@ class ConversationTableViewController: EnhancedTableViewController { } extension ConversationTableViewController: StatusTableViewCellDelegate { + var apiController: MastodonController { mastodonController } func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { // causes the table view to recalculate the cell heights tableView.beginUpdates() diff --git a/Tusker/Screens/Explore/ExploreViewController.swift b/Tusker/Screens/Explore/ExploreViewController.swift index a7f6fc12..c278c2b4 100644 --- a/Tusker/Screens/Explore/ExploreViewController.swift +++ b/Tusker/Screens/Explore/ExploreViewController.swift @@ -12,12 +12,16 @@ import Pachyderm class ExploreViewController: EnhancedTableViewController { + let mastodonController: MastodonController + var dataSource: DataSource! var resultsController: SearchResultsViewController! var searchController: UISearchController! - init() { + init(mastodonController: MastodonController) { + self.mastodonController = mastodonController + super.init(style: .insetGrouped) title = NSLocalizedString("Explore", comment: "explore tab title") @@ -88,7 +92,7 @@ class ExploreViewController: EnhancedTableViewController { dataSource.apply(snapshot) } - resultsController = SearchResultsViewController() + resultsController = SearchResultsViewController(mastodonController: mastodonController) resultsController.exploreNavigationController = self.navigationController! searchController = UISearchController(searchResultsController: resultsController) searchController.searchResultsUpdater = resultsController @@ -107,7 +111,7 @@ class ExploreViewController: EnhancedTableViewController { func reloadLists() { let request = Client.getLists() - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in guard case let .success(lists, _) = response else { fatalError() } @@ -143,7 +147,7 @@ class ExploreViewController: EnhancedTableViewController { alert.addAction(UIAlertAction(title: NSLocalizedString("Delete List", comment: "delete list alert confirm button"), style: .destructive, handler: { (_) in let request = List.delete(list) - MastodonController.run(request) { (response) in + self.mastodonController.run(request) { (response) in guard case .success(_, _) = response else { fatalError() } @@ -174,10 +178,10 @@ class ExploreViewController: EnhancedTableViewController { return case .bookmarks: - show(BookmarksTableViewController(), sender: nil) + show(BookmarksTableViewController(mastodonController: mastodonController), sender: nil) case let .list(list): - show(ListTimelineViewController(for: list), sender: nil) + show(ListTimelineViewController(for: list, mastodonController: mastodonController), sender: nil) case .addList: tableView.selectRow(at: nil, animated: true, scrollPosition: .none) @@ -190,13 +194,13 @@ class ExploreViewController: EnhancedTableViewController { } let request = Client.createList(title: title) - MastodonController.run(request) { (response) in + self.mastodonController.run(request) { (response) in guard case let .success(list, _) = response else { fatalError() } self.reloadLists() DispatchQueue.main.async { - let listTimelineController = ListTimelineViewController(for: list) + let listTimelineController = ListTimelineViewController(for: list, mastodonController: self.mastodonController) listTimelineController.presentEditOnAppear = true self.show(listTimelineController, sender: nil) } @@ -205,11 +209,11 @@ class ExploreViewController: EnhancedTableViewController { present(alert, animated: true) case let .savedHashtag(hashtag): - show(HashtagTimelineViewController(for: hashtag), sender: nil) + show(HashtagTimelineViewController(for: hashtag, mastodonController: mastodonController), sender: nil) case .addSavedHashtag: tableView.selectRow(at: nil, animated: true, scrollPosition: .none) - let navController = UINavigationController(rootViewController: AddSavedHashtagViewController()) + let navController = UINavigationController(rootViewController: AddSavedHashtagViewController(mastodonController: mastodonController)) present(navController, animated: true) case let .savedInstance(url): diff --git a/Tusker/Screens/Lists/EditListAccountsViewController.swift b/Tusker/Screens/Lists/EditListAccountsViewController.swift index 7484d1dd..796c58f4 100644 --- a/Tusker/Screens/Lists/EditListAccountsViewController.swift +++ b/Tusker/Screens/Lists/EditListAccountsViewController.swift @@ -11,6 +11,8 @@ import Pachyderm class EditListAccountsViewController: EnhancedTableViewController { + let mastodonController: MastodonController + let list: List var dataSource: DataSource! @@ -20,8 +22,9 @@ class EditListAccountsViewController: EnhancedTableViewController { var searchResultsController: SearchResultsViewController! var searchController: UISearchController! - init(list: List) { + init(list: List, mastodonController: MastodonController) { self.list = list + self.mastodonController = mastodonController super.init(style: .plain) @@ -49,7 +52,7 @@ class EditListAccountsViewController: EnhancedTableViewController { }) dataSource.editListAccountsController = self - searchResultsController = SearchResultsViewController() + searchResultsController = SearchResultsViewController(mastodonController: mastodonController) searchResultsController.delegate = self searchResultsController.onlySections = [.accounts] searchController = UISearchController(searchResultsController: searchResultsController) @@ -70,7 +73,7 @@ class EditListAccountsViewController: EnhancedTableViewController { func loadAccounts() { let request = List.getAccounts(list) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in guard case let .success(accounts, pagination) = response else { fatalError() } @@ -109,7 +112,7 @@ class EditListAccountsViewController: EnhancedTableViewController { fatalError() } let request = List.update(self.list, title: text) - MastodonController.run(request) { (response) in + self.mastodonController.run(request) { (response) in guard case .success(_, _) = response else { fatalError() } @@ -143,7 +146,7 @@ extension EditListAccountsViewController { } let request = List.remove(editListAccountsController!.list, accounts: [id]) - MastodonController.run(request) { (response) in + editListAccountsController!.mastodonController.run(request) { (response) in guard case .success(_, _) = response else { fatalError() } @@ -157,7 +160,7 @@ extension EditListAccountsViewController { extension EditListAccountsViewController: SearchResultsViewControllerDelegate { func selectedSearchResult(account accountID: String) { let request = List.add(list, accounts: [accountID]) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in guard case .success(_, _) = response else { fatalError() } diff --git a/Tusker/Screens/Lists/ListTimelineViewController.swift b/Tusker/Screens/Lists/ListTimelineViewController.swift index 664d65ee..bf8dbac3 100644 --- a/Tusker/Screens/Lists/ListTimelineViewController.swift +++ b/Tusker/Screens/Lists/ListTimelineViewController.swift @@ -15,10 +15,10 @@ class ListTimelineViewController: TimelineTableViewController { var presentEditOnAppear = false - init(for list: List) { + init(for list: List, mastodonController: MastodonController) { self.list = list - super.init(for: .list(id: list.id)) + super.init(for: .list(id: list.id), mastodonController: mastodonController) title = list.title } @@ -42,7 +42,7 @@ class ListTimelineViewController: TimelineTableViewController { } func presentEdit(animated: Bool) { - let editListAccountsController = EditListAccountsViewController(list: list) + let editListAccountsController = EditListAccountsViewController(list: list, mastodonController: mastodonController) editListAccountsController.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonPressed)) let navController = UINavigationController(rootViewController: editListAccountsController) present(navController, animated: animated) diff --git a/Tusker/Screens/Main/MainTabBarViewController.swift b/Tusker/Screens/Main/MainTabBarViewController.swift index 02590765..d0d01655 100644 --- a/Tusker/Screens/Main/MainTabBarViewController.swift +++ b/Tusker/Screens/Main/MainTabBarViewController.swift @@ -9,18 +9,30 @@ import UIKit class MainTabBarViewController: UITabBarController, UITabBarControllerDelegate { - + + let mastodonController: MastodonController + + init(mastodonController: MastodonController) { + self.mastodonController = mastodonController + + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override func viewDidLoad() { super.viewDidLoad() self.delegate = self viewControllers = [ - embedInNavigationController(TimelinesPageViewController()), - embedInNavigationController(NotificationsPageViewController()), - ComposeViewController(), - embedInNavigationController(ExploreViewController()), - embedInNavigationController(MyProfileTableViewController()), + embedInNavigationController(TimelinesPageViewController(mastodonController: mastodonController)), + embedInNavigationController(NotificationsPageViewController(mastodonController: mastodonController)), + ComposeViewController(mastodonController: mastodonController), + embedInNavigationController(ExploreViewController(mastodonController: mastodonController)), + embedInNavigationController(MyProfileTableViewController(mastodonController: mastodonController)), ] } @@ -41,7 +53,7 @@ class MainTabBarViewController: UITabBarController, UITabBarControllerDelegate { } func presentCompose() { - let compose = ComposeViewController() + let compose = ComposeViewController(mastodonController: mastodonController) let navigationController = embedInNavigationController(compose) navigationController.presentationController?.delegate = compose present(navigationController, animated: true) diff --git a/Tusker/Screens/Notifications/NotificationsPageViewController.swift b/Tusker/Screens/Notifications/NotificationsPageViewController.swift index 3e503e1b..ac66701a 100644 --- a/Tusker/Screens/Notifications/NotificationsPageViewController.swift +++ b/Tusker/Screens/Notifications/NotificationsPageViewController.swift @@ -13,13 +13,17 @@ class NotificationsPageViewController: SegmentedPageViewController { private let notificationsTitle = NSLocalizedString("Notifications", comment: "notifications tab title") private let mentionsTitle = NSLocalizedString("Mentions", comment: "mentions tab title") + + let mastodonController: MastodonController - init() { - let notifications = NotificationsTableViewController(allowedTypes: Pachyderm.Notification.Kind.allCases) + init(mastodonController: MastodonController) { + self.mastodonController = mastodonController + + let notifications = NotificationsTableViewController(allowedTypes: Pachyderm.Notification.Kind.allCases, mastodonController: mastodonController) notifications.title = notificationsTitle notifications.userActivity = UserActivityManager.checkNotificationsActivity() - let mentions = NotificationsTableViewController(allowedTypes: [.mention]) + let mentions = NotificationsTableViewController(allowedTypes: [.mention], mastodonController: mastodonController) mentions.title = mentionsTitle mentions.userActivity = UserActivityManager.checkMentionsActivity() diff --git a/Tusker/Screens/Notifications/NotificationsTableViewController.swift b/Tusker/Screens/Notifications/NotificationsTableViewController.swift index ae6ccf35..4bee64b2 100644 --- a/Tusker/Screens/Notifications/NotificationsTableViewController.swift +++ b/Tusker/Screens/Notifications/NotificationsTableViewController.swift @@ -16,6 +16,8 @@ class NotificationsTableViewController: EnhancedTableViewController { private let followGroupCell = "followGroupCell" private let followRequestCell = "followRequestCell" + let mastodonController: MastodonController + let excludedTypes: [Pachyderm.Notification.Kind] let groupTypes = [Notification.Kind.favourite, .reblog, .follow] @@ -30,8 +32,9 @@ class NotificationsTableViewController: EnhancedTableViewController { var newer: RequestRange? var older: RequestRange? - init(allowedTypes: [Pachyderm.Notification.Kind]) { + init(allowedTypes: [Pachyderm.Notification.Kind], mastodonController: MastodonController) { self.excludedTypes = Array(Set(Pachyderm.Notification.Kind.allCases).subtracting(allowedTypes)) + self.mastodonController = mastodonController super.init(style: .plain) @@ -57,7 +60,7 @@ class NotificationsTableViewController: EnhancedTableViewController { tableView.prefetchDataSource = self let request = Client.getNotifications(excludeTypes: excludedTypes) - MastodonController.run(request) { result in + mastodonController.run(request) { result in guard case let .success(notifications, pagination) = result else { fatalError() } let groups = NotificationGroup.createGroups(notifications: notifications, only: self.groupTypes) @@ -125,7 +128,7 @@ class NotificationsTableViewController: EnhancedTableViewController { guard let older = older else { return } let request = Client.getNotifications(excludeTypes: excludedTypes, range: older) - MastodonController.run(request) { result in + mastodonController.run(request) { result in guard case let .success(newNotifications, pagination) = result else { fatalError() } let groups = NotificationGroup.createGroups(notifications: newNotifications, only: self.groupTypes) @@ -182,7 +185,7 @@ class NotificationsTableViewController: EnhancedTableViewController { .map(Pachyderm.Notification.dismiss(id:)) .forEach { (request) in group.enter() - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in group.leave() } } @@ -197,7 +200,7 @@ class NotificationsTableViewController: EnhancedTableViewController { guard let newer = newer else { return } let request = Client.getNotifications(excludeTypes: excludedTypes, range: newer) - MastodonController.run(request) { result in + mastodonController.run(request) { result in guard case let .success(newNotifications, pagination) = result else { fatalError() } let groups = NotificationGroup.createGroups(notifications: newNotifications, only: self.groupTypes) @@ -222,6 +225,7 @@ class NotificationsTableViewController: EnhancedTableViewController { } extension NotificationsTableViewController: StatusTableViewCellDelegate { + var apiController: MastodonController { mastodonController } func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { // causes the table view to recalculate the cell heights tableView.beginUpdates() diff --git a/Tusker/Screens/Onboarding/OnboardingViewController.swift b/Tusker/Screens/Onboarding/OnboardingViewController.swift index 7df60929..21daac5e 100644 --- a/Tusker/Screens/Onboarding/OnboardingViewController.swift +++ b/Tusker/Screens/Onboarding/OnboardingViewController.swift @@ -46,8 +46,9 @@ class OnboardingViewController: UINavigationController { extension OnboardingViewController: InstanceSelectorTableViewControllerDelegate { func didSelectInstance(url: URL) { LocalData.shared.instanceURL = url - MastodonController.createClient() - MastodonController.registerApp { + let mastodonController = MastodonController.shared + mastodonController.createClient() + mastodonController.registerApp { let clientID = LocalData.shared.clientID! let callbackURL = "tusker://oauth" @@ -69,7 +70,7 @@ extension OnboardingViewController: InstanceSelectorTableViewControllerDelegate let item = components.queryItems?.first(where: { $0.name == "code" }), let authCode = item.value else { return } - MastodonController.authorize(authorizationCode: authCode) { + mastodonController.authorize(authorizationCode: authCode) { DispatchQueue.main.async { self.onboardingDelegate?.didFinishOnboarding() } diff --git a/Tusker/Screens/Profile/MyProfileTableViewController.swift b/Tusker/Screens/Profile/MyProfileTableViewController.swift index 3e58ac59..7fef8706 100644 --- a/Tusker/Screens/Profile/MyProfileTableViewController.swift +++ b/Tusker/Screens/Profile/MyProfileTableViewController.swift @@ -11,14 +11,14 @@ import SwiftUI class MyProfileTableViewController: ProfileTableViewController { - init() { - super.init(accountID: nil) + init(mastodonController: MastodonController) { + super.init(accountID: nil, mastodonController: mastodonController) title = "My Profile" tabBarItem.image = UIImage(systemName: "person.fill") - MastodonController.getOwnAccount { (account) in + mastodonController.getOwnAccount { (account) in self.accountID = account.id ImageCache.avatars.get(account.avatar, completion: { (data) in diff --git a/Tusker/Screens/Profile/ProfileTableViewController.swift b/Tusker/Screens/Profile/ProfileTableViewController.swift index 45b520e0..e6b1d4b3 100644 --- a/Tusker/Screens/Profile/ProfileTableViewController.swift +++ b/Tusker/Screens/Profile/ProfileTableViewController.swift @@ -12,6 +12,8 @@ import SafariServices class ProfileTableViewController: EnhancedTableViewController { + let mastodonController: MastodonController + var accountID: String! { didSet { if shouldLoadOnAccountIDSet { @@ -43,7 +45,9 @@ class ProfileTableViewController: EnhancedTableViewController { var shouldLoadOnAccountIDSet = false var loadingVC: LoadingViewController? = nil - init(accountID: String?) { + init(accountID: String?, mastodonController: MastodonController) { + self.mastodonController = mastodonController + self.accountID = accountID super.init(style: .plain) @@ -130,12 +134,12 @@ class ProfileTableViewController: EnhancedTableViewController { func getStatuses(for range: RequestRange = .default, onlyPinned: Bool = false, completion: @escaping Client.Callback<[Status]>) { let request = Account.getStatuses(accountID, range: range, onlyMedia: false, pinned: onlyPinned, excludeReplies: !Preferences.shared.showRepliesInProfiles) - MastodonController.run(request, completion: completion) + mastodonController.run(request, completion: completion) } func sendMessageMentioning() { guard let account = MastodonCache.account(for: accountID) else { fatalError("Missing cached account \(accountID!)") } - let vc = UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct)) + let vc = UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct, mastodonController: mastodonController)) present(vc, animated: true) } @@ -233,6 +237,8 @@ class ProfileTableViewController: EnhancedTableViewController { } extension ProfileTableViewController: StatusTableViewCellDelegate { + var apiController: MastodonController { mastodonController } + func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { // causes the table view to recalculate the cell heights tableView.beginUpdates() diff --git a/Tusker/Screens/Search/SearchResultsViewController.swift b/Tusker/Screens/Search/SearchResultsViewController.swift index ad77eed3..45e97c4b 100644 --- a/Tusker/Screens/Search/SearchResultsViewController.swift +++ b/Tusker/Screens/Search/SearchResultsViewController.swift @@ -28,6 +28,8 @@ extension SearchResultsViewControllerDelegate { class SearchResultsViewController: EnhancedTableViewController { + let mastodonController: MastodonController! + weak var exploreNavigationController: UINavigationController? weak var delegate: SearchResultsViewControllerDelegate? @@ -40,7 +42,9 @@ class SearchResultsViewController: EnhancedTableViewController { let searchSubject = PassthroughSubject() var currentQuery: String? - init() { + init(mastodonController: MastodonController) { + self.mastodonController = mastodonController + super.init(style: .grouped) title = NSLocalizedString("Search", comment: "search screen title") @@ -118,7 +122,7 @@ class SearchResultsViewController: EnhancedTableViewController { } let request = Client.search(query: query, resolve: true, limit: 10) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in guard case let .success(results, _) = response else { fatalError() } DispatchQueue.main.async { @@ -217,6 +221,7 @@ extension SearchResultsViewController: UISearchBarDelegate { } extension SearchResultsViewController: StatusTableViewCellDelegate { + var apiController: MastodonController { mastodonController } func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { tableView.beginUpdates() tableView.endUpdates() diff --git a/Tusker/Screens/Status Action Account List/StatusActionAccountListTableViewController.swift b/Tusker/Screens/Status Action Account List/StatusActionAccountListTableViewController.swift index 9ccf9234..e0d9195c 100644 --- a/Tusker/Screens/Status Action Account List/StatusActionAccountListTableViewController.swift +++ b/Tusker/Screens/Status Action Account List/StatusActionAccountListTableViewController.swift @@ -14,6 +14,8 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController { private let statusCell = "statusCell" private let accountCell = "accountCell" + let mastodonController: MastodonController + let actionType: ActionType let statusID: String var statusState: StatusState @@ -32,8 +34,11 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController { - Parameter actionType The action that this VC is for. - Parameter statusID The ID of the status to show. - Parameter accountIDs The accounts that will be shown. If `nil` is passed, a request will be performed to load the accounts. + - Parameter mastodonController The `MastodonController` instance this view controller uses. */ - init(actionType: ActionType, statusID: String, statusState: StatusState, accountIDs: [String]?) { + init(actionType: ActionType, statusID: String, statusState: StatusState, accountIDs: [String]?, mastodonController: MastodonController) { + self.mastodonController = mastodonController + self.actionType = actionType self.statusID = statusID self.statusState = statusState @@ -75,7 +80,7 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController { tableView.tableFooterView = UIActivityIndicatorView(style: .large) let request = actionType == .favorite ? Status.getFavourites(status) : Status.getReblogs(status) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in guard case let .success(accounts, _) = response else { fatalError() } MastodonCache.addAll(accounts: accounts) DispatchQueue.main.async { @@ -137,6 +142,7 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController { } extension StatusActionAccountListTableViewController: StatusTableViewCellDelegate { + var apiController: MastodonController { mastodonController } func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { // causes the table view to recalculate the cell heights tableView.beginUpdates() diff --git a/Tusker/Screens/Timeline/HashtagTimelineViewController.swift b/Tusker/Screens/Timeline/HashtagTimelineViewController.swift index 0313a11e..3dcd8787 100644 --- a/Tusker/Screens/Timeline/HashtagTimelineViewController.swift +++ b/Tusker/Screens/Timeline/HashtagTimelineViewController.swift @@ -22,10 +22,10 @@ class HashtagTimelineViewController: TimelineTableViewController { } } - init(for hashtag: Hashtag) { + init(for hashtag: Hashtag, mastodonController: MastodonController) { self.hashtag = hashtag - super.init(for: .tag(hashtag: hashtag.name)) + super.init(for: .tag(hashtag: hashtag.name), mastodonController: mastodonController) } required init?(coder aDecoder: NSCoder) { diff --git a/Tusker/Screens/Timeline/InstanceTimelineViewController.swift b/Tusker/Screens/Timeline/InstanceTimelineViewController.swift index 405c998f..b5ee418d 100644 --- a/Tusker/Screens/Timeline/InstanceTimelineViewController.swift +++ b/Tusker/Screens/Timeline/InstanceTimelineViewController.swift @@ -31,7 +31,10 @@ class InstanceTimelineViewController: TimelineTableViewController { init(for url: URL) { self.instanceURL = url - super.init(for: .instance(instanceURL: url)) + let mastodonController = MastodonController() + mastodonController.createClient(instanceURL: url) + + super.init(for: .instance(instanceURL: url), mastodonController: mastodonController) } required init?(coder aDecoder: NSCoder) { diff --git a/Tusker/Screens/Timeline/TimelineTableViewController.swift b/Tusker/Screens/Timeline/TimelineTableViewController.swift index f38cacd2..f110638f 100644 --- a/Tusker/Screens/Timeline/TimelineTableViewController.swift +++ b/Tusker/Screens/Timeline/TimelineTableViewController.swift @@ -12,6 +12,7 @@ import Pachyderm class TimelineTableViewController: EnhancedTableViewController { var timeline: Timeline! + let mastodonController: MastodonController var timelineSegments: [[(id: String, state: StatusState)]] = [] { didSet { @@ -24,8 +25,9 @@ class TimelineTableViewController: EnhancedTableViewController { var newer: RequestRange? var older: RequestRange? - init(for timeline: Timeline) { + init(for timeline: Timeline, mastodonController: MastodonController) { self.timeline = timeline + self.mastodonController = mastodonController super.init(style: .plain) @@ -56,13 +58,13 @@ class TimelineTableViewController: EnhancedTableViewController { tableView.prefetchDataSource = self - guard MastodonController.accessToken != nil else { return } + guard mastodonController.accessToken != nil else { return } loadInitialStatuses() } func loadInitialStatuses() { let request = Client.getStatuses(timeline: timeline) - MastodonController.run(request) { response in + mastodonController.run(request) { response in guard case let .success(statuses, pagination) = response else { fatalError() } MastodonCache.addAll(statuses: statuses) self.timelineSegments.insert(statuses.map { ($0.id, .unknown) }, at: 0) @@ -100,7 +102,7 @@ class TimelineTableViewController: EnhancedTableViewController { guard let older = older else { return } let request = Client.getStatuses(timeline: timeline, range: older) - MastodonController.run(request) { response in + mastodonController.run(request) { response in guard case let .success(newStatuses, pagination) = response else { fatalError() } self.older = pagination?.older MastodonCache.addAll(statuses: newStatuses) @@ -125,7 +127,7 @@ class TimelineTableViewController: EnhancedTableViewController { guard let newer = newer else { return } let request = Client.getStatuses(timeline: timeline, range: newer) - MastodonController.run(request) { response in + mastodonController.run(request) { response in guard case let .success(newStatuses, pagination) = response else { fatalError() } self.newer = pagination?.newer MastodonCache.addAll(statuses: newStatuses) @@ -146,6 +148,8 @@ class TimelineTableViewController: EnhancedTableViewController { } extension TimelineTableViewController: StatusTableViewCellDelegate { + var apiController: MastodonController { mastodonController } + func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { // causes the table view to recalculate the cell heights tableView.beginUpdates() diff --git a/Tusker/Screens/Timeline/TimelinesPageViewController.swift b/Tusker/Screens/Timeline/TimelinesPageViewController.swift index 7fd95c3a..a01e74db 100644 --- a/Tusker/Screens/Timeline/TimelinesPageViewController.swift +++ b/Tusker/Screens/Timeline/TimelinesPageViewController.swift @@ -14,14 +14,18 @@ class TimelinesPageViewController: SegmentedPageViewController { private let federatedTitle = NSLocalizedString("Federated", comment: "federated timeline tab title") private let localTitle = NSLocalizedString("Local", comment: "local timeline tab title") - init() { - let home = TimelineTableViewController(for: .home) + let mastodonController: MastodonController + + init(mastodonController: MastodonController) { + self.mastodonController = mastodonController + + let home = TimelineTableViewController(for: .home, mastodonController: mastodonController) home.title = homeTitle - let federated = TimelineTableViewController(for: .public(local: false)) + let federated = TimelineTableViewController(for: .public(local: false), mastodonController: mastodonController) federated.title = federatedTitle - let local = TimelineTableViewController(for: .public(local: true)) + let local = TimelineTableViewController(for: .public(local: true), mastodonController: mastodonController) local.title = localTitle super.init(titles: [ diff --git a/Tusker/Shortcuts/UserActivityManager.swift b/Tusker/Shortcuts/UserActivityManager.swift index b53373af..5701e1f9 100644 --- a/Tusker/Shortcuts/UserActivityManager.swift +++ b/Tusker/Shortcuts/UserActivityManager.swift @@ -15,6 +15,8 @@ class UserActivityManager { private static let encoder = PropertyListEncoder() private static let decoder = PropertyListDecoder() + private static var mastodonController: MastodonController { .shared } + private static func getMainTabBarController() -> MainTabBarViewController { return (UIApplication.shared.delegate! as! AppDelegate).window!.rootViewController as! MainTabBarViewController } @@ -42,7 +44,8 @@ class UserActivityManager { static func handleNewPost(activity: NSUserActivity) { // TODO: check not currently showing compose screen let mentioning = activity.userInfo?["mentioning"] as? String - present(UINavigationController(rootViewController: ComposeViewController(mentioningAcct: mentioning))) + let composeVC = ComposeViewController(mentioningAcct: mentioning, mastodonController: mastodonController) + present(UINavigationController(rootViewController: composeVC)) } // MARK: - Check Notifications @@ -144,7 +147,8 @@ class UserActivityManager { rootController.segmentedControl.selectedSegmentIndex = index rootController.selectPage(at: index, animated: false) default: - navigationController.pushViewController(TimelineTableViewController(for: timeline), animated: false) + let timeline = TimelineTableViewController(for: timeline, mastodonController: mastodonController) + navigationController.pushViewController(timeline, animated: false) } } @@ -182,7 +186,7 @@ class UserActivityManager { tabBarController.select(tab: .explore) if let navigationController = tabBarController.getTabController(tab: .explore) as? UINavigationController { navigationController.popToRootViewController(animated: false) - navigationController.pushViewController(BookmarksTableViewController(), animated: false) + navigationController.pushViewController(BookmarksTableViewController(mastodonController: mastodonController), animated: false) } } diff --git a/Tusker/TuskerNavigationDelegate.swift b/Tusker/TuskerNavigationDelegate.swift index a62072b2..2530ed17 100644 --- a/Tusker/TuskerNavigationDelegate.swift +++ b/Tusker/TuskerNavigationDelegate.swift @@ -12,6 +12,8 @@ import Pachyderm protocol TuskerNavigationDelegate { + var apiController: MastodonController { get } + func show(_ vc: UIViewController) func selected(account accountID: String) @@ -68,15 +70,15 @@ extension TuskerNavigationDelegate where Self: UIViewController { return } - show(ProfileTableViewController(accountID: accountID), sender: self) + show(ProfileTableViewController(accountID: accountID, mastodonController: apiController), sender: self) } func selected(mention: Mention) { - show(ProfileTableViewController(accountID: mention.id), sender: self) + show(ProfileTableViewController(accountID: mention.id, mastodonController: apiController), sender: self) } func selected(tag: Hashtag) { - show(HashtagTimelineViewController(for: tag), sender: self) + show(HashtagTimelineViewController(for: tag, mastodonController: apiController), sender: self) } func selected(url: URL) { @@ -113,7 +115,7 @@ extension TuskerNavigationDelegate where Self: UIViewController { return } - show(ConversationTableViewController(for: statusID, state: state), sender: self) + show(ConversationTableViewController(for: statusID, state: state, mastodonController: apiController), sender: self) } // protocols can't have parameter defaults, so this stub is necessary to fulfill the protocol req @@ -122,14 +124,14 @@ extension TuskerNavigationDelegate where Self: UIViewController { } func compose(mentioning: String? = nil) { - let compose = ComposeViewController( mentioningAcct: mentioning) + let compose = ComposeViewController(mentioningAcct: mentioning, mastodonController: apiController) let vc = UINavigationController(rootViewController: compose) vc.presentationController?.delegate = compose present(vc, animated: true) } func reply(to statusID: String) { - let compose = ComposeViewController(inReplyTo: statusID) + let compose = ComposeViewController(inReplyTo: statusID, mastodonController: apiController) let vc = UINavigationController(rootViewController: compose) vc.presentationController?.delegate = compose present(vc, animated: true) @@ -200,7 +202,7 @@ extension TuskerNavigationDelegate where Self: UIViewController { customActivites.insert(bookmarked ? UnbookmarkStatusActivity() : BookmarkStatusActivity(), at: 0) } - if status.account == MastodonController.account, + if status.account == apiController.account, let pinned = status.pinned { customActivites.insert(pinned ? UnpinStatusActivity() : PinStatusActivity(), at: 1) } @@ -228,13 +230,13 @@ extension TuskerNavigationDelegate where Self: UIViewController { } func showFollowedByList(accountIDs: [String]) { - let vc = AccountListTableViewController(accountIDs: accountIDs) + let vc = AccountListTableViewController(accountIDs: accountIDs, mastodonController: apiController) vc.title = NSLocalizedString("Followed By", comment: "followed by accounts list title") show(vc, sender: self) } func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, statusState state: StatusState, accountIDs: [String]?) -> StatusActionAccountListTableViewController { - return StatusActionAccountListTableViewController(actionType: action, statusID: statusID, statusState: state, accountIDs: accountIDs) + return StatusActionAccountListTableViewController(actionType: action, statusID: statusID, statusState: state, accountIDs: accountIDs, mastodonController: apiController) } } diff --git a/Tusker/Views/Account Cell/AccountTableViewCell.swift b/Tusker/Views/Account Cell/AccountTableViewCell.swift index e933d335..cd82f5f4 100644 --- a/Tusker/Views/Account Cell/AccountTableViewCell.swift +++ b/Tusker/Views/Account Cell/AccountTableViewCell.swift @@ -11,6 +11,7 @@ import UIKit class AccountTableViewCell: UITableViewCell { var delegate: TuskerNavigationDelegate? + var mastodonController: MastodonController? { delegate?.apiController } @IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var displayNameLabel: UILabel! @@ -68,6 +69,11 @@ extension AccountTableViewCell: MenuPreviewProvider { var navigationDelegate: TuskerNavigationDelegate? { return delegate } func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { - return (content: { ProfileTableViewController(accountID: self.accountID) }, actions: { self.actionsForProfile(accountID: self.accountID) }) + guard let mastodonController = mastodonController else { return nil } + return (content: { + ProfileTableViewController(accountID: self.accountID, mastodonController: mastodonController) + }, actions: { + self.actionsForProfile(accountID: self.accountID) + }) } } diff --git a/Tusker/Views/ContentLabel.swift b/Tusker/Views/ContentLabel.swift index 1cdced23..b53e2d02 100644 --- a/Tusker/Views/ContentLabel.swift +++ b/Tusker/Views/ContentLabel.swift @@ -178,13 +178,15 @@ class ContentLabel: LinkLabel { func getViewController(forLink url: URL, inRange range: NSRange) -> UIViewController { let text = (self.text! as NSString).substring(with: range) - if let mention = getMention(for: url, text: text) { - return ProfileTableViewController(accountID: mention.id) - } else if let tag = getHashtag(for: url, text: text) { - return HashtagTimelineViewController(for: tag) - } else { - return SFSafariViewController(url: url) + if let navigationDelegate = navigationDelegate { + if let mention = getMention(for: url, text: text) { + return ProfileTableViewController(accountID: mention.id, mastodonController: navigationDelegate.apiController) + } else if let tag = getHashtag(for: url, text: text) { + return HashtagTimelineViewController(for: tag, mastodonController: navigationDelegate.apiController) + } + } + return SFSafariViewController(url: url) } func getViewController(forLinkAt point: CGPoint) -> UIViewController? { diff --git a/Tusker/Views/Hashtag Cell/HashtagTableViewCell.swift b/Tusker/Views/Hashtag Cell/HashtagTableViewCell.swift index 387c7652..bd364d16 100644 --- a/Tusker/Views/Hashtag Cell/HashtagTableViewCell.swift +++ b/Tusker/Views/Hashtag Cell/HashtagTableViewCell.swift @@ -12,7 +12,7 @@ import Pachyderm class HashtagTableViewCell: UITableViewCell { var delegate: TuskerNavigationDelegate? - + @IBOutlet weak var hashtagLabel: UILabel! var hashtag: Hashtag! diff --git a/Tusker/Views/Notifications/FollowNotificationGroupTableViewCell.swift b/Tusker/Views/Notifications/FollowNotificationGroupTableViewCell.swift index cafb5c13..f45025dc 100644 --- a/Tusker/Views/Notifications/FollowNotificationGroupTableViewCell.swift +++ b/Tusker/Views/Notifications/FollowNotificationGroupTableViewCell.swift @@ -12,6 +12,7 @@ import Pachyderm class FollowNotificationGroupTableViewCell: UITableViewCell { var delegate: TuskerNavigationDelegate? + var mastodonController: MastodonController? { delegate?.apiController } @IBOutlet weak var avatarStackView: UIStackView! @IBOutlet weak var timestampLabel: UILabel! @@ -133,12 +134,13 @@ extension FollowNotificationGroupTableViewCell: MenuPreviewProvider { var navigationDelegate: TuskerNavigationDelegate? { return delegate } func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { + guard let mastodonController = mastodonController else { return nil } return (content: { let accountIDs = self.group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account.id } if accountIDs.count == 1 { - return ProfileTableViewController(accountID: accountIDs.first!) + return ProfileTableViewController(accountID: accountIDs.first!, mastodonController: mastodonController) } else { - return AccountListTableViewController(accountIDs: accountIDs) + return AccountListTableViewController(accountIDs: accountIDs, mastodonController: mastodonController) } }, actions: { return [] diff --git a/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.swift b/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.swift index 8a5ca23f..b8865507 100644 --- a/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.swift +++ b/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.swift @@ -12,6 +12,7 @@ import Pachyderm class FollowRequestNotificationTableViewCell: UITableViewCell { var delegate: TuskerNavigationDelegate? + var mastodonController: MastodonController? { delegate?.apiController } @IBOutlet weak var stackView: UIStackView! @IBOutlet weak var avatarImageView: UIImageView! @@ -89,7 +90,7 @@ class FollowRequestNotificationTableViewCell: UITableViewCell { @IBAction func rejectButtonPressed() { let request = Account.rejectFollowRequest(account) - MastodonController.run(request) { (response) in + mastodonController!.run(request) { (response) in guard case let .success(relationship, _) = response else { fatalError() } MastodonCache.add(relationship: relationship) DispatchQueue.main.async { @@ -106,7 +107,7 @@ class FollowRequestNotificationTableViewCell: UITableViewCell { @IBAction func acceptButtonPressed() { let request = Account.authorizeFollowRequest(account) - MastodonController.run(request) { (response) in + mastodonController!.run(request) { (response) in guard case let .success(relationship, _) = response else { fatalError() } MastodonCache.add(relationship: relationship) DispatchQueue.main.async { @@ -133,8 +134,9 @@ extension FollowRequestNotificationTableViewCell: MenuPreviewProvider { var navigationDelegate: TuskerNavigationDelegate? { return delegate } func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { + guard let mastodonController = mastodonController else { return nil } return (content: { - return ProfileTableViewController(accountID: self.account.id) + return ProfileTableViewController(accountID: self.account.id, mastodonController: mastodonController) }, actions: { return [] }) diff --git a/Tusker/Views/Profile Header/ProfileHeaderTableViewCell.swift b/Tusker/Views/Profile Header/ProfileHeaderTableViewCell.swift index a3517792..c948f666 100644 --- a/Tusker/Views/Profile Header/ProfileHeaderTableViewCell.swift +++ b/Tusker/Views/Profile Header/ProfileHeaderTableViewCell.swift @@ -16,6 +16,7 @@ protocol ProfileHeaderTableViewCellDelegate: TuskerNavigationDelegate { class ProfileHeaderTableViewCell: UITableViewCell { var delegate: ProfileHeaderTableViewCellDelegate? + var mastodonController: MastodonController? { delegate?.apiController } @IBOutlet weak var headerImageView: UIImageView! @IBOutlet weak var avatarContainerView: UIView! @@ -82,7 +83,7 @@ class ProfileHeaderTableViewCell: UITableViewCell { noteLabel.setTextFromHtml(account.note) noteLabel.setEmojis(account.emojis) - if accountID != MastodonController.account.id { + if accountID != mastodonController!.account.id { // don't show relationship label for the user's own account if let relationship = MastodonCache.relationship(for: accountID) { followsYouLabel.isHidden = !relationship.followedBy diff --git a/Tusker/Views/Status/BaseStatusTableViewCell.swift b/Tusker/Views/Status/BaseStatusTableViewCell.swift index f6b062e1..f9b985c5 100644 --- a/Tusker/Views/Status/BaseStatusTableViewCell.swift +++ b/Tusker/Views/Status/BaseStatusTableViewCell.swift @@ -15,11 +15,13 @@ protocol StatusTableViewCellDelegate: TuskerNavigationDelegate { } class BaseStatusTableViewCell: UITableViewCell { + var delegate: StatusTableViewCellDelegate? { didSet { contentLabel.navigationDelegate = delegate } } + var mastodonController: MastodonController? { delegate?.apiController } @IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var displayNameLabel: UILabel! @@ -247,7 +249,7 @@ class BaseStatusTableViewCell: UITableViewCell { let realStatus: Status = status.reblog ?? status let request = (favorited ? Status.favourite : Status.unfavourite)(realStatus) - MastodonController.run(request) { response in + mastodonController!.run(request) { response in DispatchQueue.main.async { if case let .success(newStatus, _) = response { self.favorited = newStatus.favourited ?? false @@ -272,7 +274,7 @@ class BaseStatusTableViewCell: UITableViewCell { let realStatus: Status = status.reblog ?? status let request = (reblogged ? Status.reblog : Status.unreblog)(realStatus) - MastodonController.run(request) { response in + mastodonController!.run(request) { response in DispatchQueue.main.async { if case let .success(newStatus, _) = response { self.reblogged = newStatus.reblogged ?? false @@ -313,8 +315,13 @@ extension BaseStatusTableViewCell: MenuPreviewProvider { var navigationDelegate: TuskerNavigationDelegate? { return delegate } func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { + guard let mastodonController = mastodonController else { return nil } if avatarImageView.frame.contains(location) { - return (content: { ProfileTableViewController(accountID: self.accountID)}, actions: { self.actionsForProfile(accountID: self.accountID) }) + return (content: { + ProfileTableViewController(accountID: self.accountID, mastodonController: mastodonController) + }, actions: { + self.actionsForProfile(accountID: self.accountID) + }) } else if attachmentsView.frame.contains(location) { let attachmentsViewLocation = attachmentsView.convert(location, from: self) if let attachmentView = attachmentsView.attachmentViews.allObjects.first(where: { $0.frame.contains(attachmentsViewLocation) }), diff --git a/Tusker/Views/Status/TimelineStatusTableViewCell.swift b/Tusker/Views/Status/TimelineStatusTableViewCell.swift index a80e4254..a42ddeb2 100644 --- a/Tusker/Views/Status/TimelineStatusTableViewCell.swift +++ b/Tusker/Views/Status/TimelineStatusTableViewCell.swift @@ -125,8 +125,9 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell { } override func getStatusCellPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> BaseStatusTableViewCell.PreviewProviders? { + guard let mastodonController = mastodonController else { return nil } return ( - content: { ConversationTableViewController(for: self.statusID, state: self.statusState.copy()) }, + content: { ConversationTableViewController(for: self.statusID, state: self.statusState.copy(), mastodonController: mastodonController) }, actions: { self.actionsForStatus(statusID: self.statusID) } ) } @@ -142,6 +143,7 @@ extension TimelineStatusTableViewCell: SelectableTableViewCell { extension TimelineStatusTableViewCell: TableViewSwipeActionProvider { func leadingSwipeActionsConfiguration() -> UISwipeActionsConfiguration? { + guard let mastodonController = mastodonController else { return nil } guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") } let favoriteTitle: String @@ -158,7 +160,7 @@ extension TimelineStatusTableViewCell: TableViewSwipeActionProvider { favoriteColor = UIColor(displayP3Red: 1, green: 204/255, blue: 0, alpha: 1) } let favorite = UIContextualAction(style: .normal, title: favoriteTitle) { (action, view, completion) in - MastodonController.run(favoriteRequest, completion: { response in + mastodonController.run(favoriteRequest, completion: { response in DispatchQueue.main.async { guard case let .success(status, _) = response else { completion(false) @@ -185,7 +187,7 @@ extension TimelineStatusTableViewCell: TableViewSwipeActionProvider { reblogColor = tintColor } let reblog = UIContextualAction(style: .normal, title: reblogTitle) { (action, view, completion) in - MastodonController.run(reblogRequest, completion: { response in + mastodonController.run(reblogRequest, completion: { response in DispatchQueue.main.async { guard case let .success(status, _) = response else { completion(false) diff --git a/Tusker/XCallbackURL/XCBActions.swift b/Tusker/XCallbackURL/XCBActions.swift index d90d1920..ead66b93 100644 --- a/Tusker/XCallbackURL/XCBActions.swift +++ b/Tusker/XCallbackURL/XCBActions.swift @@ -13,6 +13,8 @@ import SwiftSoup struct XCBActions { // MARK: - Utils + private static var mastodonController: MastodonController { .shared } + private static func getMainTabBarController() -> MainTabBarViewController { return (UIApplication.shared.delegate as! AppDelegate).window!.rootViewController as! MainTabBarViewController } @@ -42,7 +44,7 @@ struct XCBActions { } } else if let searchQuery = request.arguments["statusURL"] { let request = Client.search(query: searchQuery) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(results, _) = response, let status = results.statuses.first { MastodonCache.add(status: status) @@ -73,7 +75,7 @@ struct XCBActions { } } else if let searchQuery = request.arguments["accountURL"] { let request = Client.search(query: searchQuery) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(results, _) = response { if let account = results.accounts.first { MastodonCache.add(account: account) @@ -91,7 +93,7 @@ struct XCBActions { } } else if let acct = request.arguments["acct"] { let request = Client.searchForAccount(query: acct) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(accounts, _) = response { if let account = accounts.first { MastodonCache.add(account: account) @@ -118,7 +120,7 @@ struct XCBActions { static func showStatus(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { getStatus(from: request, session: session) { (status) in DispatchQueue.main.async { - let vc = ConversationTableViewController(for: status.id) + let vc = ConversationTableViewController(for: status.id, mastodonController: mastodonController) show(vc) } } @@ -132,14 +134,14 @@ struct XCBActions { var status = "" if let mentioning = mentioning { status += mentioning } if let text = text { status += text } - guard CharacterCounter.count(text: status) <= MastodonController.instance.maxStatusCharacters ?? 500 else { + guard CharacterCounter.count(text: status) <= mastodonController.instance.maxStatusCharacters ?? 500 else { session.complete(with: .error, additionalData: [ - "error": "Too many characters. Instance maximum is \(MastodonController.instance.maxStatusCharacters ?? 500)" + "error": "Too many characters. Instance maximum is \(mastodonController.instance.maxStatusCharacters ?? 500)" ]) return } let request = Client.createStatus(text: status, visibility: Preferences.shared.defaultPostVisibility) - MastodonController.run(request) { response in + mastodonController.run(request) { response in if case let .success(status, _) = response { session.complete(with: .success, additionalData: [ "statusURL": status.url?.absoluteString, @@ -152,7 +154,7 @@ struct XCBActions { } } } else { - let compose = ComposeViewController(mentioningAcct: mentioning, text: text) + let compose = ComposeViewController(mentioningAcct: mentioning, text: text, mastodonController: mastodonController) compose.xcbSession = session let vc = UINavigationController(rootViewController: compose) present(vc) @@ -199,7 +201,7 @@ struct XCBActions { static func statusAction(request: @escaping (Status) -> Request, alertTitle: String, _ url: XCBRequest, _ session: XCBSession, _ silent: Bool?) { func performAction(status: Status, completion: ((Status) -> Void)?) { - MastodonController.run(request(status)) { (response) in + mastodonController.run(request(status)) { (response) in if case let .success(status, _) = response { MastodonCache.add(status: status) completion?(status) @@ -219,7 +221,7 @@ struct XCBActions { if silent ?? false { performAction(status: status, completion: nil) } else { - let vc = ConversationTableViewController(for: status.id) + let vc = ConversationTableViewController(for: status.id, mastodonController: mastodonController) DispatchQueue.main.async { show(vc) } @@ -247,7 +249,7 @@ struct XCBActions { static func showAccount(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { getAccount(from: request, session: session) { (account) in DispatchQueue.main.async { - let vc = ProfileTableViewController(accountID: account.id) + let vc = ProfileTableViewController(accountID: account.id, mastodonController: mastodonController) show(vc) } } @@ -269,7 +271,7 @@ struct XCBActions { } static func getCurrentUser(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { - let account = MastodonController.account! + let account = mastodonController.account! session.complete(with: .success, additionalData: [ "username": account.acct, "displayName": account.displayName, @@ -285,7 +287,7 @@ struct XCBActions { static func followUser(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { func performAction(_ account: Account) { let request = Account.follow(account.id) - MastodonController.run(request) { (response) in + mastodonController.run(request) { (response) in if case let .success(relationship, _) = response { MastodonCache.add(relationship: relationship) session.complete(with: .success, additionalData: [ @@ -303,7 +305,7 @@ struct XCBActions { if silent ?? false { performAction(account) } else { - let vc = ProfileTableViewController(accountID: account.id) + let vc = ProfileTableViewController(accountID: account.id, mastodonController: mastodonController) DispatchQueue.main.async { show(vc) }