forked from shadowfacts/Tusker
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
This commit is contained in:
parent
a18bcac8b8
commit
2bdcb9b7f8
|
@ -118,6 +118,7 @@
|
||||||
D64BC18A23C16487000D0238 /* UnpinStatusActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18923C16487000D0238 /* UnpinStatusActivity.swift */; };
|
D64BC18A23C16487000D0238 /* UnpinStatusActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18923C16487000D0238 /* UnpinStatusActivity.swift */; };
|
||||||
D64BC18F23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */; };
|
D64BC18F23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */; };
|
||||||
D64BC19023C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */; };
|
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 */; };
|
D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; };
|
||||||
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; };
|
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; };
|
||||||
D64F80E2215875CC00BEF393 /* XCBActionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64F80E1215875CC00BEF393 /* XCBActionType.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 = "<group>"; };
|
D64BC18923C16487000D0238 /* UnpinStatusActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnpinStatusActivity.swift; sourceTree = "<group>"; };
|
||||||
D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowRequestNotificationTableViewCell.swift; sourceTree = "<group>"; };
|
D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowRequestNotificationTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FollowRequestNotificationTableViewCell.xib; sourceTree = "<group>"; };
|
D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FollowRequestNotificationTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
|
D64BC19123C271D9000D0238 /* MastodonActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonActivity.swift; sourceTree = "<group>"; };
|
||||||
D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = "<group>"; };
|
D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = "<group>"; };
|
||||||
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; };
|
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; };
|
||||||
D64F80E1215875CC00BEF393 /* XCBActionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBActionType.swift; sourceTree = "<group>"; };
|
D64F80E1215875CC00BEF393 /* XCBActionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBActionType.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1056,6 +1058,7 @@
|
||||||
children = (
|
children = (
|
||||||
D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */,
|
D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */,
|
||||||
D6AEBB422321685E00E5038B /* OpenInSafariActivity.swift */,
|
D6AEBB422321685E00E5038B /* OpenInSafariActivity.swift */,
|
||||||
|
D64BC19123C271D9000D0238 /* MastodonActivity.swift */,
|
||||||
D6AEBB4623216B0C00E5038B /* Account Activities */,
|
D6AEBB4623216B0C00E5038B /* Account Activities */,
|
||||||
D627943323A5523800D38C68 /* Status Activities */,
|
D627943323A5523800D38C68 /* Status Activities */,
|
||||||
);
|
);
|
||||||
|
@ -1670,6 +1673,7 @@
|
||||||
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */,
|
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */,
|
||||||
D6B053A223BD2C0600A066FA /* AssetPickerViewController.swift in Sources */,
|
D6B053A223BD2C0600A066FA /* AssetPickerViewController.swift in Sources */,
|
||||||
D627944A23A6AD6100D38C68 /* BookmarksTableViewController.swift in Sources */,
|
D627944A23A6AD6100D38C68 /* BookmarksTableViewController.swift in Sources */,
|
||||||
|
D64BC19223C271D9000D0238 /* MastodonActivity.swift in Sources */,
|
||||||
D6945C3A23AC75E2005C403C /* FindInstanceViewController.swift in Sources */,
|
D6945C3A23AC75E2005C403C /* FindInstanceViewController.swift in Sources */,
|
||||||
D6AEBB4523216AF800E5038B /* FollowAccountActivity.swift in Sources */,
|
D6AEBB4523216AF800E5038B /* FollowAccountActivity.swift in Sources */,
|
||||||
D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */,
|
D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import Pachyderm
|
import Pachyderm
|
||||||
|
|
||||||
class AccountActivity: UIActivity {
|
class AccountActivity: MastodonActivity {
|
||||||
|
|
||||||
override class var activityCategory: UIActivity.Category {
|
override class var activityCategory: UIActivity.Category {
|
||||||
return .action
|
return .action
|
||||||
|
|
|
@ -28,7 +28,7 @@ class FollowAccountActivity: AccountActivity {
|
||||||
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
|
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
|
||||||
|
|
||||||
let request = Account.follow(account.id)
|
let request = Account.follow(account.id)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(relationship, _) = response {
|
if case let .success(relationship, _) = response {
|
||||||
MastodonCache.add(relationship: relationship)
|
MastodonCache.add(relationship: relationship)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -28,7 +28,7 @@ class SendMessageActivity: AccountActivity {
|
||||||
override var activityViewController: UIViewController? {
|
override var activityViewController: UIViewController? {
|
||||||
guard let account = account else { return nil }
|
guard let account = account else { return nil }
|
||||||
|
|
||||||
return UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct))
|
return UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct, mastodonController: mastodonController))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ class UnfollowAccountActivity: AccountActivity {
|
||||||
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
|
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
|
||||||
|
|
||||||
let request = Account.unfollow(account.id)
|
let request = Account.unfollow(account.id)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(relationship, _) = response {
|
if case let .success(relationship, _) = response {
|
||||||
MastodonCache.add(relationship: relationship)
|
MastodonCache.add(relationship: relationship)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ class BookmarkStatusActivity: StatusActivity {
|
||||||
guard let status = status else { return }
|
guard let status = status else { return }
|
||||||
|
|
||||||
let request = Status.bookmark(status)
|
let request = Status.bookmark(status)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(status, _) = response {
|
if case let .success(status, _) = response {
|
||||||
MastodonCache.add(status: status)
|
MastodonCache.add(status: status)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -26,7 +26,7 @@ class PinStatusActivity: StatusActivity {
|
||||||
guard let status = status else { return }
|
guard let status = status else { return }
|
||||||
|
|
||||||
let request = Status.pin(status)
|
let request = Status.pin(status)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(status, _) = response {
|
if case let .success(status, _) = response {
|
||||||
MastodonCache.add(status: status)
|
MastodonCache.add(status: status)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import Pachyderm
|
import Pachyderm
|
||||||
|
|
||||||
class StatusActivity: UIActivity {
|
class StatusActivity: MastodonActivity {
|
||||||
|
|
||||||
override class var activityCategory: UIActivity.Category {
|
override class var activityCategory: UIActivity.Category {
|
||||||
return .action
|
return .action
|
||||||
|
|
|
@ -27,7 +27,7 @@ class UnbookmarkStatusActivity: StatusActivity {
|
||||||
guard let status = status else { return }
|
guard let status = status else { return }
|
||||||
|
|
||||||
let request = Status.unbookmark(status)
|
let request = Status.unbookmark(status)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(status, _) = response {
|
if case let .success(status, _) = response {
|
||||||
MastodonCache.add(status: status)
|
MastodonCache.add(status: status)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -26,7 +26,7 @@ class UnpinStatusActivity: StatusActivity {
|
||||||
guard let status = status else { return }
|
guard let status = status else { return }
|
||||||
|
|
||||||
let request = Status.unpin(status)
|
let request = Status.unpin(status)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(status, _) = response {
|
if case let .success(status, _) = response {
|
||||||
MastodonCache.add(status: status)
|
MastodonCache.add(status: status)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -12,6 +12,8 @@ import UIKit
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
|
||||||
|
let mastodonController = MastodonController.shared
|
||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
AppShortcutItem.createItems(for: application)
|
AppShortcutItem.createItems(for: application)
|
||||||
|
@ -95,11 +97,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showAppUI() {
|
func showAppUI() {
|
||||||
MastodonController.createClient()
|
mastodonController.createClient()
|
||||||
MastodonController.getOwnAccount()
|
mastodonController.getOwnAccount()
|
||||||
MastodonController.getOwnInstance()
|
mastodonController.getOwnInstance()
|
||||||
|
|
||||||
let tabBarController = MainTabBarViewController()
|
let tabBarController = MainTabBarViewController(mastodonController: mastodonController)
|
||||||
window!.rootViewController = tabBarController
|
window!.rootViewController = tabBarController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,32 +11,33 @@ import Pachyderm
|
||||||
|
|
||||||
class MastodonController {
|
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!
|
private var client: Client!
|
||||||
static var instance: Instance!
|
|
||||||
|
|
||||||
static var accessToken: String? {
|
var account: Account!
|
||||||
|
var instance: Instance!
|
||||||
|
|
||||||
|
var accessToken: String? {
|
||||||
client?.accessToken
|
client?.accessToken
|
||||||
}
|
}
|
||||||
|
|
||||||
private init() {}
|
func createClient(instanceURL: URL = LocalData.shared.instanceURL!) {
|
||||||
|
client = Client(baseURL: instanceURL)
|
||||||
static func createClient() {
|
|
||||||
guard let url = LocalData.shared.instanceURL else { fatalError("Can't connect without instance URL") }
|
|
||||||
|
|
||||||
client = Client(baseURL: url)
|
if instanceURL == LocalData.shared.instanceURL {
|
||||||
|
client.clientID = LocalData.shared.clientID
|
||||||
client.clientID = LocalData.shared.clientID
|
client.clientSecret = LocalData.shared.clientSecret
|
||||||
client.clientSecret = LocalData.shared.clientSecret
|
client.accessToken = LocalData.shared.accessToken
|
||||||
client.accessToken = LocalData.shared.accessToken
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func run<Result>(_ request: Request<Result>, completion: @escaping Client.Callback<Result>) {
|
func run<Result>(_ request: Request<Result>, completion: @escaping Client.Callback<Result>) {
|
||||||
client.run(request, completion: completion)
|
client.run(request, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func registerApp(completion: @escaping () -> Void) {
|
func registerApp(completion: @escaping () -> Void) {
|
||||||
guard LocalData.shared.clientID == nil,
|
guard LocalData.shared.clientID == nil,
|
||||||
LocalData.shared.clientSecret == nil else {
|
LocalData.shared.clientSecret == nil else {
|
||||||
completion()
|
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
|
client.getAccessToken(authorizationCode: authorizationCode, redirectURI: "tusker://oauth") { response in
|
||||||
guard case let .success(settings, _) = response else { fatalError() }
|
guard case let .success(settings, _) = response else { fatalError() }
|
||||||
LocalData.shared.accessToken = settings.accessToken
|
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 {
|
if account != nil {
|
||||||
completion?(account)
|
completion?(account)
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,7 +74,7 @@ class MastodonController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func getOwnInstance() {
|
func getOwnInstance() {
|
||||||
let request = Client.getInstance()
|
let request = Client.getInstance()
|
||||||
run(request) { (response) in
|
run(request) { (response) in
|
||||||
guard case let .success(instance, _) = response else { fatalError() }
|
guard case let .success(instance, _) = response else { fatalError() }
|
||||||
|
|
|
@ -20,6 +20,8 @@ class MastodonCache {
|
||||||
static let statusSubject = PassthroughSubject<Status, Never>()
|
static let statusSubject = PassthroughSubject<Status, Never>()
|
||||||
static let accountSubject = PassthroughSubject<Account, Never>()
|
static let accountSubject = PassthroughSubject<Account, Never>()
|
||||||
|
|
||||||
|
static var mastodonController: MastodonController { .shared }
|
||||||
|
|
||||||
// MARK: - Statuses
|
// MARK: - Statuses
|
||||||
static func status(for id: String) -> Status? {
|
static func status(for id: String) -> Status? {
|
||||||
return statuses[id]
|
return statuses[id]
|
||||||
|
@ -38,7 +40,7 @@ class MastodonCache {
|
||||||
|
|
||||||
static func status(for id: String, completion: @escaping (Status?) -> Void) {
|
static func status(for id: String, completion: @escaping (Status?) -> Void) {
|
||||||
let request = Client.getStatus(id: id)
|
let request = Client.getStatus(id: id)
|
||||||
MastodonController.run(request) { response in
|
mastodonController.run(request) { response in
|
||||||
guard case let .success(status, _) = response else {
|
guard case let .success(status, _) = response else {
|
||||||
completion(nil)
|
completion(nil)
|
||||||
return
|
return
|
||||||
|
@ -68,7 +70,7 @@ class MastodonCache {
|
||||||
|
|
||||||
static func account(for id: String, completion: @escaping (Account?) -> Void) {
|
static func account(for id: String, completion: @escaping (Account?) -> Void) {
|
||||||
let request = Client.getAccount(id: id)
|
let request = Client.getAccount(id: id)
|
||||||
MastodonController.run(request) { response in
|
mastodonController.run(request) { response in
|
||||||
guard case let .success(account, _) = response else {
|
guard case let .success(account, _) = response else {
|
||||||
completion(nil)
|
completion(nil)
|
||||||
return
|
return
|
||||||
|
@ -97,7 +99,7 @@ class MastodonCache {
|
||||||
|
|
||||||
static func relationship(for id: String, completion: @escaping (Relationship?) -> Void) {
|
static func relationship(for id: String, completion: @escaping (Relationship?) -> Void) {
|
||||||
let request = Client.getRelationships(accounts: [id])
|
let request = Client.getRelationships(accounts: [id])
|
||||||
MastodonController.run(request) { response in
|
mastodonController.run(request) { response in
|
||||||
guard case let .success(relationships, _) = response,
|
guard case let .success(relationships, _) = response,
|
||||||
let relationship = relationships.first else {
|
let relationship = relationships.first else {
|
||||||
completion(nil)
|
completion(nil)
|
||||||
|
|
|
@ -12,10 +12,13 @@ class AccountListTableViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
private let accountCell = "accountCell"
|
private let accountCell = "accountCell"
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
let accountIDs: [String]
|
let accountIDs: [String]
|
||||||
|
|
||||||
init(accountIDs: [String]) {
|
init(accountIDs: [String], mastodonController: MastodonController) {
|
||||||
self.accountIDs = accountIDs
|
self.accountIDs = accountIDs
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
super.init(style: .grouped)
|
super.init(style: .grouped)
|
||||||
}
|
}
|
||||||
|
@ -58,4 +61,6 @@ class AccountListTableViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AccountListTableViewController: TuskerNavigationDelegate {}
|
extension AccountListTableViewController: TuskerNavigationDelegate {
|
||||||
|
var apiController: MastodonController { mastodonController }
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ class BookmarksTableViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
private let statusCell = "statusCell"
|
private let statusCell = "statusCell"
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
var statuses: [(id: String, state: StatusState)] = [] {
|
var statuses: [(id: String, state: StatusState)] = [] {
|
||||||
didSet {
|
didSet {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
@ -24,7 +26,9 @@ class BookmarksTableViewController: EnhancedTableViewController {
|
||||||
var newer: RequestRange?
|
var newer: RequestRange?
|
||||||
var older: RequestRange?
|
var older: RequestRange?
|
||||||
|
|
||||||
init() {
|
init(mastodonController: MastodonController) {
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
super.init(style: .plain)
|
super.init(style: .plain)
|
||||||
|
|
||||||
title = NSLocalizedString("Bookmarks", comment: "bookmarks screen title")
|
title = NSLocalizedString("Bookmarks", comment: "bookmarks screen title")
|
||||||
|
@ -45,7 +49,7 @@ class BookmarksTableViewController: EnhancedTableViewController {
|
||||||
tableView.prefetchDataSource = self
|
tableView.prefetchDataSource = self
|
||||||
|
|
||||||
let request = Client.getBookmarks()
|
let request = Client.getBookmarks()
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
guard case let .success(statuses, pagination) = response else { fatalError() }
|
guard case let .success(statuses, pagination) = response else { fatalError() }
|
||||||
MastodonCache.addAll(statuses: statuses)
|
MastodonCache.addAll(statuses: statuses)
|
||||||
self.statuses.append(contentsOf: statuses.map { ($0.id, .unknown) })
|
self.statuses.append(contentsOf: statuses.map { ($0.id, .unknown) })
|
||||||
|
@ -82,7 +86,7 @@ class BookmarksTableViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = Client.getBookmarks(range: older)
|
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() }
|
guard case let .success(newStatuses, pagination) = response else { fatalError() }
|
||||||
self.older = pagination?.older
|
self.older = pagination?.older
|
||||||
MastodonCache.addAll(statuses: newStatuses)
|
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 unbookmarkAction = UIContextualAction(style: .destructive, title: NSLocalizedString("Unbookmark", comment: "unbookmark action title")) { (action, view, completion) in
|
||||||
let request = Status.unbookmark(status)
|
let request = Status.unbookmark(status)
|
||||||
MastodonController.run(request) { (response) in
|
self.mastodonController.run(request) { (response) in
|
||||||
guard case let .success(newStatus, _) = response else { fatalError() }
|
guard case let .success(newStatus, _) = response else { fatalError() }
|
||||||
MastodonCache.add(status: newStatus)
|
MastodonCache.add(status: newStatus)
|
||||||
self.statuses.remove(at: indexPath.row)
|
self.statuses.remove(at: indexPath.row)
|
||||||
|
@ -131,7 +135,7 @@ class BookmarksTableViewController: EnhancedTableViewController {
|
||||||
return [
|
return [
|
||||||
UIAction(title: NSLocalizedString("Unbookmark", comment: "unbookmark action title"), image: UIImage(systemName: "bookmark.fill"), identifier: .init("unbookmark"), discoverabilityTitle: nil, attributes: [], state: .off, handler: { (_) in
|
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)
|
let request = Status.unbookmark(status)
|
||||||
MastodonController.run(request) { (response) in
|
self.mastodonController.run(request) { (response) in
|
||||||
guard case let .success(newStatus, _) = response else { fatalError() }
|
guard case let .success(newStatus, _) = response else { fatalError() }
|
||||||
MastodonCache.add(status: newStatus)
|
MastodonCache.add(status: newStatus)
|
||||||
self.statuses.remove(at: indexPath.row)
|
self.statuses.remove(at: indexPath.row)
|
||||||
|
@ -143,6 +147,8 @@ class BookmarksTableViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension BookmarksTableViewController: StatusTableViewCellDelegate {
|
extension BookmarksTableViewController: StatusTableViewCellDelegate {
|
||||||
|
var apiController: MastodonController { mastodonController }
|
||||||
|
|
||||||
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
||||||
tableView.beginUpdates()
|
tableView.beginUpdates()
|
||||||
tableView.endUpdates()
|
tableView.endUpdates()
|
||||||
|
|
|
@ -12,6 +12,8 @@ import Intents
|
||||||
|
|
||||||
class ComposeViewController: UIViewController {
|
class ComposeViewController: UIViewController {
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
var inReplyToID: String?
|
var inReplyToID: String?
|
||||||
var accountsToMention: [String]
|
var accountsToMention: [String]
|
||||||
var initialText: String?
|
var initialText: String?
|
||||||
|
@ -64,7 +66,9 @@ class ComposeViewController: UIViewController {
|
||||||
|
|
||||||
@IBOutlet weak var postProgressView: SteppedProgressView!
|
@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
|
self.inReplyToID = inReplyToID
|
||||||
if let inReplyToID = inReplyToID, let inReplyTo = MastodonCache.status(for: inReplyToID) {
|
if let inReplyToID = inReplyToID, let inReplyTo = MastodonCache.status(for: inReplyToID) {
|
||||||
accountsToMention = [inReplyTo.account.acct] + inReplyTo.mentions.map { $0.acct }
|
accountsToMention = [inReplyTo.account.acct] + inReplyTo.mentions.map { $0.acct }
|
||||||
|
@ -73,7 +77,7 @@ class ComposeViewController: UIViewController {
|
||||||
} else {
|
} else {
|
||||||
accountsToMention = []
|
accountsToMention = []
|
||||||
}
|
}
|
||||||
if let ownAccount = MastodonController.account {
|
if let ownAccount = mastodonController.account {
|
||||||
accountsToMention.removeAll(where: { acct in ownAccount.acct == acct })
|
accountsToMention.removeAll(where: { acct in ownAccount.acct == acct })
|
||||||
}
|
}
|
||||||
accountsToMention = accountsToMention.uniques()
|
accountsToMention = accountsToMention.uniques()
|
||||||
|
@ -120,7 +124,7 @@ class ComposeViewController: UIViewController {
|
||||||
statusTextView.text = accountsToMention.map({ acct in "@\(acct) " }).joined()
|
statusTextView.text = accountsToMention.map({ acct in "@\(acct) " }).joined()
|
||||||
initialText = statusTextView.text
|
initialText = statusTextView.text
|
||||||
|
|
||||||
MastodonController.getOwnAccount { (account) in
|
mastodonController.getOwnAccount { (account) in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.selfDetailView.update(account: account)
|
self.selfDetailView.update(account: account)
|
||||||
}
|
}
|
||||||
|
@ -270,7 +274,7 @@ class ComposeViewController: UIViewController {
|
||||||
// TODO: include CW char count
|
// TODO: include CW char count
|
||||||
let count = CharacterCounter.count(text: statusTextView.text)
|
let count = CharacterCounter.count(text: statusTextView.text)
|
||||||
let cwCount = contentWarningEnabled ? (contentWarningTextField.text?.count ?? 0) : 0
|
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 {
|
if remaining < 0 {
|
||||||
charactersRemainingLabel.textColor = .red
|
charactersRemainingLabel.textColor = .red
|
||||||
postBarButtonItem.isEnabled = false
|
postBarButtonItem.isEnabled = false
|
||||||
|
@ -296,7 +300,7 @@ class ComposeViewController: UIViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateAddAttachmentButton() {
|
func updateAddAttachmentButton() {
|
||||||
switch MastodonController.instance.instanceType {
|
switch mastodonController.instance.instanceType {
|
||||||
case .pleroma:
|
case .pleroma:
|
||||||
addAttachmentButton.isEnabled = true
|
addAttachmentButton.isEnabled = true
|
||||||
case .mastodon:
|
case .mastodon:
|
||||||
|
@ -481,7 +485,7 @@ class ComposeViewController: UIViewController {
|
||||||
self.postProgressView.step()
|
self.postProgressView.step()
|
||||||
|
|
||||||
let request = Client.upload(attachment: FormAttachment(mimeType: mimeType, data: data, fileName: "file"), description: description)
|
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() }
|
guard case let .success(attachment, _) = response else { fatalError() }
|
||||||
|
|
||||||
attachments[index] = attachment
|
attachments[index] = attachment
|
||||||
|
@ -507,7 +511,7 @@ class ComposeViewController: UIViewController {
|
||||||
spoilerText: contentWarning,
|
spoilerText: contentWarning,
|
||||||
visibility: visibility,
|
visibility: visibility,
|
||||||
language: nil)
|
language: nil)
|
||||||
MastodonController.run(request) { (response) in
|
self.mastodonController.run(request) { (response) in
|
||||||
guard case let .success(status, _) = response else { fatalError() }
|
guard case let .success(status, _) = response else { fatalError() }
|
||||||
self.postedStatus = status
|
self.postedStatus = status
|
||||||
MastodonCache.add(status: status)
|
MastodonCache.add(status: status)
|
||||||
|
@ -520,7 +524,7 @@ class ComposeViewController: UIViewController {
|
||||||
self.postProgressView.step()
|
self.postProgressView.step()
|
||||||
self.dismiss(animated: true)
|
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.show(conversationVC, sender: self)
|
||||||
|
|
||||||
self.xcbSession?.complete(with: .success, additionalData: [
|
self.xcbSession?.complete(with: .success, additionalData: [
|
||||||
|
@ -561,7 +565,7 @@ extension ComposeViewController: UITextViewDelegate {
|
||||||
|
|
||||||
extension ComposeViewController: AssetPickerViewControllerDelegate {
|
extension ComposeViewController: AssetPickerViewControllerDelegate {
|
||||||
func assetPicker(_ assetPicker: AssetPickerViewController, shouldAllowAssetOfType type: CompositionAttachment.AttachmentType) -> Bool {
|
func assetPicker(_ assetPicker: AssetPickerViewController, shouldAllowAssetOfType type: CompositionAttachment.AttachmentType) -> Bool {
|
||||||
switch MastodonController.instance.instanceType {
|
switch mastodonController.instance.instanceType {
|
||||||
case .pleroma:
|
case .pleroma:
|
||||||
return true
|
return true
|
||||||
case .mastodon:
|
case .mastodon:
|
||||||
|
|
|
@ -15,6 +15,8 @@ class ConversationTableViewController: EnhancedTableViewController {
|
||||||
static let showPostsImage = UIImage(systemName: "eye.fill")!
|
static let showPostsImage = UIImage(systemName: "eye.fill")!
|
||||||
static let hidePostsImage = UIImage(systemName: "eye.slash.fill")!
|
static let hidePostsImage = UIImage(systemName: "eye.slash.fill")!
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
let mainStatusID: String
|
let mainStatusID: String
|
||||||
let mainStatusState: StatusState
|
let mainStatusState: StatusState
|
||||||
var statuses: [(id: String, state: StatusState)] = [] {
|
var statuses: [(id: String, state: StatusState)] = [] {
|
||||||
|
@ -28,9 +30,10 @@ class ConversationTableViewController: EnhancedTableViewController {
|
||||||
var showStatusesAutomatically = false
|
var showStatusesAutomatically = false
|
||||||
var visibilityBarButtonItem: UIBarButtonItem!
|
var visibilityBarButtonItem: UIBarButtonItem!
|
||||||
|
|
||||||
init(for mainStatusID: String, state: StatusState = .unknown) {
|
init(for mainStatusID: String, state: StatusState = .unknown, mastodonController: MastodonController) {
|
||||||
self.mainStatusID = mainStatusID
|
self.mainStatusID = mainStatusID
|
||||||
self.mainStatusState = state
|
self.mainStatusState = state
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
super.init(style: .plain)
|
super.init(style: .plain)
|
||||||
}
|
}
|
||||||
|
@ -58,7 +61,7 @@ class ConversationTableViewController: EnhancedTableViewController {
|
||||||
guard let mainStatus = MastodonCache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID)") }
|
guard let mainStatus = MastodonCache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID)") }
|
||||||
|
|
||||||
let request = Status.getContext(mainStatus)
|
let request = Status.getContext(mainStatus)
|
||||||
MastodonController.run(request) { response in
|
mastodonController.run(request) { response in
|
||||||
guard case let .success(context, _) = response else { fatalError() }
|
guard case let .success(context, _) = response else { fatalError() }
|
||||||
let parents = self.getDirectParents(of: mainStatus, from: context.ancestors)
|
let parents = self.getDirectParents(of: mainStatus, from: context.ancestors)
|
||||||
MastodonCache.addAll(statuses: parents)
|
MastodonCache.addAll(statuses: parents)
|
||||||
|
@ -155,6 +158,7 @@ class ConversationTableViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ConversationTableViewController: StatusTableViewCellDelegate {
|
extension ConversationTableViewController: StatusTableViewCellDelegate {
|
||||||
|
var apiController: MastodonController { mastodonController }
|
||||||
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
||||||
// causes the table view to recalculate the cell heights
|
// causes the table view to recalculate the cell heights
|
||||||
tableView.beginUpdates()
|
tableView.beginUpdates()
|
||||||
|
|
|
@ -12,12 +12,16 @@ import Pachyderm
|
||||||
|
|
||||||
class ExploreViewController: EnhancedTableViewController {
|
class ExploreViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
var dataSource: DataSource!
|
var dataSource: DataSource!
|
||||||
|
|
||||||
var resultsController: SearchResultsViewController!
|
var resultsController: SearchResultsViewController!
|
||||||
var searchController: UISearchController!
|
var searchController: UISearchController!
|
||||||
|
|
||||||
init() {
|
init(mastodonController: MastodonController) {
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
super.init(style: .insetGrouped)
|
super.init(style: .insetGrouped)
|
||||||
|
|
||||||
title = NSLocalizedString("Explore", comment: "explore tab title")
|
title = NSLocalizedString("Explore", comment: "explore tab title")
|
||||||
|
@ -88,7 +92,7 @@ class ExploreViewController: EnhancedTableViewController {
|
||||||
dataSource.apply(snapshot)
|
dataSource.apply(snapshot)
|
||||||
}
|
}
|
||||||
|
|
||||||
resultsController = SearchResultsViewController()
|
resultsController = SearchResultsViewController(mastodonController: mastodonController)
|
||||||
resultsController.exploreNavigationController = self.navigationController!
|
resultsController.exploreNavigationController = self.navigationController!
|
||||||
searchController = UISearchController(searchResultsController: resultsController)
|
searchController = UISearchController(searchResultsController: resultsController)
|
||||||
searchController.searchResultsUpdater = resultsController
|
searchController.searchResultsUpdater = resultsController
|
||||||
|
@ -107,7 +111,7 @@ class ExploreViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
func reloadLists() {
|
func reloadLists() {
|
||||||
let request = Client.getLists()
|
let request = Client.getLists()
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
guard case let .success(lists, _) = response else {
|
guard case let .success(lists, _) = response else {
|
||||||
fatalError()
|
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
|
alert.addAction(UIAlertAction(title: NSLocalizedString("Delete List", comment: "delete list alert confirm button"), style: .destructive, handler: { (_) in
|
||||||
|
|
||||||
let request = List.delete(list)
|
let request = List.delete(list)
|
||||||
MastodonController.run(request) { (response) in
|
self.mastodonController.run(request) { (response) in
|
||||||
guard case .success(_, _) = response else {
|
guard case .success(_, _) = response else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
@ -174,10 +178,10 @@ class ExploreViewController: EnhancedTableViewController {
|
||||||
return
|
return
|
||||||
|
|
||||||
case .bookmarks:
|
case .bookmarks:
|
||||||
show(BookmarksTableViewController(), sender: nil)
|
show(BookmarksTableViewController(mastodonController: mastodonController), sender: nil)
|
||||||
|
|
||||||
case let .list(list):
|
case let .list(list):
|
||||||
show(ListTimelineViewController(for: list), sender: nil)
|
show(ListTimelineViewController(for: list, mastodonController: mastodonController), sender: nil)
|
||||||
|
|
||||||
case .addList:
|
case .addList:
|
||||||
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
|
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
|
||||||
|
@ -190,13 +194,13 @@ class ExploreViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = Client.createList(title: title)
|
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() }
|
guard case let .success(list, _) = response else { fatalError() }
|
||||||
|
|
||||||
self.reloadLists()
|
self.reloadLists()
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
let listTimelineController = ListTimelineViewController(for: list)
|
let listTimelineController = ListTimelineViewController(for: list, mastodonController: self.mastodonController)
|
||||||
listTimelineController.presentEditOnAppear = true
|
listTimelineController.presentEditOnAppear = true
|
||||||
self.show(listTimelineController, sender: nil)
|
self.show(listTimelineController, sender: nil)
|
||||||
}
|
}
|
||||||
|
@ -205,11 +209,11 @@ class ExploreViewController: EnhancedTableViewController {
|
||||||
present(alert, animated: true)
|
present(alert, animated: true)
|
||||||
|
|
||||||
case let .savedHashtag(hashtag):
|
case let .savedHashtag(hashtag):
|
||||||
show(HashtagTimelineViewController(for: hashtag), sender: nil)
|
show(HashtagTimelineViewController(for: hashtag, mastodonController: mastodonController), sender: nil)
|
||||||
|
|
||||||
case .addSavedHashtag:
|
case .addSavedHashtag:
|
||||||
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
|
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
|
||||||
let navController = UINavigationController(rootViewController: AddSavedHashtagViewController())
|
let navController = UINavigationController(rootViewController: AddSavedHashtagViewController(mastodonController: mastodonController))
|
||||||
present(navController, animated: true)
|
present(navController, animated: true)
|
||||||
|
|
||||||
case let .savedInstance(url):
|
case let .savedInstance(url):
|
||||||
|
|
|
@ -11,6 +11,8 @@ import Pachyderm
|
||||||
|
|
||||||
class EditListAccountsViewController: EnhancedTableViewController {
|
class EditListAccountsViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
let list: List
|
let list: List
|
||||||
|
|
||||||
var dataSource: DataSource!
|
var dataSource: DataSource!
|
||||||
|
@ -20,8 +22,9 @@ class EditListAccountsViewController: EnhancedTableViewController {
|
||||||
var searchResultsController: SearchResultsViewController!
|
var searchResultsController: SearchResultsViewController!
|
||||||
var searchController: UISearchController!
|
var searchController: UISearchController!
|
||||||
|
|
||||||
init(list: List) {
|
init(list: List, mastodonController: MastodonController) {
|
||||||
self.list = list
|
self.list = list
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
super.init(style: .plain)
|
super.init(style: .plain)
|
||||||
|
|
||||||
|
@ -49,7 +52,7 @@ class EditListAccountsViewController: EnhancedTableViewController {
|
||||||
})
|
})
|
||||||
dataSource.editListAccountsController = self
|
dataSource.editListAccountsController = self
|
||||||
|
|
||||||
searchResultsController = SearchResultsViewController()
|
searchResultsController = SearchResultsViewController(mastodonController: mastodonController)
|
||||||
searchResultsController.delegate = self
|
searchResultsController.delegate = self
|
||||||
searchResultsController.onlySections = [.accounts]
|
searchResultsController.onlySections = [.accounts]
|
||||||
searchController = UISearchController(searchResultsController: searchResultsController)
|
searchController = UISearchController(searchResultsController: searchResultsController)
|
||||||
|
@ -70,7 +73,7 @@ class EditListAccountsViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
func loadAccounts() {
|
func loadAccounts() {
|
||||||
let request = List.getAccounts(list)
|
let request = List.getAccounts(list)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
guard case let .success(accounts, pagination) = response else {
|
guard case let .success(accounts, pagination) = response else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
@ -109,7 +112,7 @@ class EditListAccountsViewController: EnhancedTableViewController {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
let request = List.update(self.list, title: text)
|
let request = List.update(self.list, title: text)
|
||||||
MastodonController.run(request) { (response) in
|
self.mastodonController.run(request) { (response) in
|
||||||
guard case .success(_, _) = response else {
|
guard case .success(_, _) = response else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
@ -143,7 +146,7 @@ extension EditListAccountsViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = List.remove(editListAccountsController!.list, accounts: [id])
|
let request = List.remove(editListAccountsController!.list, accounts: [id])
|
||||||
MastodonController.run(request) { (response) in
|
editListAccountsController!.mastodonController.run(request) { (response) in
|
||||||
guard case .success(_, _) = response else {
|
guard case .success(_, _) = response else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
@ -157,7 +160,7 @@ extension EditListAccountsViewController {
|
||||||
extension EditListAccountsViewController: SearchResultsViewControllerDelegate {
|
extension EditListAccountsViewController: SearchResultsViewControllerDelegate {
|
||||||
func selectedSearchResult(account accountID: String) {
|
func selectedSearchResult(account accountID: String) {
|
||||||
let request = List.add(list, accounts: [accountID])
|
let request = List.add(list, accounts: [accountID])
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
guard case .success(_, _) = response else {
|
guard case .success(_, _) = response else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,10 @@ class ListTimelineViewController: TimelineTableViewController {
|
||||||
|
|
||||||
var presentEditOnAppear = false
|
var presentEditOnAppear = false
|
||||||
|
|
||||||
init(for list: List) {
|
init(for list: List, mastodonController: MastodonController) {
|
||||||
self.list = list
|
self.list = list
|
||||||
|
|
||||||
super.init(for: .list(id: list.id))
|
super.init(for: .list(id: list.id), mastodonController: mastodonController)
|
||||||
|
|
||||||
title = list.title
|
title = list.title
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ class ListTimelineViewController: TimelineTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentEdit(animated: Bool) {
|
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))
|
editListAccountsController.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonPressed))
|
||||||
let navController = UINavigationController(rootViewController: editListAccountsController)
|
let navController = UINavigationController(rootViewController: editListAccountsController)
|
||||||
present(navController, animated: animated)
|
present(navController, animated: animated)
|
||||||
|
|
|
@ -9,18 +9,30 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
class MainTabBarViewController: UITabBarController, UITabBarControllerDelegate {
|
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() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
self.delegate = self
|
self.delegate = self
|
||||||
|
|
||||||
viewControllers = [
|
viewControllers = [
|
||||||
embedInNavigationController(TimelinesPageViewController()),
|
embedInNavigationController(TimelinesPageViewController(mastodonController: mastodonController)),
|
||||||
embedInNavigationController(NotificationsPageViewController()),
|
embedInNavigationController(NotificationsPageViewController(mastodonController: mastodonController)),
|
||||||
ComposeViewController(),
|
ComposeViewController(mastodonController: mastodonController),
|
||||||
embedInNavigationController(ExploreViewController()),
|
embedInNavigationController(ExploreViewController(mastodonController: mastodonController)),
|
||||||
embedInNavigationController(MyProfileTableViewController()),
|
embedInNavigationController(MyProfileTableViewController(mastodonController: mastodonController)),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +53,7 @@ class MainTabBarViewController: UITabBarController, UITabBarControllerDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentCompose() {
|
func presentCompose() {
|
||||||
let compose = ComposeViewController()
|
let compose = ComposeViewController(mastodonController: mastodonController)
|
||||||
let navigationController = embedInNavigationController(compose)
|
let navigationController = embedInNavigationController(compose)
|
||||||
navigationController.presentationController?.delegate = compose
|
navigationController.presentationController?.delegate = compose
|
||||||
present(navigationController, animated: true)
|
present(navigationController, animated: true)
|
||||||
|
|
|
@ -13,13 +13,17 @@ class NotificationsPageViewController: SegmentedPageViewController {
|
||||||
|
|
||||||
private let notificationsTitle = NSLocalizedString("Notifications", comment: "notifications tab title")
|
private let notificationsTitle = NSLocalizedString("Notifications", comment: "notifications tab title")
|
||||||
private let mentionsTitle = NSLocalizedString("Mentions", comment: "mentions tab title")
|
private let mentionsTitle = NSLocalizedString("Mentions", comment: "mentions tab title")
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
init() {
|
init(mastodonController: MastodonController) {
|
||||||
let notifications = NotificationsTableViewController(allowedTypes: Pachyderm.Notification.Kind.allCases)
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
|
let notifications = NotificationsTableViewController(allowedTypes: Pachyderm.Notification.Kind.allCases, mastodonController: mastodonController)
|
||||||
notifications.title = notificationsTitle
|
notifications.title = notificationsTitle
|
||||||
notifications.userActivity = UserActivityManager.checkNotificationsActivity()
|
notifications.userActivity = UserActivityManager.checkNotificationsActivity()
|
||||||
|
|
||||||
let mentions = NotificationsTableViewController(allowedTypes: [.mention])
|
let mentions = NotificationsTableViewController(allowedTypes: [.mention], mastodonController: mastodonController)
|
||||||
mentions.title = mentionsTitle
|
mentions.title = mentionsTitle
|
||||||
mentions.userActivity = UserActivityManager.checkMentionsActivity()
|
mentions.userActivity = UserActivityManager.checkMentionsActivity()
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
private let followGroupCell = "followGroupCell"
|
private let followGroupCell = "followGroupCell"
|
||||||
private let followRequestCell = "followRequestCell"
|
private let followRequestCell = "followRequestCell"
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
let excludedTypes: [Pachyderm.Notification.Kind]
|
let excludedTypes: [Pachyderm.Notification.Kind]
|
||||||
let groupTypes = [Notification.Kind.favourite, .reblog, .follow]
|
let groupTypes = [Notification.Kind.favourite, .reblog, .follow]
|
||||||
|
|
||||||
|
@ -30,8 +32,9 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
var newer: RequestRange?
|
var newer: RequestRange?
|
||||||
var older: 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.excludedTypes = Array(Set(Pachyderm.Notification.Kind.allCases).subtracting(allowedTypes))
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
super.init(style: .plain)
|
super.init(style: .plain)
|
||||||
|
|
||||||
|
@ -57,7 +60,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
tableView.prefetchDataSource = self
|
tableView.prefetchDataSource = self
|
||||||
|
|
||||||
let request = Client.getNotifications(excludeTypes: excludedTypes)
|
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() }
|
guard case let .success(notifications, pagination) = result else { fatalError() }
|
||||||
|
|
||||||
let groups = NotificationGroup.createGroups(notifications: notifications, only: self.groupTypes)
|
let groups = NotificationGroup.createGroups(notifications: notifications, only: self.groupTypes)
|
||||||
|
@ -125,7 +128,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
guard let older = older else { return }
|
guard let older = older else { return }
|
||||||
|
|
||||||
let request = Client.getNotifications(excludeTypes: excludedTypes, range: older)
|
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() }
|
guard case let .success(newNotifications, pagination) = result else { fatalError() }
|
||||||
|
|
||||||
let groups = NotificationGroup.createGroups(notifications: newNotifications, only: self.groupTypes)
|
let groups = NotificationGroup.createGroups(notifications: newNotifications, only: self.groupTypes)
|
||||||
|
@ -182,7 +185,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
.map(Pachyderm.Notification.dismiss(id:))
|
.map(Pachyderm.Notification.dismiss(id:))
|
||||||
.forEach { (request) in
|
.forEach { (request) in
|
||||||
group.enter()
|
group.enter()
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
group.leave()
|
group.leave()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +200,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
guard let newer = newer else { return }
|
guard let newer = newer else { return }
|
||||||
|
|
||||||
let request = Client.getNotifications(excludeTypes: excludedTypes, range: newer)
|
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() }
|
guard case let .success(newNotifications, pagination) = result else { fatalError() }
|
||||||
|
|
||||||
let groups = NotificationGroup.createGroups(notifications: newNotifications, only: self.groupTypes)
|
let groups = NotificationGroup.createGroups(notifications: newNotifications, only: self.groupTypes)
|
||||||
|
@ -222,6 +225,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NotificationsTableViewController: StatusTableViewCellDelegate {
|
extension NotificationsTableViewController: StatusTableViewCellDelegate {
|
||||||
|
var apiController: MastodonController { mastodonController }
|
||||||
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
||||||
// causes the table view to recalculate the cell heights
|
// causes the table view to recalculate the cell heights
|
||||||
tableView.beginUpdates()
|
tableView.beginUpdates()
|
||||||
|
|
|
@ -46,8 +46,9 @@ class OnboardingViewController: UINavigationController {
|
||||||
extension OnboardingViewController: InstanceSelectorTableViewControllerDelegate {
|
extension OnboardingViewController: InstanceSelectorTableViewControllerDelegate {
|
||||||
func didSelectInstance(url: URL) {
|
func didSelectInstance(url: URL) {
|
||||||
LocalData.shared.instanceURL = url
|
LocalData.shared.instanceURL = url
|
||||||
MastodonController.createClient()
|
let mastodonController = MastodonController.shared
|
||||||
MastodonController.registerApp {
|
mastodonController.createClient()
|
||||||
|
mastodonController.registerApp {
|
||||||
let clientID = LocalData.shared.clientID!
|
let clientID = LocalData.shared.clientID!
|
||||||
|
|
||||||
let callbackURL = "tusker://oauth"
|
let callbackURL = "tusker://oauth"
|
||||||
|
@ -69,7 +70,7 @@ extension OnboardingViewController: InstanceSelectorTableViewControllerDelegate
|
||||||
let item = components.queryItems?.first(where: { $0.name == "code" }),
|
let item = components.queryItems?.first(where: { $0.name == "code" }),
|
||||||
let authCode = item.value else { return }
|
let authCode = item.value else { return }
|
||||||
|
|
||||||
MastodonController.authorize(authorizationCode: authCode) {
|
mastodonController.authorize(authorizationCode: authCode) {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.onboardingDelegate?.didFinishOnboarding()
|
self.onboardingDelegate?.didFinishOnboarding()
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,14 @@ import SwiftUI
|
||||||
|
|
||||||
class MyProfileTableViewController: ProfileTableViewController {
|
class MyProfileTableViewController: ProfileTableViewController {
|
||||||
|
|
||||||
init() {
|
init(mastodonController: MastodonController) {
|
||||||
super.init(accountID: nil)
|
super.init(accountID: nil, mastodonController: mastodonController)
|
||||||
|
|
||||||
title = "My Profile"
|
title = "My Profile"
|
||||||
tabBarItem.image = UIImage(systemName: "person.fill")
|
tabBarItem.image = UIImage(systemName: "person.fill")
|
||||||
|
|
||||||
|
|
||||||
MastodonController.getOwnAccount { (account) in
|
mastodonController.getOwnAccount { (account) in
|
||||||
self.accountID = account.id
|
self.accountID = account.id
|
||||||
|
|
||||||
ImageCache.avatars.get(account.avatar, completion: { (data) in
|
ImageCache.avatars.get(account.avatar, completion: { (data) in
|
||||||
|
|
|
@ -12,6 +12,8 @@ import SafariServices
|
||||||
|
|
||||||
class ProfileTableViewController: EnhancedTableViewController {
|
class ProfileTableViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
var accountID: String! {
|
var accountID: String! {
|
||||||
didSet {
|
didSet {
|
||||||
if shouldLoadOnAccountIDSet {
|
if shouldLoadOnAccountIDSet {
|
||||||
|
@ -43,7 +45,9 @@ class ProfileTableViewController: EnhancedTableViewController {
|
||||||
var shouldLoadOnAccountIDSet = false
|
var shouldLoadOnAccountIDSet = false
|
||||||
var loadingVC: LoadingViewController? = nil
|
var loadingVC: LoadingViewController? = nil
|
||||||
|
|
||||||
init(accountID: String?) {
|
init(accountID: String?, mastodonController: MastodonController) {
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
self.accountID = accountID
|
self.accountID = accountID
|
||||||
|
|
||||||
super.init(style: .plain)
|
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]>) {
|
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)
|
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() {
|
func sendMessageMentioning() {
|
||||||
guard let account = MastodonCache.account(for: accountID) else { fatalError("Missing cached account \(accountID!)") }
|
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)
|
present(vc, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,6 +237,8 @@ class ProfileTableViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ProfileTableViewController: StatusTableViewCellDelegate {
|
extension ProfileTableViewController: StatusTableViewCellDelegate {
|
||||||
|
var apiController: MastodonController { mastodonController }
|
||||||
|
|
||||||
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
||||||
// causes the table view to recalculate the cell heights
|
// causes the table view to recalculate the cell heights
|
||||||
tableView.beginUpdates()
|
tableView.beginUpdates()
|
||||||
|
|
|
@ -28,6 +28,8 @@ extension SearchResultsViewControllerDelegate {
|
||||||
|
|
||||||
class SearchResultsViewController: EnhancedTableViewController {
|
class SearchResultsViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
|
let mastodonController: MastodonController!
|
||||||
|
|
||||||
weak var exploreNavigationController: UINavigationController?
|
weak var exploreNavigationController: UINavigationController?
|
||||||
weak var delegate: SearchResultsViewControllerDelegate?
|
weak var delegate: SearchResultsViewControllerDelegate?
|
||||||
|
|
||||||
|
@ -40,7 +42,9 @@ class SearchResultsViewController: EnhancedTableViewController {
|
||||||
let searchSubject = PassthroughSubject<String?, Never>()
|
let searchSubject = PassthroughSubject<String?, Never>()
|
||||||
var currentQuery: String?
|
var currentQuery: String?
|
||||||
|
|
||||||
init() {
|
init(mastodonController: MastodonController) {
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
super.init(style: .grouped)
|
super.init(style: .grouped)
|
||||||
|
|
||||||
title = NSLocalizedString("Search", comment: "search screen title")
|
title = NSLocalizedString("Search", comment: "search screen title")
|
||||||
|
@ -118,7 +122,7 @@ class SearchResultsViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = Client.search(query: query, resolve: true, limit: 10)
|
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() }
|
guard case let .success(results, _) = response else { fatalError() }
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
@ -217,6 +221,7 @@ extension SearchResultsViewController: UISearchBarDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SearchResultsViewController: StatusTableViewCellDelegate {
|
extension SearchResultsViewController: StatusTableViewCellDelegate {
|
||||||
|
var apiController: MastodonController { mastodonController }
|
||||||
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
||||||
tableView.beginUpdates()
|
tableView.beginUpdates()
|
||||||
tableView.endUpdates()
|
tableView.endUpdates()
|
||||||
|
|
|
@ -14,6 +14,8 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
||||||
private let statusCell = "statusCell"
|
private let statusCell = "statusCell"
|
||||||
private let accountCell = "accountCell"
|
private let accountCell = "accountCell"
|
||||||
|
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
let actionType: ActionType
|
let actionType: ActionType
|
||||||
let statusID: String
|
let statusID: String
|
||||||
var statusState: StatusState
|
var statusState: StatusState
|
||||||
|
@ -32,8 +34,11 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
||||||
- Parameter actionType The action that this VC is for.
|
- Parameter actionType The action that this VC is for.
|
||||||
- Parameter statusID The ID of the status to show.
|
- 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 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.actionType = actionType
|
||||||
self.statusID = statusID
|
self.statusID = statusID
|
||||||
self.statusState = statusState
|
self.statusState = statusState
|
||||||
|
@ -75,7 +80,7 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
||||||
tableView.tableFooterView = UIActivityIndicatorView(style: .large)
|
tableView.tableFooterView = UIActivityIndicatorView(style: .large)
|
||||||
|
|
||||||
let request = actionType == .favorite ? Status.getFavourites(status) : Status.getReblogs(status)
|
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() }
|
guard case let .success(accounts, _) = response else { fatalError() }
|
||||||
MastodonCache.addAll(accounts: accounts)
|
MastodonCache.addAll(accounts: accounts)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
@ -137,6 +142,7 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension StatusActionAccountListTableViewController: StatusTableViewCellDelegate {
|
extension StatusActionAccountListTableViewController: StatusTableViewCellDelegate {
|
||||||
|
var apiController: MastodonController { mastodonController }
|
||||||
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
||||||
// causes the table view to recalculate the cell heights
|
// causes the table view to recalculate the cell heights
|
||||||
tableView.beginUpdates()
|
tableView.beginUpdates()
|
||||||
|
|
|
@ -22,10 +22,10 @@ class HashtagTimelineViewController: TimelineTableViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(for hashtag: Hashtag) {
|
init(for hashtag: Hashtag, mastodonController: MastodonController) {
|
||||||
self.hashtag = hashtag
|
self.hashtag = hashtag
|
||||||
|
|
||||||
super.init(for: .tag(hashtag: hashtag.name))
|
super.init(for: .tag(hashtag: hashtag.name), mastodonController: mastodonController)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
|
|
@ -31,7 +31,10 @@ class InstanceTimelineViewController: TimelineTableViewController {
|
||||||
init(for url: URL) {
|
init(for url: URL) {
|
||||||
self.instanceURL = 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) {
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import Pachyderm
|
||||||
class TimelineTableViewController: EnhancedTableViewController {
|
class TimelineTableViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
var timeline: Timeline!
|
var timeline: Timeline!
|
||||||
|
let mastodonController: MastodonController
|
||||||
|
|
||||||
var timelineSegments: [[(id: String, state: StatusState)]] = [] {
|
var timelineSegments: [[(id: String, state: StatusState)]] = [] {
|
||||||
didSet {
|
didSet {
|
||||||
|
@ -24,8 +25,9 @@ class TimelineTableViewController: EnhancedTableViewController {
|
||||||
var newer: RequestRange?
|
var newer: RequestRange?
|
||||||
var older: RequestRange?
|
var older: RequestRange?
|
||||||
|
|
||||||
init(for timeline: Timeline) {
|
init(for timeline: Timeline, mastodonController: MastodonController) {
|
||||||
self.timeline = timeline
|
self.timeline = timeline
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
super.init(style: .plain)
|
super.init(style: .plain)
|
||||||
|
|
||||||
|
@ -56,13 +58,13 @@ class TimelineTableViewController: EnhancedTableViewController {
|
||||||
|
|
||||||
tableView.prefetchDataSource = self
|
tableView.prefetchDataSource = self
|
||||||
|
|
||||||
guard MastodonController.accessToken != nil else { return }
|
guard mastodonController.accessToken != nil else { return }
|
||||||
loadInitialStatuses()
|
loadInitialStatuses()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadInitialStatuses() {
|
func loadInitialStatuses() {
|
||||||
let request = Client.getStatuses(timeline: timeline)
|
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() }
|
guard case let .success(statuses, pagination) = response else { fatalError() }
|
||||||
MastodonCache.addAll(statuses: statuses)
|
MastodonCache.addAll(statuses: statuses)
|
||||||
self.timelineSegments.insert(statuses.map { ($0.id, .unknown) }, at: 0)
|
self.timelineSegments.insert(statuses.map { ($0.id, .unknown) }, at: 0)
|
||||||
|
@ -100,7 +102,7 @@ class TimelineTableViewController: EnhancedTableViewController {
|
||||||
guard let older = older else { return }
|
guard let older = older else { return }
|
||||||
|
|
||||||
let request = Client.getStatuses(timeline: timeline, range: older)
|
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() }
|
guard case let .success(newStatuses, pagination) = response else { fatalError() }
|
||||||
self.older = pagination?.older
|
self.older = pagination?.older
|
||||||
MastodonCache.addAll(statuses: newStatuses)
|
MastodonCache.addAll(statuses: newStatuses)
|
||||||
|
@ -125,7 +127,7 @@ class TimelineTableViewController: EnhancedTableViewController {
|
||||||
guard let newer = newer else { return }
|
guard let newer = newer else { return }
|
||||||
|
|
||||||
let request = Client.getStatuses(timeline: timeline, range: newer)
|
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() }
|
guard case let .success(newStatuses, pagination) = response else { fatalError() }
|
||||||
self.newer = pagination?.newer
|
self.newer = pagination?.newer
|
||||||
MastodonCache.addAll(statuses: newStatuses)
|
MastodonCache.addAll(statuses: newStatuses)
|
||||||
|
@ -146,6 +148,8 @@ class TimelineTableViewController: EnhancedTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TimelineTableViewController: StatusTableViewCellDelegate {
|
extension TimelineTableViewController: StatusTableViewCellDelegate {
|
||||||
|
var apiController: MastodonController { mastodonController }
|
||||||
|
|
||||||
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
|
||||||
// causes the table view to recalculate the cell heights
|
// causes the table view to recalculate the cell heights
|
||||||
tableView.beginUpdates()
|
tableView.beginUpdates()
|
||||||
|
|
|
@ -14,14 +14,18 @@ class TimelinesPageViewController: SegmentedPageViewController {
|
||||||
private let federatedTitle = NSLocalizedString("Federated", comment: "federated timeline tab title")
|
private let federatedTitle = NSLocalizedString("Federated", comment: "federated timeline tab title")
|
||||||
private let localTitle = NSLocalizedString("Local", comment: "local timeline tab title")
|
private let localTitle = NSLocalizedString("Local", comment: "local timeline tab title")
|
||||||
|
|
||||||
init() {
|
let mastodonController: MastodonController
|
||||||
let home = TimelineTableViewController(for: .home)
|
|
||||||
|
init(mastodonController: MastodonController) {
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
|
||||||
|
let home = TimelineTableViewController(for: .home, mastodonController: mastodonController)
|
||||||
home.title = homeTitle
|
home.title = homeTitle
|
||||||
|
|
||||||
let federated = TimelineTableViewController(for: .public(local: false))
|
let federated = TimelineTableViewController(for: .public(local: false), mastodonController: mastodonController)
|
||||||
federated.title = federatedTitle
|
federated.title = federatedTitle
|
||||||
|
|
||||||
let local = TimelineTableViewController(for: .public(local: true))
|
let local = TimelineTableViewController(for: .public(local: true), mastodonController: mastodonController)
|
||||||
local.title = localTitle
|
local.title = localTitle
|
||||||
|
|
||||||
super.init(titles: [
|
super.init(titles: [
|
||||||
|
|
|
@ -15,6 +15,8 @@ class UserActivityManager {
|
||||||
private static let encoder = PropertyListEncoder()
|
private static let encoder = PropertyListEncoder()
|
||||||
private static let decoder = PropertyListDecoder()
|
private static let decoder = PropertyListDecoder()
|
||||||
|
|
||||||
|
private static var mastodonController: MastodonController { .shared }
|
||||||
|
|
||||||
private static func getMainTabBarController() -> MainTabBarViewController {
|
private static func getMainTabBarController() -> MainTabBarViewController {
|
||||||
return (UIApplication.shared.delegate! as! AppDelegate).window!.rootViewController as! MainTabBarViewController
|
return (UIApplication.shared.delegate! as! AppDelegate).window!.rootViewController as! MainTabBarViewController
|
||||||
}
|
}
|
||||||
|
@ -42,7 +44,8 @@ class UserActivityManager {
|
||||||
static func handleNewPost(activity: NSUserActivity) {
|
static func handleNewPost(activity: NSUserActivity) {
|
||||||
// TODO: check not currently showing compose screen
|
// TODO: check not currently showing compose screen
|
||||||
let mentioning = activity.userInfo?["mentioning"] as? String
|
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
|
// MARK: - Check Notifications
|
||||||
|
@ -144,7 +147,8 @@ class UserActivityManager {
|
||||||
rootController.segmentedControl.selectedSegmentIndex = index
|
rootController.segmentedControl.selectedSegmentIndex = index
|
||||||
rootController.selectPage(at: index, animated: false)
|
rootController.selectPage(at: index, animated: false)
|
||||||
default:
|
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)
|
tabBarController.select(tab: .explore)
|
||||||
if let navigationController = tabBarController.getTabController(tab: .explore) as? UINavigationController {
|
if let navigationController = tabBarController.getTabController(tab: .explore) as? UINavigationController {
|
||||||
navigationController.popToRootViewController(animated: false)
|
navigationController.popToRootViewController(animated: false)
|
||||||
navigationController.pushViewController(BookmarksTableViewController(), animated: false)
|
navigationController.pushViewController(BookmarksTableViewController(mastodonController: mastodonController), animated: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ import Pachyderm
|
||||||
|
|
||||||
protocol TuskerNavigationDelegate {
|
protocol TuskerNavigationDelegate {
|
||||||
|
|
||||||
|
var apiController: MastodonController { get }
|
||||||
|
|
||||||
func show(_ vc: UIViewController)
|
func show(_ vc: UIViewController)
|
||||||
|
|
||||||
func selected(account accountID: String)
|
func selected(account accountID: String)
|
||||||
|
@ -68,15 +70,15 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
show(ProfileTableViewController(accountID: accountID), sender: self)
|
show(ProfileTableViewController(accountID: accountID, mastodonController: apiController), sender: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func selected(mention: Mention) {
|
func selected(mention: Mention) {
|
||||||
show(ProfileTableViewController(accountID: mention.id), sender: self)
|
show(ProfileTableViewController(accountID: mention.id, mastodonController: apiController), sender: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func selected(tag: Hashtag) {
|
func selected(tag: Hashtag) {
|
||||||
show(HashtagTimelineViewController(for: tag), sender: self)
|
show(HashtagTimelineViewController(for: tag, mastodonController: apiController), sender: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func selected(url: URL) {
|
func selected(url: URL) {
|
||||||
|
@ -113,7 +115,7 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
return
|
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
|
// 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) {
|
func compose(mentioning: String? = nil) {
|
||||||
let compose = ComposeViewController( mentioningAcct: mentioning)
|
let compose = ComposeViewController(mentioningAcct: mentioning, mastodonController: apiController)
|
||||||
let vc = UINavigationController(rootViewController: compose)
|
let vc = UINavigationController(rootViewController: compose)
|
||||||
vc.presentationController?.delegate = compose
|
vc.presentationController?.delegate = compose
|
||||||
present(vc, animated: true)
|
present(vc, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reply(to statusID: String) {
|
func reply(to statusID: String) {
|
||||||
let compose = ComposeViewController(inReplyTo: statusID)
|
let compose = ComposeViewController(inReplyTo: statusID, mastodonController: apiController)
|
||||||
let vc = UINavigationController(rootViewController: compose)
|
let vc = UINavigationController(rootViewController: compose)
|
||||||
vc.presentationController?.delegate = compose
|
vc.presentationController?.delegate = compose
|
||||||
present(vc, animated: true)
|
present(vc, animated: true)
|
||||||
|
@ -200,7 +202,7 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
customActivites.insert(bookmarked ? UnbookmarkStatusActivity() : BookmarkStatusActivity(), at: 0)
|
customActivites.insert(bookmarked ? UnbookmarkStatusActivity() : BookmarkStatusActivity(), at: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.account == MastodonController.account,
|
if status.account == apiController.account,
|
||||||
let pinned = status.pinned {
|
let pinned = status.pinned {
|
||||||
customActivites.insert(pinned ? UnpinStatusActivity() : PinStatusActivity(), at: 1)
|
customActivites.insert(pinned ? UnpinStatusActivity() : PinStatusActivity(), at: 1)
|
||||||
}
|
}
|
||||||
|
@ -228,13 +230,13 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showFollowedByList(accountIDs: [String]) {
|
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")
|
vc.title = NSLocalizedString("Followed By", comment: "followed by accounts list title")
|
||||||
show(vc, sender: self)
|
show(vc, sender: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, statusState state: StatusState, accountIDs: [String]?) -> StatusActionAccountListTableViewController {
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import UIKit
|
||||||
class AccountTableViewCell: UITableViewCell {
|
class AccountTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
var delegate: TuskerNavigationDelegate?
|
var delegate: TuskerNavigationDelegate?
|
||||||
|
var mastodonController: MastodonController? { delegate?.apiController }
|
||||||
|
|
||||||
@IBOutlet weak var avatarImageView: UIImageView!
|
@IBOutlet weak var avatarImageView: UIImageView!
|
||||||
@IBOutlet weak var displayNameLabel: UILabel!
|
@IBOutlet weak var displayNameLabel: UILabel!
|
||||||
|
@ -68,6 +69,11 @@ extension AccountTableViewCell: MenuPreviewProvider {
|
||||||
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
|
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
|
||||||
|
|
||||||
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
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)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,13 +178,15 @@ class ContentLabel: LinkLabel {
|
||||||
func getViewController(forLink url: URL, inRange range: NSRange) -> UIViewController {
|
func getViewController(forLink url: URL, inRange range: NSRange) -> UIViewController {
|
||||||
let text = (self.text! as NSString).substring(with: range)
|
let text = (self.text! as NSString).substring(with: range)
|
||||||
|
|
||||||
if let mention = getMention(for: url, text: text) {
|
if let navigationDelegate = navigationDelegate {
|
||||||
return ProfileTableViewController(accountID: mention.id)
|
if let mention = getMention(for: url, text: text) {
|
||||||
} else if let tag = getHashtag(for: url, text: text) {
|
return ProfileTableViewController(accountID: mention.id, mastodonController: navigationDelegate.apiController)
|
||||||
return HashtagTimelineViewController(for: tag)
|
} else if let tag = getHashtag(for: url, text: text) {
|
||||||
} else {
|
return HashtagTimelineViewController(for: tag, mastodonController: navigationDelegate.apiController)
|
||||||
return SFSafariViewController(url: url)
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return SFSafariViewController(url: url)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getViewController(forLinkAt point: CGPoint) -> UIViewController? {
|
func getViewController(forLinkAt point: CGPoint) -> UIViewController? {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import Pachyderm
|
||||||
class HashtagTableViewCell: UITableViewCell {
|
class HashtagTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
var delegate: TuskerNavigationDelegate?
|
var delegate: TuskerNavigationDelegate?
|
||||||
|
|
||||||
@IBOutlet weak var hashtagLabel: UILabel!
|
@IBOutlet weak var hashtagLabel: UILabel!
|
||||||
|
|
||||||
var hashtag: Hashtag!
|
var hashtag: Hashtag!
|
||||||
|
|
|
@ -12,6 +12,7 @@ import Pachyderm
|
||||||
class FollowNotificationGroupTableViewCell: UITableViewCell {
|
class FollowNotificationGroupTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
var delegate: TuskerNavigationDelegate?
|
var delegate: TuskerNavigationDelegate?
|
||||||
|
var mastodonController: MastodonController? { delegate?.apiController }
|
||||||
|
|
||||||
@IBOutlet weak var avatarStackView: UIStackView!
|
@IBOutlet weak var avatarStackView: UIStackView!
|
||||||
@IBOutlet weak var timestampLabel: UILabel!
|
@IBOutlet weak var timestampLabel: UILabel!
|
||||||
|
@ -133,12 +134,13 @@ extension FollowNotificationGroupTableViewCell: MenuPreviewProvider {
|
||||||
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
|
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
|
||||||
|
|
||||||
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
||||||
|
guard let mastodonController = mastodonController else { return nil }
|
||||||
return (content: {
|
return (content: {
|
||||||
let accountIDs = self.group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account.id }
|
let accountIDs = self.group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account.id }
|
||||||
if accountIDs.count == 1 {
|
if accountIDs.count == 1 {
|
||||||
return ProfileTableViewController(accountID: accountIDs.first!)
|
return ProfileTableViewController(accountID: accountIDs.first!, mastodonController: mastodonController)
|
||||||
} else {
|
} else {
|
||||||
return AccountListTableViewController(accountIDs: accountIDs)
|
return AccountListTableViewController(accountIDs: accountIDs, mastodonController: mastodonController)
|
||||||
}
|
}
|
||||||
}, actions: {
|
}, actions: {
|
||||||
return []
|
return []
|
||||||
|
|
|
@ -12,6 +12,7 @@ import Pachyderm
|
||||||
class FollowRequestNotificationTableViewCell: UITableViewCell {
|
class FollowRequestNotificationTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
var delegate: TuskerNavigationDelegate?
|
var delegate: TuskerNavigationDelegate?
|
||||||
|
var mastodonController: MastodonController? { delegate?.apiController }
|
||||||
|
|
||||||
@IBOutlet weak var stackView: UIStackView!
|
@IBOutlet weak var stackView: UIStackView!
|
||||||
@IBOutlet weak var avatarImageView: UIImageView!
|
@IBOutlet weak var avatarImageView: UIImageView!
|
||||||
|
@ -89,7 +90,7 @@ class FollowRequestNotificationTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
@IBAction func rejectButtonPressed() {
|
@IBAction func rejectButtonPressed() {
|
||||||
let request = Account.rejectFollowRequest(account)
|
let request = Account.rejectFollowRequest(account)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController!.run(request) { (response) in
|
||||||
guard case let .success(relationship, _) = response else { fatalError() }
|
guard case let .success(relationship, _) = response else { fatalError() }
|
||||||
MastodonCache.add(relationship: relationship)
|
MastodonCache.add(relationship: relationship)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
@ -106,7 +107,7 @@ class FollowRequestNotificationTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
@IBAction func acceptButtonPressed() {
|
@IBAction func acceptButtonPressed() {
|
||||||
let request = Account.authorizeFollowRequest(account)
|
let request = Account.authorizeFollowRequest(account)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController!.run(request) { (response) in
|
||||||
guard case let .success(relationship, _) = response else { fatalError() }
|
guard case let .success(relationship, _) = response else { fatalError() }
|
||||||
MastodonCache.add(relationship: relationship)
|
MastodonCache.add(relationship: relationship)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
@ -133,8 +134,9 @@ extension FollowRequestNotificationTableViewCell: MenuPreviewProvider {
|
||||||
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
|
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
|
||||||
|
|
||||||
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
||||||
|
guard let mastodonController = mastodonController else { return nil }
|
||||||
return (content: {
|
return (content: {
|
||||||
return ProfileTableViewController(accountID: self.account.id)
|
return ProfileTableViewController(accountID: self.account.id, mastodonController: mastodonController)
|
||||||
}, actions: {
|
}, actions: {
|
||||||
return []
|
return []
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,6 +16,7 @@ protocol ProfileHeaderTableViewCellDelegate: TuskerNavigationDelegate {
|
||||||
class ProfileHeaderTableViewCell: UITableViewCell {
|
class ProfileHeaderTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
var delegate: ProfileHeaderTableViewCellDelegate?
|
var delegate: ProfileHeaderTableViewCellDelegate?
|
||||||
|
var mastodonController: MastodonController? { delegate?.apiController }
|
||||||
|
|
||||||
@IBOutlet weak var headerImageView: UIImageView!
|
@IBOutlet weak var headerImageView: UIImageView!
|
||||||
@IBOutlet weak var avatarContainerView: UIView!
|
@IBOutlet weak var avatarContainerView: UIView!
|
||||||
|
@ -82,7 +83,7 @@ class ProfileHeaderTableViewCell: UITableViewCell {
|
||||||
noteLabel.setTextFromHtml(account.note)
|
noteLabel.setTextFromHtml(account.note)
|
||||||
noteLabel.setEmojis(account.emojis)
|
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
|
// don't show relationship label for the user's own account
|
||||||
if let relationship = MastodonCache.relationship(for: accountID) {
|
if let relationship = MastodonCache.relationship(for: accountID) {
|
||||||
followsYouLabel.isHidden = !relationship.followedBy
|
followsYouLabel.isHidden = !relationship.followedBy
|
||||||
|
|
|
@ -15,11 +15,13 @@ protocol StatusTableViewCellDelegate: TuskerNavigationDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
class BaseStatusTableViewCell: UITableViewCell {
|
class BaseStatusTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
var delegate: StatusTableViewCellDelegate? {
|
var delegate: StatusTableViewCellDelegate? {
|
||||||
didSet {
|
didSet {
|
||||||
contentLabel.navigationDelegate = delegate
|
contentLabel.navigationDelegate = delegate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var mastodonController: MastodonController? { delegate?.apiController }
|
||||||
|
|
||||||
@IBOutlet weak var avatarImageView: UIImageView!
|
@IBOutlet weak var avatarImageView: UIImageView!
|
||||||
@IBOutlet weak var displayNameLabel: UILabel!
|
@IBOutlet weak var displayNameLabel: UILabel!
|
||||||
|
@ -247,7 +249,7 @@ class BaseStatusTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
let realStatus: Status = status.reblog ?? status
|
let realStatus: Status = status.reblog ?? status
|
||||||
let request = (favorited ? Status.favourite : Status.unfavourite)(realStatus)
|
let request = (favorited ? Status.favourite : Status.unfavourite)(realStatus)
|
||||||
MastodonController.run(request) { response in
|
mastodonController!.run(request) { response in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
if case let .success(newStatus, _) = response {
|
if case let .success(newStatus, _) = response {
|
||||||
self.favorited = newStatus.favourited ?? false
|
self.favorited = newStatus.favourited ?? false
|
||||||
|
@ -272,7 +274,7 @@ class BaseStatusTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
let realStatus: Status = status.reblog ?? status
|
let realStatus: Status = status.reblog ?? status
|
||||||
let request = (reblogged ? Status.reblog : Status.unreblog)(realStatus)
|
let request = (reblogged ? Status.reblog : Status.unreblog)(realStatus)
|
||||||
MastodonController.run(request) { response in
|
mastodonController!.run(request) { response in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
if case let .success(newStatus, _) = response {
|
if case let .success(newStatus, _) = response {
|
||||||
self.reblogged = newStatus.reblogged ?? false
|
self.reblogged = newStatus.reblogged ?? false
|
||||||
|
@ -313,8 +315,13 @@ extension BaseStatusTableViewCell: MenuPreviewProvider {
|
||||||
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
|
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
|
||||||
|
|
||||||
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
||||||
|
guard let mastodonController = mastodonController else { return nil }
|
||||||
if avatarImageView.frame.contains(location) {
|
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) {
|
} else if attachmentsView.frame.contains(location) {
|
||||||
let attachmentsViewLocation = attachmentsView.convert(location, from: self)
|
let attachmentsViewLocation = attachmentsView.convert(location, from: self)
|
||||||
if let attachmentView = attachmentsView.attachmentViews.allObjects.first(where: { $0.frame.contains(attachmentsViewLocation) }),
|
if let attachmentView = attachmentsView.attachmentViews.allObjects.first(where: { $0.frame.contains(attachmentsViewLocation) }),
|
||||||
|
|
|
@ -125,8 +125,9 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
|
||||||
}
|
}
|
||||||
|
|
||||||
override func getStatusCellPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> BaseStatusTableViewCell.PreviewProviders? {
|
override func getStatusCellPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> BaseStatusTableViewCell.PreviewProviders? {
|
||||||
|
guard let mastodonController = mastodonController else { return nil }
|
||||||
return (
|
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) }
|
actions: { self.actionsForStatus(statusID: self.statusID) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -142,6 +143,7 @@ extension TimelineStatusTableViewCell: SelectableTableViewCell {
|
||||||
extension TimelineStatusTableViewCell: TableViewSwipeActionProvider {
|
extension TimelineStatusTableViewCell: TableViewSwipeActionProvider {
|
||||||
|
|
||||||
func leadingSwipeActionsConfiguration() -> UISwipeActionsConfiguration? {
|
func leadingSwipeActionsConfiguration() -> UISwipeActionsConfiguration? {
|
||||||
|
guard let mastodonController = mastodonController else { return nil }
|
||||||
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
||||||
|
|
||||||
let favoriteTitle: String
|
let favoriteTitle: String
|
||||||
|
@ -158,7 +160,7 @@ extension TimelineStatusTableViewCell: TableViewSwipeActionProvider {
|
||||||
favoriteColor = UIColor(displayP3Red: 1, green: 204/255, blue: 0, alpha: 1)
|
favoriteColor = UIColor(displayP3Red: 1, green: 204/255, blue: 0, alpha: 1)
|
||||||
}
|
}
|
||||||
let favorite = UIContextualAction(style: .normal, title: favoriteTitle) { (action, view, completion) in
|
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 {
|
DispatchQueue.main.async {
|
||||||
guard case let .success(status, _) = response else {
|
guard case let .success(status, _) = response else {
|
||||||
completion(false)
|
completion(false)
|
||||||
|
@ -185,7 +187,7 @@ extension TimelineStatusTableViewCell: TableViewSwipeActionProvider {
|
||||||
reblogColor = tintColor
|
reblogColor = tintColor
|
||||||
}
|
}
|
||||||
let reblog = UIContextualAction(style: .normal, title: reblogTitle) { (action, view, completion) in
|
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 {
|
DispatchQueue.main.async {
|
||||||
guard case let .success(status, _) = response else {
|
guard case let .success(status, _) = response else {
|
||||||
completion(false)
|
completion(false)
|
||||||
|
|
|
@ -13,6 +13,8 @@ import SwiftSoup
|
||||||
struct XCBActions {
|
struct XCBActions {
|
||||||
|
|
||||||
// MARK: - Utils
|
// MARK: - Utils
|
||||||
|
private static var mastodonController: MastodonController { .shared }
|
||||||
|
|
||||||
private static func getMainTabBarController() -> MainTabBarViewController {
|
private static func getMainTabBarController() -> MainTabBarViewController {
|
||||||
return (UIApplication.shared.delegate as! AppDelegate).window!.rootViewController as! MainTabBarViewController
|
return (UIApplication.shared.delegate as! AppDelegate).window!.rootViewController as! MainTabBarViewController
|
||||||
}
|
}
|
||||||
|
@ -42,7 +44,7 @@ struct XCBActions {
|
||||||
}
|
}
|
||||||
} else if let searchQuery = request.arguments["statusURL"] {
|
} else if let searchQuery = request.arguments["statusURL"] {
|
||||||
let request = Client.search(query: searchQuery)
|
let request = Client.search(query: searchQuery)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(results, _) = response,
|
if case let .success(results, _) = response,
|
||||||
let status = results.statuses.first {
|
let status = results.statuses.first {
|
||||||
MastodonCache.add(status: status)
|
MastodonCache.add(status: status)
|
||||||
|
@ -73,7 +75,7 @@ struct XCBActions {
|
||||||
}
|
}
|
||||||
} else if let searchQuery = request.arguments["accountURL"] {
|
} else if let searchQuery = request.arguments["accountURL"] {
|
||||||
let request = Client.search(query: searchQuery)
|
let request = Client.search(query: searchQuery)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(results, _) = response {
|
if case let .success(results, _) = response {
|
||||||
if let account = results.accounts.first {
|
if let account = results.accounts.first {
|
||||||
MastodonCache.add(account: account)
|
MastodonCache.add(account: account)
|
||||||
|
@ -91,7 +93,7 @@ struct XCBActions {
|
||||||
}
|
}
|
||||||
} else if let acct = request.arguments["acct"] {
|
} else if let acct = request.arguments["acct"] {
|
||||||
let request = Client.searchForAccount(query: acct)
|
let request = Client.searchForAccount(query: acct)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(accounts, _) = response {
|
if case let .success(accounts, _) = response {
|
||||||
if let account = accounts.first {
|
if let account = accounts.first {
|
||||||
MastodonCache.add(account: account)
|
MastodonCache.add(account: account)
|
||||||
|
@ -118,7 +120,7 @@ struct XCBActions {
|
||||||
static func showStatus(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
static func showStatus(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
||||||
getStatus(from: request, session: session) { (status) in
|
getStatus(from: request, session: session) { (status) in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
let vc = ConversationTableViewController(for: status.id)
|
let vc = ConversationTableViewController(for: status.id, mastodonController: mastodonController)
|
||||||
show(vc)
|
show(vc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,14 +134,14 @@ struct XCBActions {
|
||||||
var status = ""
|
var status = ""
|
||||||
if let mentioning = mentioning { status += mentioning }
|
if let mentioning = mentioning { status += mentioning }
|
||||||
if let text = text { status += text }
|
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: [
|
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
|
return
|
||||||
}
|
}
|
||||||
let request = Client.createStatus(text: status, visibility: Preferences.shared.defaultPostVisibility)
|
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 {
|
if case let .success(status, _) = response {
|
||||||
session.complete(with: .success, additionalData: [
|
session.complete(with: .success, additionalData: [
|
||||||
"statusURL": status.url?.absoluteString,
|
"statusURL": status.url?.absoluteString,
|
||||||
|
@ -152,7 +154,7 @@ struct XCBActions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let compose = ComposeViewController(mentioningAcct: mentioning, text: text)
|
let compose = ComposeViewController(mentioningAcct: mentioning, text: text, mastodonController: mastodonController)
|
||||||
compose.xcbSession = session
|
compose.xcbSession = session
|
||||||
let vc = UINavigationController(rootViewController: compose)
|
let vc = UINavigationController(rootViewController: compose)
|
||||||
present(vc)
|
present(vc)
|
||||||
|
@ -199,7 +201,7 @@ struct XCBActions {
|
||||||
|
|
||||||
static func statusAction(request: @escaping (Status) -> Request<Status>, alertTitle: String, _ url: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
static func statusAction(request: @escaping (Status) -> Request<Status>, alertTitle: String, _ url: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
||||||
func performAction(status: Status, completion: ((Status) -> Void)?) {
|
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 {
|
if case let .success(status, _) = response {
|
||||||
MastodonCache.add(status: status)
|
MastodonCache.add(status: status)
|
||||||
completion?(status)
|
completion?(status)
|
||||||
|
@ -219,7 +221,7 @@ struct XCBActions {
|
||||||
if silent ?? false {
|
if silent ?? false {
|
||||||
performAction(status: status, completion: nil)
|
performAction(status: status, completion: nil)
|
||||||
} else {
|
} else {
|
||||||
let vc = ConversationTableViewController(for: status.id)
|
let vc = ConversationTableViewController(for: status.id, mastodonController: mastodonController)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
show(vc)
|
show(vc)
|
||||||
}
|
}
|
||||||
|
@ -247,7 +249,7 @@ struct XCBActions {
|
||||||
static func showAccount(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
static func showAccount(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
||||||
getAccount(from: request, session: session) { (account) in
|
getAccount(from: request, session: session) { (account) in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
let vc = ProfileTableViewController(accountID: account.id)
|
let vc = ProfileTableViewController(accountID: account.id, mastodonController: mastodonController)
|
||||||
show(vc)
|
show(vc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,7 +271,7 @@ struct XCBActions {
|
||||||
}
|
}
|
||||||
|
|
||||||
static func getCurrentUser(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
static func getCurrentUser(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
||||||
let account = MastodonController.account!
|
let account = mastodonController.account!
|
||||||
session.complete(with: .success, additionalData: [
|
session.complete(with: .success, additionalData: [
|
||||||
"username": account.acct,
|
"username": account.acct,
|
||||||
"displayName": account.displayName,
|
"displayName": account.displayName,
|
||||||
|
@ -285,7 +287,7 @@ struct XCBActions {
|
||||||
static func followUser(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
static func followUser(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) {
|
||||||
func performAction(_ account: Account) {
|
func performAction(_ account: Account) {
|
||||||
let request = Account.follow(account.id)
|
let request = Account.follow(account.id)
|
||||||
MastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case let .success(relationship, _) = response {
|
if case let .success(relationship, _) = response {
|
||||||
MastodonCache.add(relationship: relationship)
|
MastodonCache.add(relationship: relationship)
|
||||||
session.complete(with: .success, additionalData: [
|
session.complete(with: .success, additionalData: [
|
||||||
|
@ -303,7 +305,7 @@ struct XCBActions {
|
||||||
if silent ?? false {
|
if silent ?? false {
|
||||||
performAction(account)
|
performAction(account)
|
||||||
} else {
|
} else {
|
||||||
let vc = ProfileTableViewController(accountID: account.id)
|
let vc = ProfileTableViewController(accountID: account.id, mastodonController: mastodonController)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
show(vc)
|
show(vc)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue