// // TuskerNavigationDelegate.swift // Tusker // // Created by Shadowfacts on 9/30/18. // Copyright © 2018 Shadowfacts. All rights reserved. // import UIKit import SafariServices import Pachyderm protocol TuskerNavigationDelegate { func show(_ vc: UIViewController) func selected(account accountID: String) func selected(mention: Mention) func selected(tag: Hashtag) func selected(url: URL) func selected(status statusID: String) func compose() func reply(to statusID: String) func largeImage(_ image: UIImage, description: String?, sourceView: UIImageView) -> LargeImageViewController func largeImage(gifData: Data, description: String?, sourceView: UIImageView) -> LargeImageViewController func showLargeImage(_ image: UIImage, description: String?, animatingFrom sourceView: UIImageView) func showLargeImage(gifData: Data, description: String?, animatingFrom sourceView: UIImageView) func gallery(attachments: [Attachment], sourceViews: [UIImageView?], startIndex: Int) -> GalleryViewController func showGallery(attachments: [Attachment], sourceViews: [UIImageView?], startIndex: Int) func showMoreOptions(forStatus statusID: String) func showMoreOptions(forURL url: URL) func showFollowedByList(accountIDs: [String]) func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, accountIDs: [String]?) -> StatusActionAccountListTableViewController } extension TuskerNavigationDelegate where Self: UIViewController { func show(_ vc: UIViewController) { show(vc, sender: self) } func selected(account accountID: String) { // don't open if the account is the same as the current one if let profileController = self as? ProfileTableViewController, profileController.accountID == accountID { return } show(ProfileTableViewController(accountID: accountID), sender: self) } func selected(mention: Mention) { show(ProfileTableViewController(accountID: mention.id), sender: self) } func selected(tag: Hashtag) { show(TimelineTableViewController(for: .tag(hashtag: tag.name)), sender: self) } func selected(url: URL) { if (Preferences.shared.openLinksInApps) { UIApplication.shared.open(url, options: [.universalLinksOnly: true]) { (success) in if (!success) { self.present(SFSafariViewController(url: url), animated: true) } } } else { present(SFSafariViewController(url: url), animated: true) } } func selected(status statusID: String) { // don't open if the conversation is the same as the current one if let conversationController = self as? ConversationTableViewController, conversationController.mainStatusID == statusID { return } show(ConversationTableViewController(for: statusID), sender: self) } func compose() { let compose = ComposeViewController() let vc = UINavigationController(rootViewController: compose) vc.presentationController?.delegate = compose present(vc, animated: true) } func reply(to statusID: String) { let compose = ComposeViewController(inReplyTo: statusID) let vc = UINavigationController(rootViewController: compose) vc.presentationController?.delegate = compose present(vc, animated: true) } private func sourceViewInfo(_ sourceView: UIImageView?) -> LargeImageViewController.SourceInfo? { guard let sourceView = sourceView else { return nil } var sourceFrame = sourceView.convert(sourceView.bounds, to: view) 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) } return (image: sourceView.image!, frame: sourceFrame, cornerRadius: sourceView.layer.cornerRadius) } func largeImage(_ image: UIImage, description: String?, sourceView: UIImageView) -> LargeImageViewController { let vc = LargeImageViewController(image: image, description: description, sourceInfo: sourceViewInfo(sourceView)) vc.transitioningDelegate = self return vc } func largeImage(gifData: Data, description: String?, sourceView: UIImageView) -> LargeImageViewController { let vc = LargeImageViewController(image: UIImage(data: gifData)!, description: description, sourceInfo: sourceViewInfo(sourceView)) vc.transitioningDelegate = self vc.gifData = gifData return vc } func showLargeImage(_ image: UIImage, description: String?, animatingFrom sourceView: UIImageView) { present(largeImage(image, description: description, sourceView: sourceView), animated: true) } func showLargeImage(gifData: Data, description: String?, animatingFrom sourceView: UIImageView) { present(largeImage(gifData: gifData, description: description, sourceView: sourceView), animated: true) } func gallery(attachments: [Attachment], sourceViews: [UIImageView?], startIndex: Int) -> GalleryViewController { let sourcesInfo = sourceViews.map(sourceViewInfo) let vc = GalleryViewController(attachments: attachments, sourcesInfo: sourcesInfo, startIndex: startIndex) vc.transitioningDelegate = self return vc } func showGallery(attachments: [Attachment], sourceViews: [UIImageView?], startIndex: Int) { present(gallery(attachments: attachments, sourceViews: sourceViews, startIndex: startIndex), animated: true) } private func moreOptions(forURL url: URL) -> UIViewController { let customActivites: [UIActivity] = [ OpenInSafariActivity() ] let activityController = UIActivityViewController(activityItems: [url], applicationActivities: customActivites) activityController.completionWithItemsHandler = OpenInSafariActivity.completionHandler(viewController: self, url: url) return activityController } private func moreOptions(forStatus statusID: String) -> UIViewController { guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID)") } guard let url = status.url else { fatalError("Missing url for status \(statusID)") } return moreOptions(forURL: url) } func showMoreOptions(forStatus statusID: String) { present(moreOptions(forStatus: statusID), animated: true) } func showMoreOptions(forURL url: URL) { present(moreOptions(forURL: url), animated: true) } func showFollowedByList(accountIDs: [String]) { let vc = AccountListTableViewController(accountIDs: accountIDs) vc.title = NSLocalizedString("Followed By", comment: "followed by accounts list title") show(vc, sender: self) } func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, accountIDs: [String]?) -> StatusActionAccountListTableViewController { return StatusActionAccountListTableViewController(actionType: action, statusID: statusID, accountIDs: accountIDs) } }