2018-10-12 01:20:58 +00:00
|
|
|
//
|
|
|
|
// PreviewViewControllerProvider.swift
|
|
|
|
// Tusker
|
|
|
|
//
|
|
|
|
// Created by Shadowfacts on 10/10/18.
|
|
|
|
// Copyright © 2018 Shadowfacts. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import UIKit
|
2018-10-20 19:35:56 +00:00
|
|
|
import SafariServices
|
2019-06-04 21:04:37 +00:00
|
|
|
import Pachyderm
|
2018-10-12 01:20:58 +00:00
|
|
|
|
2019-06-04 21:04:37 +00:00
|
|
|
protocol MenuPreviewProvider {
|
2018-10-12 01:20:58 +00:00
|
|
|
|
2020-06-27 04:22:14 +00:00
|
|
|
typealias PreviewProviders = (content: UIContextMenuContentPreviewProvider, actions: () -> [UIMenuElement])
|
2019-06-04 21:04:37 +00:00
|
|
|
|
2019-12-14 18:36:05 +00:00
|
|
|
var navigationDelegate: TuskerNavigationDelegate? { get }
|
|
|
|
|
2019-06-04 21:04:37 +00:00
|
|
|
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders?
|
2018-10-12 01:20:58 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-03-21 02:13:04 +00:00
|
|
|
protocol CustomPreviewPresenting {
|
|
|
|
func presentFromPreview(presenter: UIViewController)
|
|
|
|
}
|
|
|
|
|
2019-06-04 21:04:37 +00:00
|
|
|
extension MenuPreviewProvider {
|
|
|
|
|
2020-01-06 00:54:28 +00:00
|
|
|
private var mastodonController: MastodonController? { navigationDelegate?.apiController }
|
|
|
|
|
2020-06-27 04:22:14 +00:00
|
|
|
// Default no-op implementation
|
|
|
|
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func actionsForProfile(accountID: String, sourceView: UIView?) -> [UIMenuElement] {
|
2020-01-06 00:54:28 +00:00
|
|
|
guard let mastodonController = mastodonController,
|
2020-05-02 23:52:35 +00:00
|
|
|
let account = mastodonController.persistentContainer.account(for: accountID) else { return [] }
|
2020-06-27 04:22:14 +00:00
|
|
|
|
|
|
|
var actionsSection: [UIMenuElement] = [
|
2019-07-27 22:53:07 +00:00
|
|
|
createAction(identifier: "sendmessage", title: "Send Message", systemImageName: "envelope", handler: { (_) in
|
2019-12-14 18:36:05 +00:00
|
|
|
self.navigationDelegate?.compose(mentioning: account.acct)
|
2019-07-27 22:53:07 +00:00
|
|
|
}),
|
2020-06-27 04:22:14 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
// todo: handle pre-iOS 14
|
|
|
|
if accountID != mastodonController.account.id,
|
|
|
|
#available(iOS 14.0, *) {
|
|
|
|
actionsSection.append(UIDeferredMenuElement({ (elementHandler) in
|
|
|
|
guard let mastodonController = self.mastodonController else {
|
|
|
|
elementHandler([])
|
|
|
|
return
|
|
|
|
}
|
|
|
|
let request = Client.getRelationships(accounts: [account.id])
|
|
|
|
mastodonController.run(request) { (response) in
|
|
|
|
if case let .success(results, _) = response,
|
|
|
|
let relationship = results.first {
|
|
|
|
let following = relationship.following
|
|
|
|
DispatchQueue.main.async {
|
|
|
|
elementHandler([
|
|
|
|
createAction(identifier: "follow", title: following ? "Unfollow" : "Follow", systemImageName: following ? "person.badge.minus" : "person.badge.minus", handler: { (_) in
|
|
|
|
let request = (following ? Account.unfollow : Account.follow)(accountID)
|
|
|
|
mastodonController.run(request) { (_) in
|
|
|
|
}
|
|
|
|
})
|
|
|
|
])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
let shareSection = [
|
|
|
|
openInSafariAction(url: account.url),
|
2019-07-27 22:53:07 +00:00
|
|
|
createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { (_) in
|
2020-01-18 02:29:53 +00:00
|
|
|
self.navigationDelegate?.showMoreOptions(forAccount: accountID, sourceView: sourceView)
|
2019-07-27 22:53:07 +00:00
|
|
|
})
|
2019-06-04 21:04:37 +00:00
|
|
|
]
|
2020-06-27 04:22:14 +00:00
|
|
|
|
|
|
|
return [
|
|
|
|
UIMenu(title: "", image: nil, identifier: nil, options: [.displayInline], children: actionsSection),
|
|
|
|
UIMenu(title: "", image: nil, identifier: nil, options: [.displayInline], children: shareSection)
|
|
|
|
]
|
2018-10-12 01:20:58 +00:00
|
|
|
}
|
|
|
|
|
2020-01-18 02:29:53 +00:00
|
|
|
func actionsForURL(_ url: URL, sourceView: UIView?) -> [UIAction] {
|
2019-06-04 21:04:37 +00:00
|
|
|
return [
|
2020-06-27 04:22:14 +00:00
|
|
|
openInSafariAction(url: url),
|
2019-07-27 22:53:07 +00:00
|
|
|
createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { (_) in
|
2020-01-18 02:29:53 +00:00
|
|
|
self.navigationDelegate?.showMoreOptions(forURL: url, sourceView: sourceView)
|
2019-07-27 22:53:07 +00:00
|
|
|
})
|
2019-06-04 21:04:37 +00:00
|
|
|
]
|
2018-10-12 01:20:58 +00:00
|
|
|
}
|
2019-06-04 21:04:37 +00:00
|
|
|
|
2020-06-27 04:22:14 +00:00
|
|
|
func actionsForHashtag(_ hashtag: Hashtag, sourceView: UIView?) -> [UIMenuElement] {
|
|
|
|
let account = mastodonController!.accountInfo!
|
|
|
|
let saved = SavedDataManager.shared.isSaved(hashtag: hashtag, for: account)
|
|
|
|
|
|
|
|
let actionsSection = [
|
|
|
|
createAction(identifier: "save", title: saved ? "Unsave Hashtag" : "Save Hashtag", systemImageName: "number", handler: { (_) in
|
|
|
|
if saved {
|
|
|
|
SavedDataManager.shared.remove(hashtag: hashtag, for: account)
|
|
|
|
} else {
|
|
|
|
SavedDataManager.shared.add(hashtag: hashtag, for: account)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
]
|
|
|
|
|
|
|
|
let shareSection = actionsForURL(hashtag.url, sourceView: sourceView)
|
|
|
|
|
|
|
|
return [
|
|
|
|
UIMenu(title: "", image: nil, identifier: nil, options: [.displayInline], children: actionsSection),
|
|
|
|
UIMenu(title: "", image: nil, identifier: nil, options: [.displayInline], children: shareSection)
|
|
|
|
]
|
2019-06-04 21:04:37 +00:00
|
|
|
}
|
|
|
|
|
2020-06-27 04:22:14 +00:00
|
|
|
func actionsForStatus(statusID: String, sourceView: UIView?) -> [UIMenuElement] {
|
2020-01-06 00:54:28 +00:00
|
|
|
guard let mastodonController = mastodonController,
|
2020-05-02 23:52:35 +00:00
|
|
|
let status = mastodonController.persistentContainer.status(for: statusID) else { return [] }
|
2020-06-27 04:22:14 +00:00
|
|
|
let bookmarked = status.bookmarked ?? false
|
|
|
|
let muted = status.muted
|
|
|
|
|
|
|
|
var actionsSection = [
|
2019-07-27 22:53:07 +00:00
|
|
|
createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { (_) in
|
2019-12-14 18:36:05 +00:00
|
|
|
self.navigationDelegate?.reply(to: statusID)
|
2019-07-27 22:53:07 +00:00
|
|
|
}),
|
2020-06-27 04:22:14 +00:00
|
|
|
createAction(identifier: "bookmark", title: bookmarked ? "Unbookmark" : "Bookmark", systemImageName: bookmarked ? "bookmark.fill" : "bookmark", handler: { (_) in
|
|
|
|
let request = (bookmarked ? Status.unbookmark : Status.bookmark)(statusID)
|
|
|
|
self.mastodonController?.run(request) { (response) in
|
|
|
|
if case let .success(status, _) = response {
|
|
|
|
self.mastodonController?.persistentContainer.addOrUpdate(status: status, incrementReferenceCount: false)
|
|
|
|
}
|
|
|
|
}
|
2019-07-27 22:53:07 +00:00
|
|
|
}),
|
2020-06-27 04:22:14 +00:00
|
|
|
createAction(identifier: "mute", title: muted ? "Unmute" : "Mute", systemImageName: muted ? "speaker" : "speaker.slash", handler: { (_) in
|
|
|
|
let request = (muted ? Status.unmuteConversation : Status.muteConversation)(statusID)
|
|
|
|
self.mastodonController?.run(request) { (response) in
|
|
|
|
if case let .success(status, _) = response {
|
|
|
|
self.mastodonController?.persistentContainer.addOrUpdate(status: status, incrementReferenceCount: false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
]
|
|
|
|
|
|
|
|
if mastodonController.account != nil && mastodonController.account.id == status.account.id {
|
|
|
|
let pinned = status.pinned ?? false
|
|
|
|
actionsSection.append(createAction(identifier: "", title: pinned ? "Unpin" : "Pin", systemImageName: pinned ? "pin.slash" : "pin", handler: { (_) in
|
|
|
|
let request = (pinned ? Status.unpin : Status.pin)(statusID)
|
|
|
|
self.mastodonController?.run(request, completion: { (response) in
|
|
|
|
if case let .success(status, _) = response {
|
|
|
|
self.mastodonController?.persistentContainer.addOrUpdate(status: status, incrementReferenceCount: false)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
let shareSection = [
|
|
|
|
openInSafariAction(url: status.url!),
|
2019-07-27 22:53:07 +00:00
|
|
|
createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { (_) in
|
2020-01-18 02:29:53 +00:00
|
|
|
self.navigationDelegate?.showMoreOptions(forStatus: statusID, sourceView: sourceView)
|
2020-06-27 04:22:14 +00:00
|
|
|
}),
|
|
|
|
]
|
|
|
|
|
|
|
|
return [
|
|
|
|
UIMenu(title: "", image: nil, identifier: nil, options: [.displayInline], children: actionsSection),
|
|
|
|
UIMenu(title: "", image: nil, identifier: nil, options: [.displayInline], children: shareSection),
|
2019-06-04 21:04:37 +00:00
|
|
|
]
|
|
|
|
}
|
2019-09-06 21:56:45 +00:00
|
|
|
|
2019-07-27 22:53:07 +00:00
|
|
|
private func createAction(identifier: String, title: String, systemImageName: String, handler: @escaping UIActionHandler) -> UIAction {
|
|
|
|
return UIAction(title: title, image: UIImage(systemName: systemImageName), identifier: UIAction.Identifier(identifier), discoverabilityTitle: nil, attributes: [], state: .off, handler: handler)
|
|
|
|
}
|
|
|
|
|
2020-06-27 04:22:14 +00:00
|
|
|
private func openInSafariAction(url: URL) -> UIAction {
|
|
|
|
return createAction(identifier: "openinsafari", title: "Open in Safari", systemImageName: "safari", handler: { (_) in
|
|
|
|
self.navigationDelegate?.selected(url: url)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-10-12 01:20:58 +00:00
|
|
|
}
|
2020-03-21 02:13:04 +00:00
|
|
|
|
|
|
|
extension LargeImageViewController: CustomPreviewPresenting {
|
|
|
|
func presentFromPreview(presenter: UIViewController) {
|
|
|
|
presenter.present(self, animated: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension GalleryViewController: CustomPreviewPresenting {
|
|
|
|
func presentFromPreview(presenter: UIViewController) {
|
|
|
|
presenter.present(self, animated: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension SFSafariViewController: CustomPreviewPresenting {
|
|
|
|
func presentFromPreview(presenter: UIViewController) {
|
|
|
|
presenter.present(self, animated: true)
|
|
|
|
}
|
|
|
|
}
|