forked from shadowfacts/Tusker
Refactor menu actions to allow presenting from menu bar items
This commit is contained in:
parent
c6da754875
commit
ab8e498cee
|
@ -293,7 +293,7 @@
|
||||||
D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */; };
|
D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */; };
|
||||||
D6DF95C12533F5DE0027A9B6 /* RelationshipMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DF95C02533F5DE0027A9B6 /* RelationshipMO.swift */; };
|
D6DF95C12533F5DE0027A9B6 /* RelationshipMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DF95C02533F5DE0027A9B6 /* RelationshipMO.swift */; };
|
||||||
D6DFC69E242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */; };
|
D6DFC69E242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */; };
|
||||||
D6DFC6A0242C4CCC00ACC392 /* WeakArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */; };
|
D6DFC6A0242C4CCC00ACC392 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69F242C4CCC00ACC392 /* Weak.swift */; };
|
||||||
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E0DC8D216EDF1E00369478 /* Previewing.swift */; };
|
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E0DC8D216EDF1E00369478 /* Previewing.swift */; };
|
||||||
D6E343AB265AAD6B00C4AA01 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D6E343AA265AAD6B00C4AA01 /* Media.xcassets */; };
|
D6E343AB265AAD6B00C4AA01 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D6E343AA265AAD6B00C4AA01 /* Media.xcassets */; };
|
||||||
D6E343AD265AAD6B00C4AA01 /* ActionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E343AC265AAD6B00C4AA01 /* ActionViewController.swift */; };
|
D6E343AD265AAD6B00C4AA01 /* ActionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E343AC265AAD6B00C4AA01 /* ActionViewController.swift */; };
|
||||||
|
@ -668,7 +668,7 @@
|
||||||
D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preferences+Notification.swift"; sourceTree = "<group>"; };
|
D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preferences+Notification.swift"; sourceTree = "<group>"; };
|
||||||
D6DF95C02533F5DE0027A9B6 /* RelationshipMO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelationshipMO.swift; sourceTree = "<group>"; };
|
D6DF95C02533F5DE0027A9B6 /* RelationshipMO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelationshipMO.swift; sourceTree = "<group>"; };
|
||||||
D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackpadScrollGestureRecognizer.swift; sourceTree = "<group>"; };
|
D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackpadScrollGestureRecognizer.swift; sourceTree = "<group>"; };
|
||||||
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakArray.swift; sourceTree = "<group>"; };
|
D6DFC69F242C4CCC00ACC392 /* Weak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; };
|
||||||
D6E0DC8D216EDF1E00369478 /* Previewing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Previewing.swift; sourceTree = "<group>"; };
|
D6E0DC8D216EDF1E00369478 /* Previewing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Previewing.swift; sourceTree = "<group>"; };
|
||||||
D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OpenInTusker.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OpenInTusker.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D6E343AA265AAD6B00C4AA01 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
|
D6E343AA265AAD6B00C4AA01 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
|
||||||
|
@ -1421,7 +1421,7 @@
|
||||||
D6945C2E23AC47C3005C403C /* SavedDataManager.swift */,
|
D6945C2E23AC47C3005C403C /* SavedDataManager.swift */,
|
||||||
D6895DE828D962C2006341DA /* TimelineLikeController.swift */,
|
D6895DE828D962C2006341DA /* TimelineLikeController.swift */,
|
||||||
D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */,
|
D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */,
|
||||||
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */,
|
D6DFC69F242C4CCC00ACC392 /* Weak.swift */,
|
||||||
D63D8DF32850FE7A008D95E1 /* ViewTags.swift */,
|
D63D8DF32850FE7A008D95E1 /* ViewTags.swift */,
|
||||||
D6D4DDD6212518A200E1C4BB /* Assets.xcassets */,
|
D6D4DDD6212518A200E1C4BB /* Assets.xcassets */,
|
||||||
D6AEBB3F2321640F00E5038B /* Activities */,
|
D6AEBB3F2321640F00E5038B /* Activities */,
|
||||||
|
@ -2010,7 +2010,7 @@
|
||||||
D6945C3223AC4D36005C403C /* HashtagTimelineViewController.swift in Sources */,
|
D6945C3223AC4D36005C403C /* HashtagTimelineViewController.swift in Sources */,
|
||||||
D647D92824257BEB0005044F /* AttachmentPreviewViewController.swift in Sources */,
|
D647D92824257BEB0005044F /* AttachmentPreviewViewController.swift in Sources */,
|
||||||
D66362752137068A00C9CBA2 /* Visibility+Helpers.swift in Sources */,
|
D66362752137068A00C9CBA2 /* Visibility+Helpers.swift in Sources */,
|
||||||
D6DFC6A0242C4CCC00ACC392 /* WeakArray.swift in Sources */,
|
D6DFC6A0242C4CCC00ACC392 /* Weak.swift in Sources */,
|
||||||
D6C693FC2162FE6F007D6A6D /* LoadingViewController.swift in Sources */,
|
D6C693FC2162FE6F007D6A6D /* LoadingViewController.swift in Sources */,
|
||||||
D61ABEF828EFC3F900B29151 /* ProfileStatusesViewController.swift in Sources */,
|
D61ABEF828EFC3F900B29151 /* ProfileStatusesViewController.swift in Sources */,
|
||||||
D6ADB6EA28E91C30009924AB /* TimelineStatusCollectionViewCell.swift in Sources */,
|
D6ADB6EA28E91C30009924AB /* TimelineStatusCollectionViewCell.swift in Sources */,
|
||||||
|
|
|
@ -125,7 +125,7 @@ private func createReblogAction(status: StatusMO, container: StatusSwipeActionCo
|
||||||
|
|
||||||
private func createShareAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction {
|
private func createShareAction(status: StatusMO, container: StatusSwipeActionContainer) -> UIContextualAction {
|
||||||
let action = UIContextualAction(style: .normal, title: "Share") { [unowned container] _, _, completion in
|
let action = UIContextualAction(style: .normal, title: "Share") { [unowned container] _, _, completion in
|
||||||
container.navigationDelegate.showMoreOptions(forStatus: status.id, sourceView: container)
|
container.navigationDelegate.showMoreOptions(forStatus: status.id, source: .view(container))
|
||||||
completion(true)
|
completion(true)
|
||||||
}
|
}
|
||||||
// bold to more closesly match other action symbols
|
// bold to more closesly match other action symbols
|
||||||
|
|
|
@ -88,7 +88,7 @@ extension AccountListViewController: UICollectionViewDelegate {
|
||||||
return UIContextMenuConfiguration {
|
return UIContextMenuConfiguration {
|
||||||
ProfileViewController(accountID: id, mastodonController: self.mastodonController)
|
ProfileViewController(accountID: id, mastodonController: self.mastodonController)
|
||||||
} actionProvider: { _ in
|
} actionProvider: { _ in
|
||||||
UIMenu(children: self.actionsForProfile(accountID: id, sourceView: cell))
|
UIMenu(children: self.actionsForProfile(accountID: id, source: .view(cell)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ extension ProfileDirectoryViewController: UICollectionViewDelegate {
|
||||||
return UIContextMenuConfiguration(identifier: nil) {
|
return UIContextMenuConfiguration(identifier: nil) {
|
||||||
return ProfileViewController(accountID: account.id, mastodonController: self.mastodonController)
|
return ProfileViewController(accountID: account.id, mastodonController: self.mastodonController)
|
||||||
} actionProvider: { (_) in
|
} actionProvider: { (_) in
|
||||||
let actions = self.actionsForProfile(accountID: account.id, sourceView: self.collectionView.cellForItem(at: indexPath))
|
let actions = self.actionsForProfile(accountID: account.id, source: .view(self.collectionView.cellForItem(at: indexPath)))
|
||||||
return UIMenu(children: actions)
|
return UIMenu(children: actions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ extension TrendingHashtagsViewController: UICollectionViewDelegate {
|
||||||
return UIContextMenuConfiguration(identifier: nil) {
|
return UIContextMenuConfiguration(identifier: nil) {
|
||||||
HashtagTimelineViewController(for: hashtag, mastodonController: self.mastodonController)
|
HashtagTimelineViewController(for: hashtag, mastodonController: self.mastodonController)
|
||||||
} actionProvider: { (_) in
|
} actionProvider: { (_) in
|
||||||
UIMenu(children: self.actionsForHashtag(hashtag, sourceView: self.collectionView.cellForItem(at: indexPath)))
|
UIMenu(children: self.actionsForHashtag(hashtag, source: .view(self.collectionView.cellForItem(at: indexPath))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@ extension SearchViewController: UICollectionViewDelegate {
|
||||||
return UIContextMenuConfiguration(identifier: nil) {
|
return UIContextMenuConfiguration(identifier: nil) {
|
||||||
HashtagTimelineViewController(for: hashtag, mastodonController: self.mastodonController)
|
HashtagTimelineViewController(for: hashtag, mastodonController: self.mastodonController)
|
||||||
} actionProvider: { (_) in
|
} actionProvider: { (_) in
|
||||||
UIMenu(children: self.actionsForHashtag(hashtag, sourceView: self.collectionView.cellForItem(at: indexPath)))
|
UIMenu(children: self.actionsForHashtag(hashtag, source: .view(self.collectionView.cellForItem(at: indexPath))))
|
||||||
}
|
}
|
||||||
|
|
||||||
case let .link(card):
|
case let .link(card):
|
||||||
|
|
|
@ -206,7 +206,7 @@ extension StatusActionAccountListViewController: UICollectionViewDelegate {
|
||||||
return UIContextMenuConfiguration {
|
return UIContextMenuConfiguration {
|
||||||
ProfileViewController(accountID: id, mastodonController: self.mastodonController)
|
ProfileViewController(accountID: id, mastodonController: self.mastodonController)
|
||||||
} actionProvider: { _ in
|
} actionProvider: { _ in
|
||||||
UIMenu(children: self.actionsForProfile(accountID: id, sourceView: cell))
|
UIMenu(children: self.actionsForProfile(accountID: id, source: .view(cell)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,15 +39,15 @@ extension MenuActionProvider {
|
||||||
|
|
||||||
private var mastodonController: MastodonController? { navigationDelegate?.apiController }
|
private var mastodonController: MastodonController? { navigationDelegate?.apiController }
|
||||||
|
|
||||||
func actionsForProfile(accountID: String, sourceView: UIView?) -> [UIMenuElement] {
|
func actionsForProfile(accountID: String, source: PopoverSource) -> [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 [] }
|
||||||
|
|
||||||
var shareSection = [
|
var shareSection = [
|
||||||
openInSafariAction(url: account.url),
|
openInSafariAction(url: account.url),
|
||||||
createAction(identifier: "share", title: "Share", systemImageName: "square.and.arrow.up", handler: { [weak self, weak sourceView] (_) in
|
createAction(identifier: "share", title: "Share", systemImageName: "square.and.arrow.up", handler: { [weak self] (_) in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.navigationDelegate?.showMoreOptions(forAccount: accountID, sourceView: sourceView)
|
self.navigationDelegate?.showMoreOptions(forAccount: accountID, source: source)
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -95,17 +95,17 @@ extension MenuActionProvider {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
func actionsForURL(_ url: URL, sourceView: UIView?) -> [UIAction] {
|
func actionsForURL(_ url: URL, source: PopoverSource) -> [UIAction] {
|
||||||
return [
|
return [
|
||||||
openInSafariAction(url: url),
|
openInSafariAction(url: url),
|
||||||
createAction(identifier: "share", title: "Share", systemImageName: "square.and.arrow.up", handler: { [weak self, weak sourceView] (_) in
|
createAction(identifier: "share", title: "Share", systemImageName: "square.and.arrow.up", handler: { [weak self] (_) in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.navigationDelegate?.showMoreOptions(forURL: url, sourceView: sourceView)
|
self.navigationDelegate?.showMoreOptions(forURL: url, source: source)
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
func actionsForHashtag(_ hashtag: Hashtag, sourceView: UIView?) -> [UIMenuElement] {
|
func actionsForHashtag(_ hashtag: Hashtag, source: PopoverSource) -> [UIMenuElement] {
|
||||||
let actionsSection: [UIMenuElement]
|
let actionsSection: [UIMenuElement]
|
||||||
if let mastodonController = mastodonController,
|
if let mastodonController = mastodonController,
|
||||||
mastodonController.loggedIn {
|
mastodonController.loggedIn {
|
||||||
|
@ -127,7 +127,7 @@ extension MenuActionProvider {
|
||||||
|
|
||||||
let shareSection: [UIMenuElement]
|
let shareSection: [UIMenuElement]
|
||||||
if let url = URL(hashtag.url) {
|
if let url = URL(hashtag.url) {
|
||||||
shareSection = actionsForURL(url, sourceView: sourceView)
|
shareSection = actionsForURL(url, source: source)
|
||||||
} else {
|
} else {
|
||||||
shareSection = []
|
shareSection = []
|
||||||
}
|
}
|
||||||
|
@ -138,16 +138,16 @@ extension MenuActionProvider {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
func actionsForStatus(_ status: StatusMO, sourceView: UIView?, includeStatusButtonActions: Bool = true) -> [UIMenuElement] {
|
func actionsForStatus(_ status: StatusMO, source: PopoverSource, includeStatusButtonActions: Bool = true) -> [UIMenuElement] {
|
||||||
guard let mastodonController = mastodonController else { return [] }
|
guard let mastodonController = mastodonController else { return [] }
|
||||||
|
|
||||||
guard let accountID = mastodonController.accountInfo?.id else {
|
guard let accountID = mastodonController.accountInfo?.id else {
|
||||||
// user is logged out
|
// user is logged out
|
||||||
return [
|
return [
|
||||||
openInSafariAction(url: status.url!),
|
openInSafariAction(url: status.url!),
|
||||||
createAction(identifier: "share", title: "Share", systemImageName: "square.and.arrow.up", handler: { [weak self, weak sourceView] (_) in
|
createAction(identifier: "share", title: "Share", systemImageName: "square.and.arrow.up", handler: { [weak self] (_) in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.navigationDelegate?.showMoreOptions(forStatus: status.id, sourceView: sourceView)
|
self.navigationDelegate?.showMoreOptions(forStatus: status.id, source: source)
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -271,9 +271,9 @@ extension MenuActionProvider {
|
||||||
} else {
|
} else {
|
||||||
Logging.general.fault("Status missing URL: id=\(status.id, privacy: .public), reblog=\((status.reblog?.id).debugDescription, privacy: .public)")
|
Logging.general.fault("Status missing URL: id=\(status.id, privacy: .public), reblog=\((status.reblog?.id).debugDescription, privacy: .public)")
|
||||||
}
|
}
|
||||||
shareSection.append(createAction(identifier: "share", title: "Share", systemImageName: "square.and.arrow.up", handler: { [weak self, weak sourceView] (_) in
|
shareSection.append(createAction(identifier: "share", title: "Share", systemImageName: "square.and.arrow.up", handler: { [weak self] (_) in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.navigationDelegate?.showMoreOptions(forStatus: status.id, sourceView: sourceView)
|
self.navigationDelegate?.showMoreOptions(forStatus: status.id, source: source)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
addOpenInNewWindow(actions: &shareSection, activity: UserActivityManager.showConversationActivity(mainStatusID: status.id, accountID: accountID))
|
addOpenInNewWindow(actions: &shareSection, activity: UserActivityManager.showConversationActivity(mainStatusID: status.id, accountID: accountID))
|
||||||
|
|
|
@ -159,21 +159,21 @@ extension TuskerNavigationDelegate {
|
||||||
return UIActivityViewController(activityItems: [account.url, AccountActivityItemSource(account)], applicationActivities: nil)
|
return UIActivityViewController(activityItems: [account.url, AccountActivityItemSource(account)], applicationActivities: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func showMoreOptions(forStatus statusID: String, sourceView: UIView?) {
|
func showMoreOptions(forStatus statusID: String, source: PopoverSource) {
|
||||||
let vc = moreOptions(forStatus: statusID)
|
let vc = moreOptions(forStatus: statusID)
|
||||||
vc.popoverPresentationController?.sourceView = sourceView
|
source.apply(to: vc)
|
||||||
present(vc, animated: true)
|
present(vc, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func showMoreOptions(forURL url: URL, sourceView: UIView?) {
|
func showMoreOptions(forURL url: URL, source: PopoverSource) {
|
||||||
let vc = moreOptions(forURL: url)
|
let vc = moreOptions(forURL: url)
|
||||||
vc.popoverPresentationController?.sourceView = sourceView
|
source.apply(to: vc)
|
||||||
present(vc, animated: true)
|
present(vc, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func showMoreOptions(forAccount accountID: String, sourceView: UIView?) {
|
func showMoreOptions(forAccount accountID: String, source: PopoverSource) {
|
||||||
let vc = moreOptions(forAccount: accountID)
|
let vc = moreOptions(forAccount: accountID)
|
||||||
vc.popoverPresentationController?.sourceView = sourceView
|
source.apply(to: vc)
|
||||||
present(vc, animated: true)
|
present(vc, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,3 +188,30 @@ extension TuskerNavigationDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PopoverSource {
|
||||||
|
case none
|
||||||
|
case view(WeakHolder<UIView>)
|
||||||
|
case barButtonItem(WeakHolder<UIBarButtonItem>)
|
||||||
|
|
||||||
|
func apply(to viewController: UIViewController) {
|
||||||
|
if let popoverPresentationController = viewController.popoverPresentationController {
|
||||||
|
switch self {
|
||||||
|
case .none:
|
||||||
|
break
|
||||||
|
case .view(let view):
|
||||||
|
popoverPresentationController.sourceView = view.object
|
||||||
|
case .barButtonItem(let item):
|
||||||
|
popoverPresentationController.barButtonItem = item.object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func view(_ view: UIView?) -> Self {
|
||||||
|
.view(WeakHolder(view))
|
||||||
|
}
|
||||||
|
|
||||||
|
static func barButtonItem(_ item: UIBarButtonItem?) -> Self {
|
||||||
|
.barButtonItem(WeakHolder(item))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ extension AccountTableViewCell: MenuPreviewProvider {
|
||||||
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.delegate?.actionsForProfile(accountID: self.accountID, sourceView: self.avatarImageView) ?? [] }
|
actions: { self.delegate?.actionsForProfile(accountID: self.accountID, source: .view(self.avatarImageView)) ?? [] }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,11 +321,11 @@ extension ContentTextView: UIContextMenuInteractionDelegate {
|
||||||
let text = (self.text as NSString).substring(with: range)
|
let text = (self.text as NSString).substring(with: range)
|
||||||
let actions: [UIMenuElement]
|
let actions: [UIMenuElement]
|
||||||
if let mention = self.getMention(for: link, text: text) {
|
if let mention = self.getMention(for: link, text: text) {
|
||||||
actions = self.actionsForProfile(accountID: mention.id, sourceView: self)
|
actions = self.actionsForProfile(accountID: mention.id, source: .view(self))
|
||||||
} else if let tag = self.getHashtag(for: link, text: text) {
|
} else if let tag = self.getHashtag(for: link, text: text) {
|
||||||
actions = self.actionsForHashtag(tag, sourceView: self)
|
actions = self.actionsForHashtag(tag, source: .view(self))
|
||||||
} else {
|
} else {
|
||||||
actions = self.actionsForURL(link, sourceView: self)
|
actions = self.actionsForURL(link, source: .view(self))
|
||||||
}
|
}
|
||||||
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: actions)
|
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: actions)
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ extension FollowNotificationGroupTableViewCell: MenuPreviewProvider {
|
||||||
}
|
}
|
||||||
}, actions: {
|
}, actions: {
|
||||||
if accountIDs.count == 1 {
|
if accountIDs.count == 1 {
|
||||||
return self.delegate?.actionsForProfile(accountID: accountIDs.first!, sourceView: self) ?? []
|
return self.delegate?.actionsForProfile(accountID: accountIDs.first!, source: .view(self)) ?? []
|
||||||
} else {
|
} else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ extension PollFinishedTableViewCell: MenuPreviewProvider {
|
||||||
return (content: {
|
return (content: {
|
||||||
delegate.conversation(mainStatusID: statusID, state: .unknown)
|
delegate.conversation(mainStatusID: statusID, state: .unknown)
|
||||||
}, actions: {
|
}, actions: {
|
||||||
delegate.actionsForStatus(status, sourceView: self)
|
delegate.actionsForStatus(status, source: .view(self))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ extension StatusUpdatedNotificationTableViewCell: MenuPreviewProvider {
|
||||||
return (content: {
|
return (content: {
|
||||||
delegate.conversation(mainStatusID: statusID, state: .unknown)
|
delegate.conversation(mainStatusID: statusID, state: .unknown)
|
||||||
}, actions: {
|
}, actions: {
|
||||||
delegate.actionsForStatus(status, sourceView: self)
|
delegate.actionsForStatus(status, source: .view(self))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ class ProfileHeaderView: UIView {
|
||||||
|
|
||||||
updateImages(account: account)
|
updateImages(account: account)
|
||||||
|
|
||||||
moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: delegate?.actionsForProfile(accountID: accountID, sourceView: moreButton) ?? [])
|
moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: delegate?.actionsForProfile(accountID: accountID, source: .view(moreButton)) ?? [])
|
||||||
|
|
||||||
noteTextView.navigationDelegate = delegate
|
noteTextView.navigationDelegate = delegate
|
||||||
noteTextView.setTextFromHtml(account.note)
|
noteTextView.setTextFromHtml(account.note)
|
||||||
|
|
|
@ -209,7 +209,7 @@ class BaseStatusTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
// 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: delegate?.actionsForStatus(status, sourceView: moreButton, includeStatusButtonActions: false) ?? [])
|
moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: delegate?.actionsForStatus(status, source: .view(moreButton), includeStatusButtonActions: false) ?? [])
|
||||||
|
|
||||||
pollView.isHidden = status.poll == nil
|
pollView.isHidden = status.poll == nil
|
||||||
pollView.mastodonController = mastodonController
|
pollView.mastodonController = mastodonController
|
||||||
|
@ -408,7 +408,7 @@ class BaseStatusTableViewCell: UITableViewCell {
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func morePressed() {
|
@IBAction func morePressed() {
|
||||||
delegate?.showMoreOptions(forStatus: statusID, sourceView: moreButton)
|
delegate?.showMoreOptions(forStatus: statusID, source: .view(moreButton))
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func accountPressed() {
|
@objc func accountPressed() {
|
||||||
|
|
|
@ -135,7 +135,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.delegate?.actionsForProfile(accountID: self.accountID, sourceView: self.avatarImageView) ?? [])
|
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: self.delegate?.actionsForProfile(accountID: self.accountID, source: .view(self.avatarImageView)) ?? [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,7 +230,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.actionProvider?.actionsForURL(URL(card.url)!, sourceView: self) ?? []
|
let actions = self.actionProvider?.actionsForURL(URL(card.url)!, source: .view(self)) ?? []
|
||||||
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: actions)
|
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: actions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,7 @@ extension StatusCollectionViewCell {
|
||||||
|
|
||||||
// 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: delegate?.actionsForStatus(status, sourceView: moreButton, includeStatusButtonActions: false) ?? [])
|
moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: delegate?.actionsForStatus(status, source: .view(moreButton), includeStatusButtonActions: false) ?? [])
|
||||||
|
|
||||||
contentContainer.pollView.isHidden = status.poll == nil
|
contentContainer.pollView.isHidden = status.poll == nil
|
||||||
contentContainer.pollView.mastodonController = mastodonController
|
contentContainer.pollView.mastodonController = mastodonController
|
||||||
|
@ -257,7 +257,7 @@ extension StatusCollectionViewCell {
|
||||||
return UIContextMenuConfiguration() {
|
return UIContextMenuConfiguration() {
|
||||||
ProfileViewController(accountID: self.accountID, mastodonController: self.mastodonController)
|
ProfileViewController(accountID: self.accountID, mastodonController: self.mastodonController)
|
||||||
} actionProvider: { _ in
|
} actionProvider: { _ in
|
||||||
return UIMenu(children: self.delegate?.actionsForProfile(accountID: self.accountID, sourceView: sourceView) ?? [])
|
return UIMenu(children: self.delegate?.actionsForProfile(accountID: self.accountID, source: .view(sourceView)) ?? [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -653,7 +653,7 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
|
||||||
return UIContextMenuConfiguration {
|
return UIContextMenuConfiguration {
|
||||||
ConversationTableViewController(for: self.statusID, state: self.statusState.copy(), mastodonController: self.mastodonController)
|
ConversationTableViewController(for: self.statusID, state: self.statusState.copy(), mastodonController: self.mastodonController)
|
||||||
} actionProvider: { _ in
|
} actionProvider: { _ in
|
||||||
UIMenu(children: self.delegate!.actionsForStatus(status, sourceView: self))
|
UIMenu(children: self.delegate!.actionsForStatus(status, source: .view(self)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -377,7 +377,7 @@ 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.delegate?.actionsForProfile(accountID: self.accountID, sourceView: self.avatarImageView) ?? [])
|
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: self.delegate?.actionsForProfile(accountID: self.accountID, source: .view(self.avatarImageView)) ?? [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +405,7 @@ extension TimelineStatusTableViewCell: MenuPreviewProvider {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
content: { ConversationTableViewController(for: self.statusID, state: self.statusState.copy(), mastodonController: mastodonController) },
|
content: { ConversationTableViewController(for: self.statusID, state: self.statusState.copy(), mastodonController: mastodonController) },
|
||||||
actions: { self.delegate?.actionsForStatus(status, sourceView: self) ?? [] }
|
actions: { self.delegate?.actionsForStatus(status, source: .view(self)) ?? [] }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ extension ToastableViewController {
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if let newValue = newValue {
|
if let newValue = newValue {
|
||||||
objc_setAssociatedObject(self, currentToastKey, WeakHolder(object: newValue), .OBJC_ASSOCIATION_RETAIN)
|
objc_setAssociatedObject(self, currentToastKey, WeakHolder(newValue), .OBJC_ASSOCIATION_RETAIN)
|
||||||
} else {
|
} else {
|
||||||
objc_setAssociatedObject(self, currentToastKey, nil, .OBJC_ASSOCIATION_RETAIN)
|
objc_setAssociatedObject(self, currentToastKey, nil, .OBJC_ASSOCIATION_RETAIN)
|
||||||
}
|
}
|
||||||
|
@ -96,11 +96,3 @@ extension ToastableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate class WeakHolder<T: AnyObject> {
|
|
||||||
weak var object: T?
|
|
||||||
|
|
||||||
init(object: T) {
|
|
||||||
self.object = object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// WeakArray.swift
|
// Weak.swift
|
||||||
// Tusker
|
// Tusker
|
||||||
//
|
//
|
||||||
// Created by Shadowfacts on 3/25/20.
|
// Created by Shadowfacts on 3/25/20.
|
||||||
|
@ -8,16 +8,16 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
fileprivate class WeakWrapper<T: AnyObject> {
|
class WeakHolder<T: AnyObject> {
|
||||||
weak var value: T?
|
weak var object: T?
|
||||||
|
|
||||||
init(_ value: T?) {
|
init(_ object: T?) {
|
||||||
self.value = value
|
self.object = object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WeakArray<Element: AnyObject>: MutableCollection, RangeReplaceableCollection {
|
struct WeakArray<Element: AnyObject>: MutableCollection, RangeReplaceableCollection {
|
||||||
private var array: [WeakWrapper<Element>]
|
private var array: [WeakHolder<Element>]
|
||||||
|
|
||||||
var startIndex: Int { array.startIndex }
|
var startIndex: Int { array.startIndex }
|
||||||
var endIndex: Int { array.endIndex }
|
var endIndex: Int { array.endIndex }
|
||||||
|
@ -27,19 +27,19 @@ struct WeakArray<Element: AnyObject>: MutableCollection, RangeReplaceableCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ elements: [Element]) {
|
init(_ elements: [Element]) {
|
||||||
array = elements.map { WeakWrapper($0) }
|
array = elements.map { WeakHolder($0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ elements: [Element?]) {
|
init(_ elements: [Element?]) {
|
||||||
array = elements.map { WeakWrapper($0) }
|
array = elements.map { WeakHolder($0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
subscript(position: Int) -> Element? {
|
subscript(position: Int) -> Element? {
|
||||||
get {
|
get {
|
||||||
array[position].value
|
array[position].object
|
||||||
}
|
}
|
||||||
set(newValue) {
|
set(newValue) {
|
||||||
array[position] = WeakWrapper(newValue)
|
array[position] = WeakHolder(newValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,6 @@ struct WeakArray<Element: AnyObject>: MutableCollection, RangeReplaceableCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func replaceSubrange<C>(_ subrange: Range<Int>, with newElements: C) where C : Collection, Self.Element == C.Element {
|
mutating func replaceSubrange<C>(_ subrange: Range<Int>, with newElements: C) where C : Collection, Self.Element == C.Element {
|
||||||
array.replaceSubrange(subrange, with: newElements.map { WeakWrapper($0) })
|
array.replaceSubrange(subrange, with: newElements.map { WeakHolder($0) })
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue