Add favorite/reblog menu actions on iOS 16
This commit is contained in:
parent
f106cc78bb
commit
4991da1622
|
@ -137,10 +137,9 @@ extension MenuActionProvider {
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
let bookmarked = status.bookmarked ?? false
|
let bookmarked = status.bookmarked ?? false
|
||||||
|
|
||||||
var actionsSection = [
|
var toggleableSection = [
|
||||||
createAction(identifier: "bookmark", title: bookmarked ? "Unbookmark" : "Bookmark", systemImageName: bookmarked ? "bookmark.fill" : "bookmark", handler: { [weak self] (_) in
|
createAction(identifier: "bookmark", title: bookmarked ? "Unbookmark" : "Bookmark", systemImageName: bookmarked ? "bookmark.fill" : "bookmark", handler: { [weak self] (_) in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
let request = (bookmarked ? Status.unbookmark : Status.bookmark)(status.id)
|
let request = (bookmarked ? Status.unbookmark : Status.bookmark)(status.id)
|
||||||
|
@ -161,6 +160,57 @@ extension MenuActionProvider {
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
let favorited = status.favourited
|
||||||
|
// TODO: move this color into an asset catalog or something
|
||||||
|
var favImage = UIImage(systemName: favorited ? "star.fill" : "star")!
|
||||||
|
if favorited {
|
||||||
|
favImage = favImage.withTintColor(UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1), renderingMode: .alwaysOriginal)
|
||||||
|
}
|
||||||
|
toggleableSection.insert(createAction(identifier: "favorite", title: favorited ? "Unfavorite" : "Favorite", image: favImage, handler: { [weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
let request = (favorited ? Status.favourite : Status.unfavourite)(status.id)
|
||||||
|
self.mastodonController?.run(request, completion: { response in
|
||||||
|
switch response {
|
||||||
|
case .success(let status, _):
|
||||||
|
self.mastodonController?.persistentContainer.addOrUpdate(status: status)
|
||||||
|
case .failure(let error):
|
||||||
|
if let toastable = self.toastableViewController {
|
||||||
|
let config = ToastConfiguration(from: error, with: "Error \(favorited ? "Unf" : "F")avoriting", in: toastable, retryAction: nil)
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
toastable.showToast(configuration: config, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}), at: 0)
|
||||||
|
|
||||||
|
let reblogged = status.reblogged
|
||||||
|
var reblogImage = UIImage(systemName: "repeat")!
|
||||||
|
if reblogged {
|
||||||
|
reblogImage = reblogImage.withTintColor(UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1), renderingMode: .alwaysOriginal)
|
||||||
|
}
|
||||||
|
toggleableSection.insert(createAction(identifier: "reblog", title: reblogged ? "Unreblog" : "Reblog", image: reblogImage, handler: { [weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
let request = (reblogged ? Status.reblog : Status.unreblog)(status.id)
|
||||||
|
self.mastodonController?.run(request, completion: { response in
|
||||||
|
switch response {
|
||||||
|
case .success(let status, _):
|
||||||
|
self.mastodonController?.persistentContainer.addOrUpdate(status: status)
|
||||||
|
case .failure(let error):
|
||||||
|
if let toastable = self.toastableViewController {
|
||||||
|
let config = ToastConfiguration(from: error, with: "Error \(reblogged ? "Unr" : "R")eblogging", in: toastable, retryAction: nil)
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
toastable.showToast(configuration: config, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}), at: 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var actionsSection: [UIAction] = []
|
||||||
|
|
||||||
if includeReply {
|
if includeReply {
|
||||||
actionsSection.insert(createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { [weak self] (_) in
|
actionsSection.insert(createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { [weak self] (_) in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
@ -172,7 +222,7 @@ extension MenuActionProvider {
|
||||||
// only allow muting conversations that either current user posted or is participating in (technically, is mentioned, since that's the best we can do)
|
// only allow muting conversations that either current user posted or is participating in (technically, is mentioned, since that's the best we can do)
|
||||||
if status.account.id == account.id || status.mentions.contains(where: { $0.id == account.id }) {
|
if status.account.id == account.id || status.mentions.contains(where: { $0.id == account.id }) {
|
||||||
let muted = status.muted
|
let muted = status.muted
|
||||||
actionsSection.append(createAction(identifier: "mute", title: muted ? "Unmute Conversation" : "Mute Conversation", systemImageName: muted ? "speaker" : "speaker.slash", handler: { [weak self] (_) in
|
toggleableSection.append(createAction(identifier: "mute", title: muted ? "Unmute Conversation" : "Mute Conversation", systemImageName: muted ? "speaker" : "speaker.slash", handler: { [weak self] (_) in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
let request = (muted ? Status.unmuteConversation : Status.muteConversation)(status.id)
|
let request = (muted ? Status.unmuteConversation : Status.muteConversation)(status.id)
|
||||||
self.mastodonController?.run(request) { (response) in
|
self.mastodonController?.run(request) { (response) in
|
||||||
|
@ -195,7 +245,7 @@ extension MenuActionProvider {
|
||||||
if account.id == status.account.id,
|
if account.id == status.account.id,
|
||||||
mastodonController.instanceFeatures.profilePinnedStatuses {
|
mastodonController.instanceFeatures.profilePinnedStatuses {
|
||||||
let pinned = status.pinned ?? false
|
let pinned = status.pinned ?? false
|
||||||
actionsSection.append(createAction(identifier: "pin", title: pinned ? "Unpin from Profile" : "Pin to Profile", systemImageName: pinned ? "pin.slash" : "pin", handler: { [weak self] (_) in
|
toggleableSection.append(createAction(identifier: "pin", title: pinned ? "Unpin from Profile" : "Pin to Profile", systemImageName: pinned ? "pin.slash" : "pin", handler: { [weak self] (_) in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
let request = (pinned ? Status.unpin : Status.pin)(status.id)
|
let request = (pinned ? Status.unpin : Status.pin)(status.id)
|
||||||
self.mastodonController?.run(request, completion: { [weak self] (response) in
|
self.mastodonController?.run(request, completion: { [weak self] (response) in
|
||||||
|
@ -250,10 +300,18 @@ extension MenuActionProvider {
|
||||||
|
|
||||||
addOpenInNewWindow(actions: &shareSection, activity: UserActivityManager.showConversationActivity(mainStatusID: status.id, accountID: accountID))
|
addOpenInNewWindow(actions: &shareSection, activity: UserActivityManager.showConversationActivity(mainStatusID: status.id, accountID: accountID))
|
||||||
|
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
return [
|
return [
|
||||||
UIMenu(title: "", image: nil, identifier: nil, options: [.displayInline], children: shareSection),
|
UIMenu(options: .displayInline, preferredElementSize: .medium, children: toggleableSection + actionsSection),
|
||||||
UIMenu(title: "", image: nil, identifier: nil, options: [.displayInline], children: actionsSection),
|
UIMenu(options: .displayInline, children: shareSection),
|
||||||
]
|
]
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
UIMenu(options: .displayInline, children: shareSection),
|
||||||
|
UIMenu(options: .displayInline, children: toggleableSection),
|
||||||
|
UIMenu(options: .displayInline, children: actionsSection),
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func actionsForTrendingLink(card: Card) -> [UIMenuElement] {
|
func actionsForTrendingLink(card: Card) -> [UIMenuElement] {
|
||||||
|
@ -286,6 +344,10 @@ extension MenuActionProvider {
|
||||||
} else {
|
} else {
|
||||||
image = nil
|
image = nil
|
||||||
}
|
}
|
||||||
|
return createAction(identifier: identifier, title: title, image: image, handler: handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func createAction(identifier: String, title: String, image: UIImage?, handler: @escaping UIActionHandler) -> UIAction {
|
||||||
return UIAction(title: title, image: image, identifier: UIAction.Identifier(identifier), discoverabilityTitle: nil, attributes: [], state: .off, handler: handler)
|
return UIAction(title: title, image: image, identifier: UIAction.Identifier(identifier), discoverabilityTitle: nil, attributes: [], state: .off, handler: handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue