Refactor view controller creation/navigation into AppRouter
This commit is contained in:
parent
788e0500de
commit
54f142e3f9
|
@ -60,6 +60,7 @@
|
||||||
D621544821682A9D0003D87D /* TabsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D621544721682A9D0003D87D /* TabsTableViewController.swift */; };
|
D621544821682A9D0003D87D /* TabsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D621544721682A9D0003D87D /* TabsTableViewController.swift */; };
|
||||||
D621544B21682AD30003D87D /* TabTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D621544A21682AD30003D87D /* TabTableViewCell.swift */; };
|
D621544B21682AD30003D87D /* TabTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D621544A21682AD30003D87D /* TabTableViewCell.swift */; };
|
||||||
D621544D21682AD90003D87D /* TabTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D621544C21682AD90003D87D /* TabTableViewCell.xib */; };
|
D621544D21682AD90003D87D /* TabTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D621544C21682AD90003D87D /* TabTableViewCell.xib */; };
|
||||||
|
D627FF74217BBC9700CC0648 /* AppRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627FF73217BBC9700CC0648 /* AppRouter.swift */; };
|
||||||
D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6289E83217B795D0003D1D7 /* LargeImageViewController.xib */; };
|
D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6289E83217B795D0003D1D7 /* LargeImageViewController.xib */; };
|
||||||
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2421217AA7E1005076CC /* UserActivityManager.swift */; };
|
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2421217AA7E1005076CC /* UserActivityManager.swift */; };
|
||||||
D62D2424217ABF3F005076CC /* NSUserActivity+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2423217ABF3F005076CC /* NSUserActivity+Extensions.swift */; };
|
D62D2424217ABF3F005076CC /* NSUserActivity+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2423217ABF3F005076CC /* NSUserActivity+Extensions.swift */; };
|
||||||
|
@ -247,6 +248,7 @@
|
||||||
D621544721682A9D0003D87D /* TabsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewController.swift; sourceTree = "<group>"; };
|
D621544721682A9D0003D87D /* TabsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewController.swift; sourceTree = "<group>"; };
|
||||||
D621544A21682AD30003D87D /* TabTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabTableViewCell.swift; sourceTree = "<group>"; };
|
D621544A21682AD30003D87D /* TabTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
D621544C21682AD90003D87D /* TabTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TabTableViewCell.xib; sourceTree = "<group>"; };
|
D621544C21682AD90003D87D /* TabTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TabTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
|
D627FF73217BBC9700CC0648 /* AppRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouter.swift; sourceTree = "<group>"; };
|
||||||
D6289E83217B795D0003D1D7 /* LargeImageViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LargeImageViewController.xib; sourceTree = "<group>"; };
|
D6289E83217B795D0003D1D7 /* LargeImageViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LargeImageViewController.xib; sourceTree = "<group>"; };
|
||||||
D62D2421217AA7E1005076CC /* UserActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserActivityManager.swift; sourceTree = "<group>"; };
|
D62D2421217AA7E1005076CC /* UserActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserActivityManager.swift; sourceTree = "<group>"; };
|
||||||
D62D2423217ABF3F005076CC /* NSUserActivity+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSUserActivity+Extensions.swift"; sourceTree = "<group>"; };
|
D62D2423217ABF3F005076CC /* NSUserActivity+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSUserActivity+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
|
@ -743,6 +745,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D6D4DDCF212518A000E1C4BB /* AppDelegate.swift */,
|
D6D4DDCF212518A000E1C4BB /* AppDelegate.swift */,
|
||||||
|
D627FF73217BBC9700CC0648 /* AppRouter.swift */,
|
||||||
D64D0AAC2128D88B005A6F37 /* LocalData.swift */,
|
D64D0AAC2128D88B005A6F37 /* LocalData.swift */,
|
||||||
04DACE8D212CC7CC009840C4 /* ImageCache.swift */,
|
04DACE8D212CC7CC009840C4 /* ImageCache.swift */,
|
||||||
D6028B9A2150811100F223B9 /* MastodonCache.swift */,
|
D6028B9A2150811100F223B9 /* MastodonCache.swift */,
|
||||||
|
@ -1137,6 +1140,7 @@
|
||||||
D6C693CA2161253F007D6A6D /* SilentActionPermissionsTableViewController.swift in Sources */,
|
D6C693CA2161253F007D6A6D /* SilentActionPermissionsTableViewController.swift in Sources */,
|
||||||
D6333B372137838300CE884A /* AttributedString+Trim.swift in Sources */,
|
D6333B372137838300CE884A /* AttributedString+Trim.swift in Sources */,
|
||||||
D641C777213CAA9E004B4513 /* ActionNotificationTableViewCell.swift in Sources */,
|
D641C777213CAA9E004B4513 /* ActionNotificationTableViewCell.swift in Sources */,
|
||||||
|
D627FF74217BBC9700CC0648 /* AppRouter.swift in Sources */,
|
||||||
D6C693FE2162FEEA007D6A6D /* UIViewController+Children.swift in Sources */,
|
D6C693FE2162FEEA007D6A6D /* UIViewController+Children.swift in Sources */,
|
||||||
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */,
|
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */,
|
||||||
D663626821360E2C00C9CBA2 /* PreferencesTableViewController.swift in Sources */,
|
D663626821360E2C00C9CBA2 /* PreferencesTableViewController.swift in Sources */,
|
||||||
|
|
|
@ -12,6 +12,7 @@ import UIKit
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
var router: AppRouter!
|
||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
window = UIWindow(frame: UIScreen.main.bounds)
|
window = UIWindow(frame: UIScreen.main.bounds)
|
||||||
|
@ -66,7 +67,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
MastodonController.getOwnAccount()
|
MastodonController.getOwnAccount()
|
||||||
MastodonController.getOwnInstance()
|
MastodonController.getOwnInstance()
|
||||||
|
|
||||||
window!.rootViewController = MainTabBarViewController()
|
let tabBarController = MainTabBarViewController()
|
||||||
|
window!.rootViewController = tabBarController
|
||||||
|
router = tabBarController.router
|
||||||
}
|
}
|
||||||
|
|
||||||
func showOnboardingUI() {
|
func showOnboardingUI() {
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
//
|
||||||
|
// AppRouter.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 10/20/18.
|
||||||
|
// Copyright © 2018 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import Pachyderm
|
||||||
|
import SafariServices
|
||||||
|
|
||||||
|
class AppRouter {
|
||||||
|
|
||||||
|
let rootViewController: UIViewController
|
||||||
|
var currentViewController: UIViewController {
|
||||||
|
return getContentViewController(from: rootViewController)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(root: UIViewController) {
|
||||||
|
self.rootViewController = root
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getContentViewController(from vc: UIViewController) -> UIViewController {
|
||||||
|
if let vc = vc as? UITabBarController,
|
||||||
|
let selected = vc.selectedViewController {
|
||||||
|
return getContentViewController(from: selected)
|
||||||
|
} else if let vc = vc as? UINavigationController,
|
||||||
|
let top = vc.topViewController {
|
||||||
|
return getContentViewController(from: top)
|
||||||
|
} else {
|
||||||
|
return vc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func present(_ vc: UIViewController, animated: Bool) {
|
||||||
|
if currentViewController.presentingViewController != nil {
|
||||||
|
currentViewController.dismiss(animated: animated) {
|
||||||
|
self.present(vc, animated: animated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentViewController.present(vc, animated: animated)
|
||||||
|
}
|
||||||
|
|
||||||
|
func push(_ vc: UIViewController, animated: Bool) {
|
||||||
|
if currentViewController.presentingViewController != nil {
|
||||||
|
currentViewController.dismiss(animated: animated) {
|
||||||
|
self.push(vc, animated: animated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guard let nav = currentViewController.navigationController else { fatalError("Can't push view controller while not in navigation controller") }
|
||||||
|
nav.pushViewController(vc, animated: animated)
|
||||||
|
}
|
||||||
|
|
||||||
|
func profile(for accountID: String) -> ProfileTableViewController {
|
||||||
|
return ProfileTableViewController(accountID: accountID, router: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func profile(for mention: Mention) -> ProfileTableViewController {
|
||||||
|
return ProfileTableViewController(accountID: mention.id, router: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeline(for timeline: Timeline) -> TimelineTableViewController {
|
||||||
|
return TimelineTableViewController(for: timeline, router: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeline(tag: Hashtag) -> TimelineTableViewController {
|
||||||
|
return timeline(for: .tag(hashtag: tag.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func safariViewController(for url: URL) -> SFSafariViewController {
|
||||||
|
return SFSafariViewController(url: url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func conversation(for statusID: String) -> ConversationTableViewController {
|
||||||
|
return ConversationTableViewController(for: statusID, router: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func compose(inReplyTo inReplyToID: String? = nil, mentioningAcct: String? = nil, text: String? = nil) -> ComposeViewController {
|
||||||
|
return ComposeViewController(inReplyTo: inReplyToID, mentioningAcct: mentioningAcct, text: text, router: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func largeImage(_ image: UIImage, description: String?, sourceFrame: CGRect, sourceCornerRadius: CGFloat, transitioningDelegate: UIViewControllerTransitioningDelegate?) -> LargeImageViewController {
|
||||||
|
let vc = LargeImageViewController(image: image, description: description, sourceFrame: sourceFrame, sourceCornerRadius: sourceCornerRadius, router: self)
|
||||||
|
vc.transitioningDelegate = transitioningDelegate
|
||||||
|
return vc
|
||||||
|
}
|
||||||
|
|
||||||
|
func moreOptions(forStatus statusID: String) -> UIAlertController {
|
||||||
|
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID)") }
|
||||||
|
|
||||||
|
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||||
|
if let url = status.url {
|
||||||
|
alert.addAction(UIAlertAction(title: "Open in Safari", style: .default, handler: { (_) in
|
||||||
|
let vc = SFSafariViewController(url: url)
|
||||||
|
self.present(vc, animated: true)
|
||||||
|
}))
|
||||||
|
alert.addAction(UIAlertAction(title: "Copy", style: .default, handler: { (_) in
|
||||||
|
UIPasteboard.general.url = url
|
||||||
|
}))
|
||||||
|
alert.addAction(UIAlertAction(title: "Share...", style: .default, handler: { (_) in
|
||||||
|
let vc = UIActivityViewController(activityItems: [url], applicationActivities: nil)
|
||||||
|
self.present(vc, animated: true)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
||||||
|
return alert
|
||||||
|
}
|
||||||
|
|
||||||
|
func moreOptions(forURL url: URL) -> UIAlertController {
|
||||||
|
let alert = UIAlertController(title: nil, message: url.absoluteString, preferredStyle: .actionSheet)
|
||||||
|
alert.addAction(UIAlertAction(title: "Open in Safari", style: .default, handler: { (_) in
|
||||||
|
let vc = SFSafariViewController(url: url)
|
||||||
|
self.present(vc, animated: true)
|
||||||
|
}))
|
||||||
|
alert.addAction(UIAlertAction(title: "Copy", style: .default, handler: { (_) in
|
||||||
|
UIPasteboard.general.url = url
|
||||||
|
}))
|
||||||
|
alert.addAction(UIAlertAction(title: "Share...", style: .default, handler: { (_) in
|
||||||
|
let vc = UIActivityViewController(activityItems: [url], applicationActivities: nil)
|
||||||
|
self.present(vc, animated: true)
|
||||||
|
}))
|
||||||
|
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
||||||
|
return alert
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,14 +7,6 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import Pachyderm
|
|
||||||
import SafariServices
|
|
||||||
|
|
||||||
extension LargeImageViewControllerDelegate where Self: UIViewController {
|
|
||||||
func closeLargeImage() {
|
|
||||||
dismiss(animated: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension UIViewController: UIViewControllerTransitioningDelegate {
|
extension UIViewController: UIViewControllerTransitioningDelegate {
|
||||||
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||||
|
|
|
@ -12,6 +12,8 @@ import Intents
|
||||||
|
|
||||||
class ComposeViewController: UIViewController {
|
class ComposeViewController: UIViewController {
|
||||||
|
|
||||||
|
let router: AppRouter
|
||||||
|
|
||||||
@IBOutlet weak var scrollView: UIScrollView!
|
@IBOutlet weak var scrollView: UIScrollView!
|
||||||
@IBOutlet weak var inReplyToContainerView: UIView!
|
@IBOutlet weak var inReplyToContainerView: UIView!
|
||||||
@IBOutlet weak var inReplyToAvatarImageView: UIImageView!
|
@IBOutlet weak var inReplyToAvatarImageView: UIImageView!
|
||||||
|
@ -51,11 +53,14 @@ class ComposeViewController: UIViewController {
|
||||||
|
|
||||||
var status: Status?
|
var status: Status?
|
||||||
|
|
||||||
init(inReplyTo inReplyToID: String? = nil, mentioningAcct: String? = nil, text: String? = nil) {
|
init(inReplyTo inReplyToID: String? = nil, mentioningAcct: String? = nil, text: String? = nil, router: AppRouter) {
|
||||||
super.init(nibName: "ComposeViewController", bundle: nil)
|
|
||||||
self.inReplyToID = inReplyToID
|
self.inReplyToID = inReplyToID
|
||||||
self.mentioningAcct = mentioningAcct
|
self.mentioningAcct = mentioningAcct
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.router = router
|
||||||
|
|
||||||
|
super.init(nibName: "ComposeViewController", bundle: nil)
|
||||||
|
|
||||||
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelPressed))
|
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelPressed))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,9 @@ import Pachyderm
|
||||||
|
|
||||||
class ConversationTableViewController: UITableViewController {
|
class ConversationTableViewController: UITableViewController {
|
||||||
|
|
||||||
var mainStatusID: String!
|
let router: AppRouter
|
||||||
|
|
||||||
|
var mainStatusID: String!
|
||||||
var statusIDs: [String] = [] {
|
var statusIDs: [String] = [] {
|
||||||
didSet {
|
didSet {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
@ -21,9 +22,11 @@ class ConversationTableViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(for mainStatusID: String) {
|
init(for mainStatusID: String, router: AppRouter) {
|
||||||
super.init(style: .plain)
|
|
||||||
self.mainStatusID = mainStatusID
|
self.mainStatusID = mainStatusID
|
||||||
|
self.router = router
|
||||||
|
|
||||||
|
super.init(style: .plain)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
@ -74,7 +77,7 @@ class ConversationTableViewController: UITableViewController {
|
||||||
if let status = MastodonCache.status(for: mainStatusID),
|
if let status = MastodonCache.status(for: mainStatusID),
|
||||||
let url = status.url {
|
let url = status.url {
|
||||||
actions.append(UIPreviewAction(title: "Open in Safari", style: .default, handler: { (_, _) in
|
actions.append(UIPreviewAction(title: "Open in Safari", style: .default, handler: { (_, _) in
|
||||||
let vc = self.viewController(forURL: url)
|
let vc = self.router.safariViewController(for: url)
|
||||||
UIApplication.shared.delegate!.window!!.rootViewController!.present(vc, animated: true)
|
UIApplication.shared.delegate!.window!!.rootViewController!.present(vc, animated: true)
|
||||||
}))
|
}))
|
||||||
actions.append(UIPreviewAction(title: "Share", style: .default, handler: { (_, _) in
|
actions.append(UIPreviewAction(title: "Share", style: .default, handler: { (_, _) in
|
||||||
|
@ -145,4 +148,3 @@ class ConversationTableViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ConversationTableViewController: StatusTableViewCellDelegate {}
|
extension ConversationTableViewController: StatusTableViewCellDelegate {}
|
||||||
extension ConversationTableViewController: LargeImageViewControllerDelegate {}
|
|
||||||
|
|
|
@ -9,13 +9,9 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import Photos
|
import Photos
|
||||||
|
|
||||||
protocol LargeImageViewControllerDelegate {
|
|
||||||
func closeLargeImage()
|
|
||||||
}
|
|
||||||
|
|
||||||
class LargeImageViewController: UIViewController, UIScrollViewDelegate {
|
class LargeImageViewController: UIViewController, UIScrollViewDelegate {
|
||||||
|
|
||||||
var delegate: LargeImageViewControllerDelegate?
|
let router: AppRouter
|
||||||
|
|
||||||
var originFrame: CGRect?
|
var originFrame: CGRect?
|
||||||
var originCornerRadius: CGFloat?
|
var originCornerRadius: CGFloat?
|
||||||
|
@ -64,22 +60,14 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
init(image: UIImage, description: String?, sourceView: UIView, sourceViewController: UIViewController) {
|
init(image: UIImage, description: String?, sourceFrame: CGRect, sourceCornerRadius: CGFloat, router: AppRouter) {
|
||||||
super.init(nibName: "LargeImageViewController", bundle: nil)
|
self.router = router
|
||||||
self.image = image
|
self.image = image
|
||||||
self.imageDescription = description
|
self.imageDescription = description
|
||||||
var frame = sourceView.convert(sourceView.bounds, to: sourceViewController.view)
|
self.originFrame = sourceFrame
|
||||||
if let scrollView = sourceViewController.view as? UIScrollView {
|
self.originCornerRadius = sourceCornerRadius
|
||||||
let scale = scrollView.zoomScale
|
|
||||||
let width = frame.width * scale
|
super.init(nibName: "LargeImageViewController", bundle: nil)
|
||||||
let height = frame.height * scale
|
|
||||||
let x = frame.minX * scale - scrollView.contentOffset.x + scrollView.frame.minX
|
|
||||||
let y = frame.minY * scale - scrollView.contentOffset.y + scrollView.frame.minY
|
|
||||||
frame = CGRect(x: x, y: y, width: width, height: height)
|
|
||||||
}
|
|
||||||
self.originFrame = frame
|
|
||||||
self.originCornerRadius = sourceView.layer.cornerRadius
|
|
||||||
self.transitioningDelegate = sourceViewController
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
@ -206,7 +194,7 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func closeButtonPressed(_ sender: Any) {
|
@IBAction func closeButtonPressed(_ sender: Any) {
|
||||||
delegate?.closeLargeImage()
|
dismiss(animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func downloadPressed(_ sender: Any) {
|
@IBAction func downloadPressed(_ sender: Any) {
|
||||||
|
|
|
@ -10,6 +10,8 @@ import UIKit
|
||||||
|
|
||||||
class MainTabBarViewController: UITabBarController {
|
class MainTabBarViewController: UITabBarController {
|
||||||
|
|
||||||
|
lazy var router = AppRouter(root: self)
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
@ -31,20 +33,20 @@ class MainTabBarViewController: UITabBarController {
|
||||||
func createVC(for tab: Tab) -> UIViewController {
|
func createVC(for tab: Tab) -> UIViewController {
|
||||||
switch tab {
|
switch tab {
|
||||||
case .home:
|
case .home:
|
||||||
return TimelineTableViewController(for: .home)
|
return TimelineTableViewController(for: .home, router: router)
|
||||||
case .federated:
|
case .federated:
|
||||||
return TimelineTableViewController(for: .public(local: false))
|
return TimelineTableViewController(for: .public(local: false), router: router)
|
||||||
case .local:
|
case .local:
|
||||||
return TimelineTableViewController(for: .public(local: true))
|
return TimelineTableViewController(for: .public(local: true), router: router)
|
||||||
case .myProfile:
|
case .myProfile:
|
||||||
let myProfile = ProfileTableViewController(accountID: nil)
|
let myProfile = ProfileTableViewController(accountID: nil, router: router)
|
||||||
myProfile.title = "My Profile"
|
myProfile.title = "My Profile"
|
||||||
MastodonController.getOwnAccount { (account) in
|
MastodonController.getOwnAccount { (account) in
|
||||||
myProfile.accountID = account.id
|
myProfile.accountID = account.id
|
||||||
}
|
}
|
||||||
return myProfile
|
return myProfile
|
||||||
case .notifications:
|
case .notifications:
|
||||||
return embedInNavigationController(NotificationsTableViewController())
|
return NotificationsTableViewController(router: router)
|
||||||
case .preferences:
|
case .preferences:
|
||||||
return PreferencesTableViewController.create()
|
return PreferencesTableViewController.create()
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ import Pachyderm
|
||||||
|
|
||||||
class NotificationsTableViewController: UITableViewController {
|
class NotificationsTableViewController: UITableViewController {
|
||||||
|
|
||||||
|
let router: AppRouter
|
||||||
|
|
||||||
var notifications: [Pachyderm.Notification] = [] {
|
var notifications: [Pachyderm.Notification] = [] {
|
||||||
didSet {
|
didSet {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
@ -22,8 +24,11 @@ class NotificationsTableViewController: UITableViewController {
|
||||||
var newer: RequestRange?
|
var newer: RequestRange?
|
||||||
var older: RequestRange?
|
var older: RequestRange?
|
||||||
|
|
||||||
init() {
|
init(router: AppRouter) {
|
||||||
|
self.router = router
|
||||||
|
|
||||||
super.init(style: .plain)
|
super.init(style: .plain)
|
||||||
|
|
||||||
self.title = "Notifications"
|
self.title = "Notifications"
|
||||||
self.refreshControl = UIRefreshControl()
|
self.refreshControl = UIRefreshControl()
|
||||||
refreshControl!.addTarget(self, action: #selector(refreshNotifications(_:)), for: .valueChanged)
|
refreshControl!.addTarget(self, action: #selector(refreshNotifications(_:)), for: .valueChanged)
|
||||||
|
@ -149,4 +154,3 @@ class NotificationsTableViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NotificationsTableViewController: StatusTableViewCellDelegate {}
|
extension NotificationsTableViewController: StatusTableViewCellDelegate {}
|
||||||
extension NotificationsTableViewController: LargeImageViewControllerDelegate {}
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ import SafariServices
|
||||||
|
|
||||||
class ProfileTableViewController: UITableViewController, PreferencesAdaptive {
|
class ProfileTableViewController: UITableViewController, PreferencesAdaptive {
|
||||||
|
|
||||||
|
let router: AppRouter
|
||||||
|
|
||||||
var accountID: String! {
|
var accountID: String! {
|
||||||
didSet {
|
didSet {
|
||||||
if shouldLoadOnAccountIDSet {
|
if shouldLoadOnAccountIDSet {
|
||||||
|
@ -36,9 +38,12 @@ class ProfileTableViewController: UITableViewController, PreferencesAdaptive {
|
||||||
var shouldLoadOnAccountIDSet = false
|
var shouldLoadOnAccountIDSet = false
|
||||||
var loadingVC: LoadingViewController? = nil
|
var loadingVC: LoadingViewController? = nil
|
||||||
|
|
||||||
init(accountID: String?) {
|
init(accountID: String?, router: AppRouter) {
|
||||||
super.init(style: .plain)
|
|
||||||
self.accountID = accountID
|
self.accountID = accountID
|
||||||
|
self.router = router
|
||||||
|
|
||||||
|
super.init(style: .plain)
|
||||||
|
|
||||||
self.refreshControl = UIRefreshControl()
|
self.refreshControl = UIRefreshControl()
|
||||||
refreshControl!.addTarget(self, action: #selector(refreshStatuses(_:)), for: .valueChanged)
|
refreshControl!.addTarget(self, action: #selector(refreshStatuses(_:)), for: .valueChanged)
|
||||||
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(composePressed(_:)))
|
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(composePressed(_:)))
|
||||||
|
@ -107,7 +112,7 @@ class ProfileTableViewController: UITableViewController, PreferencesAdaptive {
|
||||||
var actions = [UIPreviewActionItem]()
|
var actions = [UIPreviewActionItem]()
|
||||||
if let account = MastodonCache.account(for: accountID) {
|
if let account = MastodonCache.account(for: accountID) {
|
||||||
actions.append(UIPreviewAction(title: "Open in Safari", style: .default, handler: { (_, _) in
|
actions.append(UIPreviewAction(title: "Open in Safari", style: .default, handler: { (_, _) in
|
||||||
let vc = self.viewController(forURL: account.url)
|
let vc = self.router.safariViewController(for: account.url)
|
||||||
UIApplication.shared.delegate!.window!!.rootViewController!.present(vc, animated: true)
|
UIApplication.shared.delegate!.window!!.rootViewController!.present(vc, animated: true)
|
||||||
}))
|
}))
|
||||||
actions.append(UIPreviewAction(title: "Share", style: .default, handler: { (_, _) in
|
actions.append(UIPreviewAction(title: "Share", style: .default, handler: { (_, _) in
|
||||||
|
@ -115,7 +120,7 @@ class ProfileTableViewController: UITableViewController, PreferencesAdaptive {
|
||||||
UIApplication.shared.delegate!.window!!.rootViewController!.present(vc, animated: true)
|
UIApplication.shared.delegate!.window!!.rootViewController!.present(vc, animated: true)
|
||||||
}))
|
}))
|
||||||
actions.append(UIPreviewAction(title: "Send Message", style: .default, handler: { (_, _) in
|
actions.append(UIPreviewAction(title: "Send Message", style: .default, handler: { (_, _) in
|
||||||
let vc = UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct))
|
let vc = UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct, router: self.router))
|
||||||
UIApplication.shared.delegate!.window!!.rootViewController!.present(vc, animated: true)
|
UIApplication.shared.delegate!.window!!.rootViewController!.present(vc, animated: true)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -148,7 +153,7 @@ class ProfileTableViewController: UITableViewController, PreferencesAdaptive {
|
||||||
|
|
||||||
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, router: router))
|
||||||
present(vc, animated: true)
|
present(vc, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,4 +284,3 @@ extension ProfileTableViewController: ProfileHeaderTableViewCellDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extension ProfileTableViewController: LargeImageViewControllerDelegate {}
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ import Pachyderm
|
||||||
|
|
||||||
class TimelineTableViewController: UITableViewController {
|
class TimelineTableViewController: UITableViewController {
|
||||||
|
|
||||||
|
let router: AppRouter
|
||||||
|
|
||||||
lazy var favoriteActionImage: UIImage = UIGraphicsImageRenderer(size: CGSize(width: 30 * 137/131, height: 30)).image { _ in
|
lazy var favoriteActionImage: UIImage = UIGraphicsImageRenderer(size: CGSize(width: 30 * 137/131, height: 30)).image { _ in
|
||||||
UIImage(named: "Favorite")!.draw(in: CGRect(x: 0, y: 0, width: 30 * 137/131, height: 30))
|
UIImage(named: "Favorite")!.draw(in: CGRect(x: 0, y: 0, width: 30 * 137/131, height: 30))
|
||||||
}
|
}
|
||||||
|
@ -37,9 +39,11 @@ class TimelineTableViewController: UITableViewController {
|
||||||
var newer: RequestRange?
|
var newer: RequestRange?
|
||||||
var older: RequestRange?
|
var older: RequestRange?
|
||||||
|
|
||||||
init(for timeline: Timeline) {
|
init(for timeline: Timeline, router: AppRouter) {
|
||||||
super.init(style: .plain)
|
|
||||||
self.timeline = timeline
|
self.timeline = timeline
|
||||||
|
self.router = router
|
||||||
|
|
||||||
|
super.init(style: .plain)
|
||||||
|
|
||||||
switch timeline {
|
switch timeline {
|
||||||
case .home:
|
case .home:
|
||||||
|
@ -168,4 +172,3 @@ class TimelineTableViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TimelineTableViewController: StatusTableViewCellDelegate {}
|
extension TimelineTableViewController: StatusTableViewCellDelegate {}
|
||||||
extension TimelineTableViewController: LargeImageViewControllerDelegate {}
|
|
||||||
|
|
|
@ -12,15 +12,9 @@ import Pachyderm
|
||||||
class UserActivityManager {
|
class UserActivityManager {
|
||||||
|
|
||||||
// MARK: - Utils
|
// MARK: - Utils
|
||||||
private static func presentModally(_ vc: UIViewController, animated: Bool, completion: (() -> Void)? = nil) {
|
private static var router: AppRouter = {
|
||||||
UIApplication.shared.keyWindow!.rootViewController!.present(vc, animated: animated, completion: completion)
|
return (UIApplication.shared.delegate as! AppDelegate).router
|
||||||
}
|
}()
|
||||||
|
|
||||||
private static func presentNav(_ vc: UIViewController, animated: Bool) {
|
|
||||||
let tabBarController = UIApplication.shared.keyWindow!.rootViewController! as! UITabBarController
|
|
||||||
let navController = tabBarController.selectedViewController as! UINavigationController
|
|
||||||
navController.pushViewController(vc, animated: animated)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - New Post
|
// MARK: - New Post
|
||||||
static func newPostActivity(mentioning: Account? = nil) -> NSUserActivity {
|
static func newPostActivity(mentioning: Account? = nil) -> NSUserActivity {
|
||||||
|
@ -41,7 +35,7 @@ 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
|
||||||
presentModally(UINavigationController(rootViewController: ComposeViewController(mentioningAcct: mentioning)), animated: true)
|
router.present(router.compose(mentioningAcct: mentioning), animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Check Notifications
|
// MARK: - Check Notifications
|
||||||
|
|
|
@ -11,33 +11,26 @@ import SafariServices
|
||||||
import Pachyderm
|
import Pachyderm
|
||||||
|
|
||||||
protocol TuskerNavigationDelegate {
|
protocol TuskerNavigationDelegate {
|
||||||
func viewController(forAccount accountID: String) -> UIViewController
|
|
||||||
|
var router: AppRouter { get }
|
||||||
|
|
||||||
func selected(account accountID: String)
|
func selected(account accountID: String)
|
||||||
|
|
||||||
func viewController(forMention mention: Mention) -> UIViewController
|
|
||||||
|
|
||||||
func selected(mention: Mention)
|
func selected(mention: Mention)
|
||||||
|
|
||||||
func viewController(forTag tag: Hashtag) -> UIViewController
|
|
||||||
|
|
||||||
func selected(tag: Hashtag)
|
func selected(tag: Hashtag)
|
||||||
|
|
||||||
func viewController(forURL url: URL) -> UIViewController
|
|
||||||
|
|
||||||
func selected(url: URL)
|
func selected(url: URL)
|
||||||
|
|
||||||
func viewController(forStatus statusID: String) -> UIViewController
|
|
||||||
|
|
||||||
func selected(status statusID: String)
|
func selected(status statusID: String)
|
||||||
|
|
||||||
func compose()
|
func compose()
|
||||||
|
|
||||||
func reply(to statusID: String)
|
func reply(to statusID: String)
|
||||||
|
|
||||||
func viewController(forImage image: UIImage, description: String?, animatingFrom originView: UIView) -> UIViewController
|
func largeImage(_ image: UIImage, description: String?, sourceView: UIView) -> LargeImageViewController
|
||||||
|
|
||||||
func showLargeImage(_ image: UIImage, description: String?, animatingFrom originView: UIView)
|
func showLargeImage(_ image: UIImage, description: String?, animatingFrom sourceView: UIView)
|
||||||
|
|
||||||
func showMoreOptions(forStatus statusID: String)
|
func showMoreOptions(forStatus statusID: String)
|
||||||
|
|
||||||
|
@ -46,10 +39,6 @@ protocol TuskerNavigationDelegate {
|
||||||
|
|
||||||
extension TuskerNavigationDelegate where Self: UIViewController {
|
extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
|
|
||||||
func viewController(forAccount accountID: String) -> UIViewController {
|
|
||||||
return ProfileTableViewController(accountID: accountID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func selected(account accountID: String) {
|
func selected(account accountID: String) {
|
||||||
// don't open if the account is the same as the current one
|
// don't open if the account is the same as the current one
|
||||||
if let profileController = self as? ProfileTableViewController,
|
if let profileController = self as? ProfileTableViewController,
|
||||||
|
@ -57,49 +46,19 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let navigationController = navigationController else {
|
router.push(router.profile(for: accountID), animated: true)
|
||||||
fatalError("Can't show profile VC when not in navigation controller")
|
|
||||||
}
|
|
||||||
let vc = viewController(forAccount: accountID)
|
|
||||||
navigationController.pushViewController(vc, animated: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func viewController(forMention mention: Mention) -> UIViewController {
|
|
||||||
return ProfileTableViewController(accountID: mention.id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func selected(mention: Mention) {
|
func selected(mention: Mention) {
|
||||||
guard let navigationController = navigationController else {
|
router.push(router.profile(for: mention), animated: true)
|
||||||
fatalError("Can't show profile VC from mention when not in navigation controller")
|
|
||||||
}
|
|
||||||
let vc = viewController(forMention: mention)
|
|
||||||
navigationController.pushViewController(vc, animated: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func viewController(forTag tag: Hashtag) -> UIViewController {
|
|
||||||
let timeline = Timeline.tag(hashtag: tag.name)
|
|
||||||
return TimelineTableViewController(for: timeline)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func selected(tag: Hashtag) {
|
func selected(tag: Hashtag) {
|
||||||
guard let navigationController = navigationController else {
|
router.push(router.timeline(tag: tag), animated: true)
|
||||||
fatalError("Can't show hashtag timeline when not in navigation controller")
|
|
||||||
}
|
|
||||||
let vc = viewController(forTag: tag)
|
|
||||||
navigationController.pushViewController(vc, animated: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func viewController(forURL url: URL) -> UIViewController {
|
|
||||||
return SFSafariViewController(url: url)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func selected(url: URL) {
|
func selected(url: URL) {
|
||||||
let vc = viewController(forURL: url)
|
router.present(router.safariViewController(for: url), animated: true)
|
||||||
present(vc, animated: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func viewController(forStatus statusID: String) -> UIViewController {
|
|
||||||
return ConversationTableViewController(for: statusID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func selected(status statusID: String) {
|
func selected(status statusID: String) {
|
||||||
|
@ -109,73 +68,43 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let navigationController = navigationController else {
|
router.push(router.conversation(for: statusID), animated: true)
|
||||||
fatalError("Can't show conversation VC when not in navigation controller")
|
|
||||||
}
|
|
||||||
let vc = viewController(forStatus: statusID)
|
|
||||||
navigationController.pushViewController(vc, animated: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func compose() {
|
func compose() {
|
||||||
let vc = UINavigationController(rootViewController: ComposeViewController())
|
let vc: UINavigationController = UINavigationController(rootViewController: router.compose())
|
||||||
present(vc, animated: true)
|
router.present(vc, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reply(to statusID: String) {
|
func reply(to statusID: String) {
|
||||||
let vc = UINavigationController(rootViewController: ComposeViewController(inReplyTo: statusID))
|
let vc = UINavigationController(rootViewController: router.compose(inReplyTo: statusID))
|
||||||
present(vc, animated: true)
|
router.present(vc, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func viewController(forImage image: UIImage, description: String?, animatingFrom originView: UIView) -> UIViewController {
|
func largeImage(_ image: UIImage, description: String?, sourceView: UIView) -> LargeImageViewController {
|
||||||
guard let self = self as? UIViewController & LargeImageViewControllerDelegate else {
|
var sourceFrame = sourceView.convert(sourceView.bounds, to: view)
|
||||||
fatalError("Can't create large image view controller unless self is LargeImageViewControllerDelegate")
|
if let scrollView = view as? UIScrollView {
|
||||||
|
let scale = scrollView.zoomScale
|
||||||
|
let width = sourceFrame.width * scale
|
||||||
|
let height = sourceFrame.height * scale
|
||||||
|
let x = sourceFrame.minX * scale - scrollView.contentOffset.x + scrollView.frame.minX
|
||||||
|
let y = sourceFrame.minY * scale - scrollView.contentOffset.y + scrollView.frame.minY
|
||||||
|
sourceFrame = CGRect(x: x, y: y, width: width, height: height)
|
||||||
}
|
}
|
||||||
let vc = LargeImageViewController(image: image, description: description, sourceView: originView, sourceViewController: self)
|
let sourceCornerRadius = sourceView.layer.cornerRadius
|
||||||
vc.delegate = self
|
return router.largeImage(image, description: description, sourceFrame: sourceFrame, sourceCornerRadius: sourceCornerRadius, transitioningDelegate: self)
|
||||||
return vc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func showLargeImage(_ image: UIImage, description: String?, animatingFrom originView: UIView) {
|
func showLargeImage(_ image: UIImage, description: String?, animatingFrom sourceView: UIView) {
|
||||||
let vc = viewController(forImage: image, description: description, animatingFrom: originView)
|
router.present(largeImage(image, description: description, sourceView: sourceView), animated: true)
|
||||||
present(vc, animated: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func showMoreOptions(forStatus statusID: String) {
|
func showMoreOptions(forStatus statusID: String) {
|
||||||
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID)") }
|
router.present(router.moreOptions(forStatus: statusID), animated: true)
|
||||||
|
|
||||||
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
|
||||||
if let url = status.url {
|
|
||||||
alert.addAction(UIAlertAction(title: "Open in Safari", style: .default, handler: { (_) in
|
|
||||||
let vc = SFSafariViewController(url: url)
|
|
||||||
self.present(vc, animated: true)
|
|
||||||
}))
|
|
||||||
alert.addAction(UIAlertAction(title: "Copy", style: .default, handler: { (_) in
|
|
||||||
UIPasteboard.general.url = url
|
|
||||||
}))
|
|
||||||
alert.addAction(UIAlertAction(title: "Share...", style: .default, handler: { (_) in
|
|
||||||
let vc = UIActivityViewController(activityItems: [url], applicationActivities: nil)
|
|
||||||
self.present(vc, animated: true)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
|
||||||
present(alert, animated: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func showMoreOptions(forURL url: URL) {
|
func showMoreOptions(forURL url: URL) {
|
||||||
let alert = UIAlertController(title: nil, message: url.absoluteString, preferredStyle: .actionSheet)
|
router.present(router.moreOptions(forURL: url), animated: true)
|
||||||
alert.addAction(UIAlertAction(title: "Open in Safari", style: .default, handler: { (_) in
|
|
||||||
let vc = SFSafariViewController(url: url)
|
|
||||||
self.present(vc, animated: true)
|
|
||||||
}))
|
|
||||||
alert.addAction(UIAlertAction(title: "Copy", style: .default, handler: { (_) in
|
|
||||||
UIPasteboard.general.url = url
|
|
||||||
}))
|
|
||||||
alert.addAction(UIAlertAction(title: "Share...", style: .default, handler: { (_) in
|
|
||||||
let vc = UIActivityViewController(activityItems: [url], applicationActivities: nil)
|
|
||||||
self.present(vc, animated: true)
|
|
||||||
}))
|
|
||||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
|
||||||
present(alert, animated: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,11 +92,11 @@ class ContentLabel: TTTAttributedLabel {
|
||||||
}
|
}
|
||||||
let text = (self.text as! NSString).substring(with: link.result.range)
|
let text = (self.text as! NSString).substring(with: link.result.range)
|
||||||
if let mention = getMention(for: url, text: text) {
|
if let mention = getMention(for: url, text: text) {
|
||||||
return navigationDelegate.viewController(forMention: mention)
|
return navigationDelegate.router.profile(for: mention)
|
||||||
} else if let tag = getHashtag(for: url, text: text) {
|
} else if let tag = getHashtag(for: url, text: text) {
|
||||||
return navigationDelegate.viewController(forTag: tag)
|
return navigationDelegate.router.timeline(tag: tag)
|
||||||
} else {
|
} else {
|
||||||
return navigationDelegate.viewController(forURL: url)
|
return navigationDelegate.router.safariViewController(for: url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,11 +193,11 @@ class ActionNotificationTableViewCell: UITableViewCell, PreferencesAdaptive {
|
||||||
extension ActionNotificationTableViewCell: PreviewViewControllerProvider {
|
extension ActionNotificationTableViewCell: PreviewViewControllerProvider {
|
||||||
func getPreviewViewController(forLocation location: CGPoint, sourceViewController: UIViewController) -> UIViewController? {
|
func getPreviewViewController(forLocation location: CGPoint, sourceViewController: UIViewController) -> UIViewController? {
|
||||||
if avatarContainerView.frame.contains(location) {
|
if avatarContainerView.frame.contains(location) {
|
||||||
return delegate?.viewController(forAccount: notification.account.id)
|
return delegate?.router.profile(for: notification.account.id)
|
||||||
} else if contentLabel.frame.contains(location),
|
} else if contentLabel.frame.contains(location),
|
||||||
let vc = contentLabel.getViewController(forLinkAt: contentLabel.convert(location, from: self)) {
|
let vc = contentLabel.getViewController(forLinkAt: contentLabel.convert(location, from: self)) {
|
||||||
return vc
|
return vc
|
||||||
}
|
}
|
||||||
return delegate?.viewController(forStatus: statusID)
|
return delegate?.router.conversation(for: statusID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ import Pachyderm
|
||||||
|
|
||||||
class FollowNotificationTableViewCell: UITableViewCell, PreferencesAdaptive {
|
class FollowNotificationTableViewCell: UITableViewCell, PreferencesAdaptive {
|
||||||
|
|
||||||
|
var router: AppRouter!
|
||||||
|
|
||||||
var delegate: StatusTableViewCellDelegate?
|
var delegate: StatusTableViewCellDelegate?
|
||||||
|
|
||||||
@IBOutlet weak var followLabel: UILabel!
|
@IBOutlet weak var followLabel: UILabel!
|
||||||
|
@ -99,6 +101,6 @@ class FollowNotificationTableViewCell: UITableViewCell, PreferencesAdaptive {
|
||||||
|
|
||||||
extension FollowNotificationTableViewCell: PreviewViewControllerProvider {
|
extension FollowNotificationTableViewCell: PreviewViewControllerProvider {
|
||||||
func getPreviewViewController(forLocation location: CGPoint, sourceViewController: UIViewController) -> UIViewController? {
|
func getPreviewViewController(forLocation location: CGPoint, sourceViewController: UIViewController) -> UIViewController? {
|
||||||
return delegate?.viewController(forAccount: accountID)
|
return router.profile(for: accountID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,13 +228,13 @@ extension ConversationMainStatusTableViewCell: AttachmentViewDelegate {
|
||||||
extension ConversationMainStatusTableViewCell: PreviewViewControllerProvider {
|
extension ConversationMainStatusTableViewCell: PreviewViewControllerProvider {
|
||||||
func getPreviewViewController(forLocation location: CGPoint, sourceViewController: UIViewController) -> UIViewController? {
|
func getPreviewViewController(forLocation location: CGPoint, sourceViewController: UIViewController) -> UIViewController? {
|
||||||
if avatarImageView.frame.contains(location) {
|
if avatarImageView.frame.contains(location) {
|
||||||
return delegate?.viewController(forAccount: accountID)
|
return delegate?.router.profile(for: 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.subviews.first(where: { $0.frame.contains(attachmentsViewLocation) }) as? AttachmentView {
|
if let attachmentView = attachmentsView.subviews.first(where: { $0.frame.contains(attachmentsViewLocation) }) as? AttachmentView {
|
||||||
let image = attachmentView.image!
|
let image = attachmentView.image!
|
||||||
let description = attachmentView.description
|
let description = attachmentView.description
|
||||||
return delegate?.viewController(forImage: image, description: description, animatingFrom: attachmentView)
|
return delegate?.largeImage(image, description: description, sourceView: attachmentView)
|
||||||
}
|
}
|
||||||
} else if contentLabel.frame.contains(location),
|
} else if contentLabel.frame.contains(location),
|
||||||
let vc = contentLabel.getViewController(forLinkAt: contentLabel.convert(location, from: self)) {
|
let vc = contentLabel.getViewController(forLinkAt: contentLabel.convert(location, from: self)) {
|
||||||
|
|
|
@ -357,18 +357,18 @@ extension StatusTableViewCell: AttachmentViewDelegate {
|
||||||
extension StatusTableViewCell: PreviewViewControllerProvider {
|
extension StatusTableViewCell: PreviewViewControllerProvider {
|
||||||
func getPreviewViewController(forLocation location: CGPoint, sourceViewController: UIViewController) -> UIViewController? {
|
func getPreviewViewController(forLocation location: CGPoint, sourceViewController: UIViewController) -> UIViewController? {
|
||||||
if avatarImageView.frame.contains(location) {
|
if avatarImageView.frame.contains(location) {
|
||||||
return delegate?.viewController(forAccount: accountID)
|
return delegate?.router.profile(for: 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.subviews.first(where: { $0.frame.contains(attachmentsViewLocation) }) as? AttachmentView {
|
if let attachmentView = attachmentsView.subviews.first(where: { $0.frame.contains(attachmentsViewLocation) }) as? AttachmentView {
|
||||||
let image = attachmentView.image!
|
let image = attachmentView.image!
|
||||||
let description = attachmentView.attachment.description
|
let description = attachmentView.attachment.description
|
||||||
return delegate?.viewController(forImage: image, description: description, animatingFrom: attachmentView)
|
return delegate?.largeImage(image, description: description, sourceView: attachmentView)
|
||||||
}
|
}
|
||||||
} else if contentLabel.frame.contains(location),
|
} else if contentLabel.frame.contains(location),
|
||||||
let vc = contentLabel.getViewController(forLinkAt: contentLabel.convert(location, from: self)) {
|
let vc = contentLabel.getViewController(forLinkAt: contentLabel.convert(location, from: self)) {
|
||||||
return vc
|
return vc
|
||||||
}
|
}
|
||||||
return delegate?.viewController(forStatus: statusID)
|
return delegate?.router.conversation(for: statusID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,15 +13,9 @@ import SwiftSoup
|
||||||
struct XCBActions {
|
struct XCBActions {
|
||||||
|
|
||||||
// MARK: - Utils
|
// MARK: - Utils
|
||||||
private static func presentModally(_ vc: UIViewController, animated: Bool, completion: (() -> Void)? = nil) {
|
private static var router: AppRouter = {
|
||||||
UIApplication.shared.keyWindow!.rootViewController!.present(vc, animated: animated, completion: completion)
|
return (UIApplication.shared.delegate as! AppDelegate).router
|
||||||
}
|
}()
|
||||||
|
|
||||||
private static func presentNav(_ vc: UIViewController, animated: Bool) {
|
|
||||||
let tabBarController = UIApplication.shared.keyWindow!.rootViewController! as! UITabBarController
|
|
||||||
let navController = tabBarController.selectedViewController as! UINavigationController
|
|
||||||
navController.pushViewController(vc, animated: animated)
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func getStatus(from request: XCBRequest, session: XCBSession, completion: @escaping (Status) -> Void) {
|
private static func getStatus(from request: XCBRequest, session: XCBSession, completion: @escaping (Status) -> Void) {
|
||||||
if let id = request.arguments["statusID"] {
|
if let id = request.arguments["statusID"] {
|
||||||
|
@ -111,9 +105,9 @@ struct XCBActions {
|
||||||
// MARK: - Statuses
|
// MARK: - Statuses
|
||||||
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
|
||||||
let vc = ConversationTableViewController(for: status.id)
|
let vc = router.conversation(for: status.id)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
presentNav(vc, animated: true)
|
router.push(vc, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,10 +140,10 @@ struct XCBActions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let compose = ComposeViewController(mentioningAcct: mentioning, text: text)
|
let compose = router.compose(mentioningAcct: mentioning, text: text)
|
||||||
compose.xcbSession = session
|
compose.xcbSession = session
|
||||||
let vc = UINavigationController(rootViewController: compose)
|
let vc = UINavigationController(rootViewController: compose)
|
||||||
presentModally(vc, animated: true)
|
router.present(vc, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,9 +207,9 @@ 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 = router.conversation(for: status.id)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
presentNav(vc, animated: true)
|
router.push(vc, animated: true)
|
||||||
}
|
}
|
||||||
let alertController = UIAlertController(title: alertTitle, message: nil, preferredStyle: .alert)
|
let alertController = UIAlertController(title: alertTitle, message: nil, preferredStyle: .alert)
|
||||||
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (_) in
|
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (_) in
|
||||||
|
@ -229,7 +223,7 @@ struct XCBActions {
|
||||||
session.complete(with: .cancel)
|
session.complete(with: .cancel)
|
||||||
}))
|
}))
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
presentModally(alertController, animated: true)
|
router.present(alertController, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,9 +234,9 @@ struct XCBActions {
|
||||||
// MARK: - Accounts
|
// MARK: - Accounts
|
||||||
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
|
||||||
let vc = ProfileTableViewController(accountID: account.id)
|
let vc = router.profile(for: account.id)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
presentNav(vc, animated: true)
|
router.push(vc, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,9 +291,9 @@ struct XCBActions {
|
||||||
if silent ?? false {
|
if silent ?? false {
|
||||||
performAction(account)
|
performAction(account)
|
||||||
} else {
|
} else {
|
||||||
let vc = ProfileTableViewController(accountID: account.id)
|
let vc = router.profile(for: account.id)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
presentNav(vc, animated: true)
|
router.push(vc, animated: true)
|
||||||
}
|
}
|
||||||
let alertController = UIAlertController(title: "Follow \(account.realDisplayName)?", message: nil, preferredStyle: .alert)
|
let alertController = UIAlertController(title: "Follow \(account.realDisplayName)?", message: nil, preferredStyle: .alert)
|
||||||
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (_) in
|
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (_) in
|
||||||
|
@ -309,7 +303,7 @@ struct XCBActions {
|
||||||
session.complete(with: .cancel)
|
session.complete(with: .cancel)
|
||||||
}))
|
}))
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
presentModally(alertController, animated: true)
|
router.present(alertController, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue