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 9dd15d8ba4..44d85d1e69 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 e12e223390..1b91a98ecc 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 f0dc74f20b..7beb3523ca 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 0238b0abb5..ea67c0b02d 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 94daf75653..344387d782 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 0000000000..32275951e6 --- /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 df1fcfc9cf..8c64f007c0 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 f73d04749f..3714a453a4 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 715b0a6e3d..3469b78922 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 e88a3549be..be22c5e130 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 134e852d21..cbb717cbc6 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 68e6c4a830..6f7521aa9b 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 6c841c494e..a916d77734 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 70b5482d57..1ac5eddf57 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 8635a01745..36fe72e25c 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 142213af17..a4370c0501 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 6dbabc22d5..07a6816971 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 92410f587f..31bbc06147 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 a7f6fc120c..c278c2b42e 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 7484d1dd06..796c58f409 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 664d65eed9..bf8dbac3f1 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 0259076567..d0d01655d7 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 3e503e1b2d..ac66701a87 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 ae6ccf3541..4bee64b26a 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 7df609294e..21daac5eb9 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 3e58ac5934..7fef87064a 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 45b520e035..e6b1d4b36b 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 ad77eed37e..45e97c4bf2 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 9ccf923460..e0d9195cea 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 0313a11e74..3dcd8787c7 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 405c998fad..b5ee418d31 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 f38cacd2af..f110638f6e 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 7fd95c3a46..a01e74dbe9 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 b53373afc3..5701e1f9c4 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 a62072b2bc..2530ed1709 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 e933d33551..cd82f5f422 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 1cdced2372..b53e2d0293 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 387c7652df..bd364d1668 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 cafb5c134f..f45025dcd5 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 8a5ca23f64..b8865507ac 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 a3517792ed..c948f666de 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 f6b062e19a..f9b985c52b 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 a80e425476..a42ddeb24a 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 d90d1920aa..ead66b9371 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) }