Split MenuActionProvider from MenuPreviewProvider

This commit is contained in:
Shadowfacts 2022-05-01 23:04:56 -04:00
parent c069712c22
commit bf8a294676
24 changed files with 118 additions and 73 deletions

View File

@ -67,3 +67,9 @@ class AccountListTableViewController: EnhancedTableViewController {
extension AccountListTableViewController: TuskerNavigationDelegate { extension AccountListTableViewController: TuskerNavigationDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
} }
extension AccountListTableViewController: ToastableViewController {
}
extension AccountListTableViewController: MenuActionProvider {
}

View File

@ -153,6 +153,15 @@ class BookmarksTableViewController: EnhancedTableViewController {
} }
extension BookmarksTableViewController: TuskerNavigationDelegate {
}
extension BookmarksTableViewController: ToastableViewController {
}
extension BookmarksTableViewController: MenuActionProvider {
}
extension BookmarksTableViewController: StatusTableViewCellDelegate { extension BookmarksTableViewController: StatusTableViewCellDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }

View File

@ -444,6 +444,9 @@ extension ConversationTableViewController: TuskerNavigationDelegate {
} }
} }
extension ConversationTableViewController: MenuActionProvider {
}
extension ConversationTableViewController: StatusTableViewCellDelegate { extension ConversationTableViewController: StatusTableViewCellDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {

View File

@ -134,8 +134,10 @@ extension ProfileDirectoryViewController: TuskerNavigationDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
} }
extension ProfileDirectoryViewController: MenuPreviewProvider { extension ProfileDirectoryViewController: ToastableViewController {
var navigationDelegate: TuskerNavigationDelegate? { self } }
extension ProfileDirectoryViewController: MenuActionProvider {
} }
extension ProfileDirectoryViewController: UICollectionViewDelegate { extension ProfileDirectoryViewController: UICollectionViewDelegate {

View File

@ -110,6 +110,8 @@ extension TrendingHashtagsViewController: TuskerNavigationDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
} }
extension TrendingHashtagsViewController: MenuPreviewProvider { extension TrendingHashtagsViewController: ToastableViewController {
var navigationDelegate: TuskerNavigationDelegate? { self } }
extension TrendingHashtagsViewController: MenuActionProvider {
} }

View File

@ -104,6 +104,8 @@ extension TrendingLinksViewController: TuskerNavigationDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
} }
extension TrendingLinksViewController: MenuPreviewProvider { extension TrendingLinksViewController: ToastableViewController {
var navigationDelegate: TuskerNavigationDelegate? { self } }
extension TrendingLinksViewController: MenuActionProvider {
} }

View File

@ -85,6 +85,12 @@ extension TrendingStatusesViewController: TuskerNavigationDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
} }
extension TrendingStatusesViewController: ToastableViewController {
}
extension TrendingStatusesViewController: MenuActionProvider {
}
extension TrendingStatusesViewController: StatusTableViewCellDelegate { extension TrendingStatusesViewController: StatusTableViewCellDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
tableView.beginUpdates() tableView.beginUpdates()

View File

@ -176,3 +176,9 @@ extension EditListAccountsViewController: SearchResultsViewControllerDelegate {
extension EditListAccountsViewController: TuskerNavigationDelegate { extension EditListAccountsViewController: TuskerNavigationDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
} }
extension EditListAccountsViewController: ToastableViewController {
}
extension EditListAccountsViewController: MenuActionProvider {
}

View File

@ -250,6 +250,9 @@ extension NotificationsTableViewController: TuskerNavigationDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
} }
extension NotificationsTableViewController: MenuActionProvider {
}
extension NotificationsTableViewController: StatusTableViewCellDelegate { extension NotificationsTableViewController: StatusTableViewCellDelegate {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {
cellHeightChanged() cellHeightChanged()

View File

@ -288,6 +288,15 @@ extension SearchResultsViewController: UISearchBarDelegate {
} }
} }
extension SearchResultsViewController: TuskerNavigationDelegate {
}
extension SearchResultsViewController: ToastableViewController {
}
extension SearchResultsViewController: MenuActionProvider {
}
extension SearchResultsViewController: StatusTableViewCellDelegate { extension SearchResultsViewController: StatusTableViewCellDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {

View File

@ -144,6 +144,15 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
} }
extension StatusActionAccountListTableViewController: TuskerNavigationDelegate {
}
extension StatusActionAccountListTableViewController: ToastableViewController {
}
extension StatusActionAccountListTableViewController: MenuActionProvider {
}
extension StatusActionAccountListTableViewController: StatusTableViewCellDelegate { extension StatusActionAccountListTableViewController: StatusTableViewCellDelegate {
var apiController: MastodonController { mastodonController } var apiController: MastodonController { mastodonController }
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) { func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) {

View File

@ -294,6 +294,9 @@ extension TimelineTableViewController: StatusTableViewCellDelegate {
} }
} }
extension TimelineTableViewController: MenuActionProvider {
}
extension TimelineTableViewController: UITableViewDataSourcePrefetching, StatusTablePrefetching { extension TimelineTableViewController: UITableViewDataSourcePrefetching, StatusTablePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
let ids: [String] = indexPaths.compactMap { let ids: [String] = indexPaths.compactMap {

View File

@ -10,29 +10,33 @@ import UIKit
import SafariServices import SafariServices
import Pachyderm import Pachyderm
protocol MenuPreviewProvider: AnyObject { protocol MenuActionProvider: AnyObject {
var navigationDelegate: TuskerNavigationDelegate? { get }
var toastableViewController: ToastableViewController? { get }
}
protocol MenuPreviewProvider: AnyObject {
typealias PreviewProviders = (content: UIContextMenuContentPreviewProvider, actions: () -> [UIMenuElement]) typealias PreviewProviders = (content: UIContextMenuContentPreviewProvider, actions: () -> [UIMenuElement])
var navigationDelegate: TuskerNavigationDelegate? { get }
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders?
} }
protocol CustomPreviewPresenting { protocol CustomPreviewPresenting {
func presentFromPreview(presenter: UIViewController) func presentFromPreview(presenter: UIViewController)
} }
extension MenuPreviewProvider { extension MenuActionProvider where Self: TuskerNavigationDelegate {
var navigationDelegate: TuskerNavigationDelegate? { self }
}
extension MenuActionProvider where Self: ToastableViewController {
var toastableViewController: ToastableViewController? { self }
}
extension MenuActionProvider {
private var mastodonController: MastodonController? { navigationDelegate?.apiController } private var mastodonController: MastodonController? { navigationDelegate?.apiController }
// Default no-op implementation
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
return nil
}
func actionsForProfile(accountID: String, sourceView: UIView?) -> [UIMenuElement] { func actionsForProfile(accountID: String, sourceView: UIView?) -> [UIMenuElement] {
guard let mastodonController = mastodonController, guard let mastodonController = mastodonController,
let account = mastodonController.persistentContainer.account(for: accountID) else { return [] } let account = mastodonController.persistentContainer.account(for: accountID) else { return [] }

View File

@ -11,7 +11,7 @@ import SwiftSoup
class AccountTableViewCell: UITableViewCell { class AccountTableViewCell: UITableViewCell {
weak var delegate: TuskerNavigationDelegate? weak var delegate: (TuskerNavigationDelegate & MenuActionProvider)?
var mastodonController: MastodonController! { delegate?.apiController } var mastodonController: MastodonController! { delegate?.apiController }
@IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var avatarImageView: UIImageView!
@ -98,13 +98,11 @@ extension AccountTableViewCell: SelectableTableViewCell {
} }
extension AccountTableViewCell: MenuPreviewProvider { extension AccountTableViewCell: MenuPreviewProvider {
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 } guard let mastodonController = mastodonController else { return nil }
return ( return (
content: { ProfileViewController(accountID: self.accountID, mastodonController: mastodonController) }, content: { ProfileViewController(accountID: self.accountID, mastodonController: mastodonController) },
actions: { self.actionsForProfile(accountID: self.accountID, sourceView: self.avatarImageView) } actions: { self.delegate?.actionsForProfile(accountID: self.accountID, sourceView: self.avatarImageView) ?? [] }
) )
} }
} }

View File

@ -243,9 +243,10 @@ extension ContentTextView: UITextViewDelegate {
} }
} }
extension ContentTextView: MenuPreviewProvider { extension ContentTextView: MenuActionProvider {
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { var toastableViewController: ToastableViewController? {
fatalError("unimplemented") // todo: pass this down through the text view
nil
} }
} }

View File

@ -12,7 +12,7 @@ import SwiftSoup
class ActionNotificationGroupTableViewCell: UITableViewCell { class ActionNotificationGroupTableViewCell: UITableViewCell {
weak var delegate: TuskerNavigationDelegate? weak var delegate: (TuskerNavigationDelegate & MenuActionProvider)?
var mastodonController: MastodonController! { delegate?.apiController } var mastodonController: MastodonController! { delegate?.apiController }
@IBOutlet weak var actionImageView: UIImageView! @IBOutlet weak var actionImageView: UIImageView!
@ -244,8 +244,6 @@ extension ActionNotificationGroupTableViewCell: SelectableTableViewCell {
} }
extension ActionNotificationGroupTableViewCell: MenuPreviewProvider { extension ActionNotificationGroupTableViewCell: MenuPreviewProvider {
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
return (content: { return (content: {
let notifications = self.group.notifications let notifications = self.group.notifications

View File

@ -11,7 +11,7 @@ import Pachyderm
class FollowNotificationGroupTableViewCell: UITableViewCell { class FollowNotificationGroupTableViewCell: UITableViewCell {
weak var delegate: TuskerNavigationDelegate? weak var delegate: (TuskerNavigationDelegate & MenuActionProvider)?
var mastodonController: MastodonController! { delegate?.apiController } var mastodonController: MastodonController! { delegate?.apiController }
@IBOutlet weak var avatarStackView: UIStackView! @IBOutlet weak var avatarStackView: UIStackView!
@ -196,8 +196,6 @@ extension FollowNotificationGroupTableViewCell: SelectableTableViewCell {
} }
extension FollowNotificationGroupTableViewCell: MenuPreviewProvider { extension FollowNotificationGroupTableViewCell: MenuPreviewProvider {
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 } guard let mastodonController = mastodonController else { return nil }
let accountIDs = self.group.notifications.map { $0.account.id } let accountIDs = self.group.notifications.map { $0.account.id }
@ -209,7 +207,7 @@ extension FollowNotificationGroupTableViewCell: MenuPreviewProvider {
} }
}, actions: { }, actions: {
if accountIDs.count == 1 { if accountIDs.count == 1 {
return self.actionsForProfile(accountID: accountIDs.first!, sourceView: self) return self.delegate?.actionsForProfile(accountID: accountIDs.first!, sourceView: self) ?? []
} else { } else {
return [] return []
} }

View File

@ -11,7 +11,7 @@ import Pachyderm
class FollowRequestNotificationTableViewCell: UITableViewCell { class FollowRequestNotificationTableViewCell: UITableViewCell {
weak var delegate: TuskerNavigationDelegate? weak var delegate: (TuskerNavigationDelegate & MenuActionProvider)?
var mastodonController: MastodonController! { delegate?.apiController } var mastodonController: MastodonController! { delegate?.apiController }
@IBOutlet weak var stackView: UIStackView! @IBOutlet weak var stackView: UIStackView!
@ -169,8 +169,6 @@ extension FollowRequestNotificationTableViewCell: SelectableTableViewCell {
} }
extension FollowRequestNotificationTableViewCell: MenuPreviewProvider { extension FollowRequestNotificationTableViewCell: MenuPreviewProvider {
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 } guard let mastodonController = mastodonController else { return nil }
return (content: { return (content: {

View File

@ -12,7 +12,7 @@ import SwiftSoup
class PollFinishedTableViewCell: UITableViewCell { class PollFinishedTableViewCell: UITableViewCell {
weak var delegate: TuskerNavigationDelegate? weak var delegate: (TuskerNavigationDelegate & MenuActionProvider)?
var mastodonController: MastodonController? { delegate?.apiController } var mastodonController: MastodonController? { delegate?.apiController }
@IBOutlet weak var displayNameLabel: EmojiLabel! @IBOutlet weak var displayNameLabel: EmojiLabel!
@ -91,8 +91,6 @@ extension PollFinishedTableViewCell: SelectableTableViewCell {
} }
extension PollFinishedTableViewCell: MenuPreviewProvider { extension PollFinishedTableViewCell: MenuPreviewProvider {
var navigationDelegate: TuskerNavigationDelegate? { delegate }
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
guard let delegate = delegate, guard let delegate = delegate,
let statusID = notification?.status?.id, let statusID = notification?.status?.id,
@ -102,7 +100,7 @@ extension PollFinishedTableViewCell: MenuPreviewProvider {
return (content: { return (content: {
delegate.conversation(mainStatusID: statusID, state: .unknown) delegate.conversation(mainStatusID: statusID, state: .unknown)
}, actions: { }, actions: {
self.actionsForStatus(status, sourceView: self) delegate.actionsForStatus(status, sourceView: self)
}) })
} }
} }

View File

@ -10,7 +10,7 @@ import UIKit
import Pachyderm import Pachyderm
import Combine import Combine
protocol ProfileHeaderViewDelegate: TuskerNavigationDelegate { protocol ProfileHeaderViewDelegate: TuskerNavigationDelegate, MenuActionProvider {
func profileHeader(_ headerView: ProfileHeaderView, selectedPostsIndexChangedTo newIndex: Int) func profileHeader(_ headerView: ProfileHeaderView, selectedPostsIndexChangedTo newIndex: Int)
} }
@ -106,7 +106,7 @@ class ProfileHeaderView: UIView {
updateImages(account: account) updateImages(account: account)
moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: actionsForProfile(accountID: accountID, sourceView: moreButton)) moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: delegate?.actionsForProfile(accountID: accountID, sourceView: moreButton) ?? [])
noteTextView.navigationDelegate = delegate noteTextView.navigationDelegate = delegate
noteTextView.setTextFromHtml(account.note) noteTextView.setTextFromHtml(account.note)
@ -272,7 +272,3 @@ extension ProfileHeaderView: UIPointerInteractionDelegate {
return UIPointerStyle(effect: .lift(preview), shape: .none) return UIPointerStyle(effect: .lift(preview), shape: .none)
} }
} }
extension ProfileHeaderView: MenuPreviewProvider {
var navigationDelegate: TuskerNavigationDelegate? { delegate }
}

View File

@ -11,11 +11,11 @@ import Pachyderm
import Combine import Combine
import AVKit import AVKit
protocol StatusTableViewCellDelegate: TuskerNavigationDelegate { protocol StatusTableViewCellDelegate: TuskerNavigationDelegate, MenuActionProvider {
func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell) func statusCellCollapsedStateChanged(_ cell: BaseStatusTableViewCell)
} }
class BaseStatusTableViewCell: UITableViewCell, MenuPreviewProvider { class BaseStatusTableViewCell: UITableViewCell {
weak var delegate: StatusTableViewCellDelegate? { weak var delegate: StatusTableViewCellDelegate? {
didSet { didSet {
@ -153,7 +153,8 @@ class BaseStatusTableViewCell: UITableViewCell, MenuPreviewProvider {
cardView.card = status.card cardView.card = status.card
cardView.isHidden = status.card == nil cardView.isHidden = status.card == nil
cardView.navigationDelegate = navigationDelegate cardView.navigationDelegate = delegate
cardView.actionProvider = delegate
attachmentsView.updateUI(status: status) attachmentsView.updateUI(status: status)
@ -206,7 +207,7 @@ class BaseStatusTableViewCell: UITableViewCell, MenuPreviewProvider {
// keep menu in sync with changed states e.g. bookmarked, muted // keep menu in sync with changed states e.g. bookmarked, muted
// do not include reply action here, because the cell already contains a button for it // do not include reply action here, because the cell already contains a button for it
moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: actionsForStatus(status, sourceView: moreButton, includeReply: false)) moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: delegate?.actionsForStatus(status, sourceView: moreButton, includeReply: false) ?? [])
pollView.isHidden = status.poll == nil pollView.isHidden = status.poll == nil
pollView.mastodonController = mastodonController pollView.mastodonController = mastodonController
@ -326,13 +327,6 @@ class BaseStatusTableViewCell: UITableViewCell, MenuPreviewProvider {
showStatusAutomatically = false showStatusAutomatically = false
} }
// MARK: - MenuPreviewProvider
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
return nil
}
// MARK: - Interaction // MARK: - Interaction
@IBAction func collapseButtonPressed() { @IBAction func collapseButtonPressed() {

View File

@ -112,7 +112,7 @@ extension ConversationMainStatusTableViewCell: UIContextMenuInteractionDelegate
return UIContextMenuConfiguration(identifier: nil) { return UIContextMenuConfiguration(identifier: nil) {
ProfileViewController(accountID: self.accountID, mastodonController: self.mastodonController) ProfileViewController(accountID: self.accountID, mastodonController: self.mastodonController)
} actionProvider: { (_) in } actionProvider: { (_) in
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: self.actionsForProfile(accountID: self.accountID, sourceView: self.avatarImageView)) return UIMenu(title: "", image: nil, identifier: nil, options: [], children: self.delegate?.actionsForProfile(accountID: self.accountID, sourceView: self.avatarImageView) ?? [])
} }
} }
} }

View File

@ -14,6 +14,7 @@ import WebURLFoundationExtras
class StatusCardView: UIView { class StatusCardView: UIView {
weak var navigationDelegate: TuskerNavigationDelegate? weak var navigationDelegate: TuskerNavigationDelegate?
weak var actionProvider: MenuActionProvider?
var card: Card? { var card: Card? {
didSet { didSet {
@ -212,9 +213,6 @@ class StatusCardView: UIView {
} }
extension StatusCardView: MenuPreviewProvider {
}
extension StatusCardView: UIContextMenuInteractionDelegate { extension StatusCardView: UIContextMenuInteractionDelegate {
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? { func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
guard let card = card else { return nil } guard let card = card else { return nil }
@ -222,7 +220,7 @@ extension StatusCardView: UIContextMenuInteractionDelegate {
return UIContextMenuConfiguration(identifier: nil) { return UIContextMenuConfiguration(identifier: nil) {
return SFSafariViewController(url: URL(card.url)!) return SFSafariViewController(url: URL(card.url)!)
} actionProvider: { (_) in } actionProvider: { (_) in
let actions = self.actionsForURL(URL(card.url)!, sourceView: self) let actions = self.actionProvider?.actionsForURL(URL(card.url)!, sourceView: self) ?? []
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: actions) return UIMenu(title: "", image: nil, identifier: nil, options: [], children: actions)
} }
} }

View File

@ -214,17 +214,6 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
reply() reply()
} }
override func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> BaseStatusTableViewCell.PreviewProviders? {
guard let mastodonController = mastodonController,
let status = mastodonController.persistentContainer.status(for: statusID) else {
return nil
}
return (
content: { ConversationTableViewController(for: self.statusID, state: self.statusState.copy(), mastodonController: mastodonController) },
actions: { self.actionsForStatus(status, sourceView: self) }
)
}
// MARK: - Accessibility // MARK: - Accessibility
override var accessibilityLabel: String? { override var accessibilityLabel: String? {
@ -377,13 +366,13 @@ extension TimelineStatusTableViewCell: UIContextMenuInteractionDelegate {
return UIContextMenuConfiguration(identifier: nil) { return UIContextMenuConfiguration(identifier: nil) {
ProfileViewController(accountID: self.accountID, mastodonController: self.mastodonController) ProfileViewController(accountID: self.accountID, mastodonController: self.mastodonController)
} actionProvider: { (_) in } actionProvider: { (_) in
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: self.actionsForProfile(accountID: self.accountID, sourceView: self.avatarImageView)) return UIMenu(title: "", image: nil, identifier: nil, options: [], children: self.delegate?.actionsForProfile(accountID: self.accountID, sourceView: self.avatarImageView) ?? [])
} }
} }
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) { func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
if let viewController = animator.previewViewController, if let viewController = animator.previewViewController,
let delegate = navigationDelegate { let delegate = delegate {
animator.preferredCommitStyle = .pop animator.preferredCommitStyle = .pop
animator.addCompletion { animator.addCompletion {
if let customPresenting = viewController as? CustomPreviewPresenting { if let customPresenting = viewController as? CustomPreviewPresenting {
@ -396,3 +385,16 @@ extension TimelineStatusTableViewCell: UIContextMenuInteractionDelegate {
} }
} }
extension TimelineStatusTableViewCell: MenuPreviewProvider {
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
guard let mastodonController = mastodonController,
let status = mastodonController.persistentContainer.status(for: statusID) else {
return nil
}
return (
content: { ConversationTableViewController(for: self.statusID, state: self.statusState.copy(), mastodonController: mastodonController) },
actions: { self.delegate?.actionsForStatus(status, sourceView: self) ?? [] }
)
}
}