// // TuskerNavigationDelegate.swift // Tusker // // Created by Shadowfacts on 9/30/18. // Copyright © 2018 Shadowfacts. All rights reserved. // import UIKit import SafariServices import Pachyderm protocol TuskerNavigationDelegate: UIViewController { var apiController: MastodonController { get } func conversation(mainStatusID: String, state: StatusState) -> ConversationTableViewController } extension TuskerNavigationDelegate { func show(_ vc: UIViewController) { if vc is LargeImageViewController || vc is GalleryViewController || vc is SFSafariViewController { present(vc, animated: true) } else { 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? ProfileViewController, profileController.accountID == accountID { return } show(ProfileViewController(accountID: accountID, mastodonController: apiController), sender: self) } func selected(mention: Mention) { show(ProfileViewController(accountID: mention.id, mastodonController: apiController), sender: self) } func selected(tag: Hashtag) { show(HashtagTimelineViewController(for: tag, mastodonController: apiController), sender: self) } func selected(url: URL, allowUniversalLinks: Bool = true) { func openSafari() { if Preferences.shared.useInAppSafari { let config = SFSafariViewController.Configuration() config.entersReaderIfAvailable = Preferences.shared.inAppSafariAutomaticReaderMode present(SFSafariViewController(url: url, configuration: config), animated: true) } else { UIApplication.shared.open(url, options: [:]) } } if allowUniversalLinks && Preferences.shared.openLinksInApps { UIApplication.shared.open(url, options: [.universalLinksOnly: true]) { (success) in if (!success) { openSafari() } } } else { openSafari() } } func conversation(mainStatusID: String, state: StatusState) -> ConversationTableViewController { return ConversationTableViewController(for: mainStatusID, state: state, mastodonController: apiController) } func selected(status statusID: String) { self.selected(status: statusID, state: .unknown) } func selected(status statusID: String, state: StatusState) { show(conversation(mainStatusID: statusID, state: state), sender: self) } func compose(editing draft: Draft) { let compose = ComposeHostingController(draft: draft, mastodonController: apiController) let vc = UINavigationController(rootViewController: compose) vc.presentationController?.delegate = compose present(vc, animated: true) } func compose(inReplyToID: String? = nil, mentioningAcct: String? = nil) { let draft = apiController.createDraft(inReplyToID: inReplyToID, mentioningAcct: mentioningAcct) compose(editing: draft) } func loadingLargeImage(url: URL, cache: ImageCache, description: String?, animatingFrom sourceView: UIImageView) -> LoadingLargeImageViewController { let vc = LoadingLargeImageViewController(url: url, cache: cache, imageDescription: description) vc.animationSourceView = sourceView vc.transitioningDelegate = self return vc } func showLoadingLargeImage(url: URL, cache: ImageCache, description: String?, animatingFrom sourceView: UIImageView) { present(loadingLargeImage(url: url, cache: cache, description: description, animatingFrom: sourceView), animated: true) } func gallery(attachments: [Attachment], sourceViews: [UIImageView?], startIndex: Int) -> GalleryViewController { let vc = GalleryViewController(attachments: attachments, sourceViews: sourceViews, 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) -> UIActivityViewController { let customActivites: [UIActivity] = [ OpenInSafariActivity() ] let activityController = UIActivityViewController(activityItems: [url], applicationActivities: customActivites) activityController.completionWithItemsHandler = OpenInSafariActivity.completionHandler(navigator: self, url: url) return activityController } private func moreOptions(forStatus statusID: String) -> UIActivityViewController { guard let status = apiController.persistentContainer.status(for: statusID) else { fatalError("Missing cached status \(statusID)") } guard let url = status.url else { fatalError("Missing url for status \(statusID)") } return UIActivityViewController(activityItems: [url, StatusActivityItemSource(status)], applicationActivities: nil) } private func moreOptions(forAccount accountID: String) -> UIActivityViewController { guard let account = apiController.persistentContainer.account(for: accountID) else { fatalError("Missing cached account \(accountID)") } return UIActivityViewController(activityItems: [account.url, AccountActivityItemSource(account)], applicationActivities: nil) } func showMoreOptions(forStatus statusID: String, sourceView: UIView?) { let vc = moreOptions(forStatus: statusID) vc.popoverPresentationController?.sourceView = sourceView present(vc, animated: true) } func showMoreOptions(forURL url: URL, sourceView: UIView?) { let vc = moreOptions(forURL: url) vc.popoverPresentationController?.sourceView = sourceView present(vc, animated: true) } func showMoreOptions(forAccount accountID: String, sourceView: UIView?) { let vc = moreOptions(forAccount: accountID) vc.popoverPresentationController?.sourceView = sourceView present(vc, animated: true) } func showFollowedByList(accountIDs: [String]) { let vc = AccountListTableViewController(accountIDs: accountIDs, mastodonController: apiController) vc.title = NSLocalizedString("Followed By", comment: "followed by accounts list title") show(vc, sender: self) } func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, statusState state: StatusState, accountIDs: [String]?) -> StatusActionAccountListTableViewController { return StatusActionAccountListTableViewController(actionType: action, statusID: statusID, statusState: state, accountIDs: accountIDs, mastodonController: apiController) } }