mirror of
https://github.com/mastodon/mastodon-ios
synced 2025-04-11 22:58:02 +02:00
Update Post Menu (IOS-229) (#1292)
* Add missing actions, hack way to inject options into menu (IOS-229) * Implement new menu structure (IOS-229) This doesn't work-work yet, as functionality isn't implemented yet. Also: Special options and traits. * Add preferredElementSize to submenus (IOS-229) * Copy Link (IOS-229) * Open In Browser (IOS-229) * Boost status from menu (IOS-229) * Favorite status from menu (IOS-229) * Fix following-status in menu and don't cache menu (IOS-229) * Add some destruction, add localization and use "Boost" instead of "Reblog" (IOS-229) * Use struct instead of tuple for those menu-parts (IOS-229)
This commit is contained in:
parent
14393a26df
commit
8d3cb2beb3
@ -143,9 +143,9 @@
|
||||
"next_status": "Next Post",
|
||||
"open_status": "Open Post",
|
||||
"open_author_profile": "Open Author's Profile",
|
||||
"open_reblogger_profile": "Open Reblogger's Profile",
|
||||
"open_reblogger_profile": "Open Booster's Profile",
|
||||
"reply_status": "Reply to Post",
|
||||
"toggle_reblog": "Toggle Reblog on Post",
|
||||
"toggle_reblog": "Toggle Boost on Post",
|
||||
"toggle_favorite": "Toggle Favorite on Post",
|
||||
"toggle_content_warning": "Toggle Content Warning",
|
||||
"preview_image": "Preview Image"
|
||||
@ -156,7 +156,7 @@
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"user_reblogged": "%s reblogged",
|
||||
"user_reblogged": "%s boosted",
|
||||
"user_replied_to": "Replied to %s",
|
||||
"show_post": "Show Post",
|
||||
"show_user_profile": "Show user profile",
|
||||
@ -178,8 +178,8 @@
|
||||
},
|
||||
"actions": {
|
||||
"reply": "Reply",
|
||||
"reblog": "Reblog",
|
||||
"unreblog": "Undo reblog",
|
||||
"reblog": "Boost",
|
||||
"unreblog": "Undo boost",
|
||||
"favorite": "Favorite",
|
||||
"unfavorite": "Unfavorite",
|
||||
"menu": "Menu",
|
||||
@ -190,9 +190,10 @@
|
||||
"share_link_in_post": "Share Link in Post",
|
||||
"tap_then_hold_to_show_menu": "Tap then hold to show menu",
|
||||
"a11y_labels": {
|
||||
"reblog": "Re-blog",
|
||||
"unreblog": "Undo re-blog"
|
||||
}
|
||||
"reblog": "Boost",
|
||||
"unreblog": "Undo boost"
|
||||
},
|
||||
"copy_link": "Copy Link"
|
||||
},
|
||||
"tag": {
|
||||
"url": "URL",
|
||||
@ -222,7 +223,7 @@
|
||||
},
|
||||
"posted_via_application": "%s via %s",
|
||||
"buttons": {
|
||||
"reblogs_title": "Reblogs",
|
||||
"reblogs_title": "Boosts",
|
||||
"favorites_title": "Favorites",
|
||||
"edit_history_title": "Edit History",
|
||||
"edit_history_detail": "Last edit %s"
|
||||
@ -251,8 +252,8 @@
|
||||
"unmute_user": "Unmute %s",
|
||||
"muted": "Muted",
|
||||
"edit_info": "Edit Info",
|
||||
"show_reblogs": "Show Reblogs",
|
||||
"hide_reblogs": "Hide Reblogs"
|
||||
"show_reblogs": "Show Boosts",
|
||||
"hide_reblogs": "Hide Boosts"
|
||||
},
|
||||
"timeline": {
|
||||
"filtered": "Filtered",
|
||||
@ -616,12 +617,12 @@
|
||||
"message": "Confirm to unblock %s"
|
||||
},
|
||||
"confirm_show_reblogs": {
|
||||
"title": "Show Reblogs",
|
||||
"message": "Confirm to show reblogs"
|
||||
"title": "Show Boosts",
|
||||
"message": "Confirm to show boosts"
|
||||
},
|
||||
"confirm_hide_reblogs": {
|
||||
"title": "Hide Reblogs",
|
||||
"message": "Confirm to hide reblogs"
|
||||
"title": "Hide Boosts",
|
||||
"message": "Confirm to hide boosts"
|
||||
},
|
||||
"confirm_block_domain": {
|
||||
"title": "Block domain",
|
||||
@ -655,7 +656,7 @@
|
||||
"title": "Favorited By"
|
||||
},
|
||||
"reblogged_by": {
|
||||
"title": "Reblogged By"
|
||||
"title": "Boosted By"
|
||||
},
|
||||
"search": {
|
||||
"title": "Search",
|
||||
@ -715,7 +716,7 @@
|
||||
"notification_description": {
|
||||
"followed_you": "followed you",
|
||||
"favorited_your_post": "favorited your post",
|
||||
"reblogged_your_post": "reblogged your post",
|
||||
"reblogged_your_post": "boosted your post",
|
||||
"mentioned_you": "mentioned you",
|
||||
"request_to_follow_you": "request to follow you",
|
||||
"poll_has_ended": "poll has ended"
|
||||
@ -871,7 +872,7 @@
|
||||
"unfollowed": "Unfollowed",
|
||||
"unfollow_user": "Unfollow %s",
|
||||
"mute_user": "Mute %s",
|
||||
"you_wont_see_their_posts_or_reblogs_in_your_home_feed_they_wont_know_they_ve_been_muted": "You won’t see their posts or reblogs in your home feed. They won’t know they’ve been muted.",
|
||||
"you_wont_see_their_posts_or_reblogs_in_your_home_feed_they_wont_know_they_ve_been_muted": "You won’t see their posts or boosts in your home feed. They won’t know they’ve been muted.",
|
||||
"block_user": "Block %s",
|
||||
"they_will_no_longer_be_able_to_follow_or_see_your_posts_but_they_can_see_if_theyve_been_blocked": "They will no longer be able to follow or see your posts, but they can see if they’ve been blocked.",
|
||||
"while_we_review_this_you_can_take_action_against_user": "While we review this, you can take action against %s"
|
||||
|
@ -143,9 +143,9 @@
|
||||
"next_status": "Next Post",
|
||||
"open_status": "Open Post",
|
||||
"open_author_profile": "Open Author's Profile",
|
||||
"open_reblogger_profile": "Open Reblogger's Profile",
|
||||
"open_reblogger_profile": "Open Booster's Profile",
|
||||
"reply_status": "Reply to Post",
|
||||
"toggle_reblog": "Toggle Reblog on Post",
|
||||
"toggle_reblog": "Toggle Boost on Post",
|
||||
"toggle_favorite": "Toggle Favorite on Post",
|
||||
"toggle_content_warning": "Toggle Content Warning",
|
||||
"preview_image": "Preview Image"
|
||||
@ -156,7 +156,7 @@
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"user_reblogged": "%s reblogged",
|
||||
"user_reblogged": "%s boosted",
|
||||
"user_replied_to": "Replied to %s",
|
||||
"show_post": "Show Post",
|
||||
"show_user_profile": "Show user profile",
|
||||
@ -178,8 +178,8 @@
|
||||
},
|
||||
"actions": {
|
||||
"reply": "Reply",
|
||||
"reblog": "Reblog",
|
||||
"unreblog": "Undo reblog",
|
||||
"reblog": "Boost",
|
||||
"unreblog": "Undo boost",
|
||||
"favorite": "Favorite",
|
||||
"unfavorite": "Unfavorite",
|
||||
"menu": "Menu",
|
||||
@ -190,9 +190,10 @@
|
||||
"share_link_in_post": "Share Link in Post",
|
||||
"tap_then_hold_to_show_menu": "Tap then hold to show menu",
|
||||
"a11y_labels": {
|
||||
"reblog": "Re-blog",
|
||||
"unreblog": "Undo re-blog"
|
||||
}
|
||||
"reblog": "Boost",
|
||||
"unreblog": "Undo boost"
|
||||
},
|
||||
"copy_link": "Copy Link"
|
||||
},
|
||||
"tag": {
|
||||
"url": "URL",
|
||||
@ -222,7 +223,7 @@
|
||||
},
|
||||
"posted_via_application": "%s via %s",
|
||||
"buttons": {
|
||||
"reblogs_title": "Reblogs",
|
||||
"reblogs_title": "Boosts",
|
||||
"favorites_title": "Favorites",
|
||||
"edit_history_title": "Edit History",
|
||||
"edit_history_detail": "Last edit %s"
|
||||
@ -251,8 +252,8 @@
|
||||
"unmute_user": "Unmute %s",
|
||||
"muted": "Muted",
|
||||
"edit_info": "Edit Info",
|
||||
"show_reblogs": "Show Reblogs",
|
||||
"hide_reblogs": "Hide Reblogs"
|
||||
"show_reblogs": "Show Boosts",
|
||||
"hide_reblogs": "Hide Boosts"
|
||||
},
|
||||
"timeline": {
|
||||
"filtered": "Filtered",
|
||||
@ -616,12 +617,12 @@
|
||||
"message": "Confirm to unblock %s"
|
||||
},
|
||||
"confirm_show_reblogs": {
|
||||
"title": "Show Reblogs",
|
||||
"message": "Confirm to show reblogs"
|
||||
"title": "Show Boosts",
|
||||
"message": "Confirm to show boosts"
|
||||
},
|
||||
"confirm_hide_reblogs": {
|
||||
"title": "Hide Reblogs",
|
||||
"message": "Confirm to hide reblogs"
|
||||
"title": "Hide Boosts",
|
||||
"message": "Confirm to hide boosts"
|
||||
},
|
||||
"confirm_block_domain": {
|
||||
"title": "Block domain",
|
||||
@ -655,7 +656,7 @@
|
||||
"title": "Favorited By"
|
||||
},
|
||||
"reblogged_by": {
|
||||
"title": "Reblogged By"
|
||||
"title": "Boosted By"
|
||||
},
|
||||
"search": {
|
||||
"title": "Search",
|
||||
@ -715,7 +716,7 @@
|
||||
"notification_description": {
|
||||
"followed_you": "followed you",
|
||||
"favorited_your_post": "favorited your post",
|
||||
"reblogged_your_post": "reblogged your post",
|
||||
"reblogged_your_post": "boosted your post",
|
||||
"mentioned_you": "mentioned you",
|
||||
"request_to_follow_you": "request to follow you",
|
||||
"poll_has_ended": "poll has ended"
|
||||
@ -871,7 +872,7 @@
|
||||
"unfollowed": "Unfollowed",
|
||||
"unfollow_user": "Unfollow %s",
|
||||
"mute_user": "Mute %s",
|
||||
"you_wont_see_their_posts_or_reblogs_in_your_home_feed_they_wont_know_they_ve_been_muted": "You won’t see their posts or reblogs in your home feed. They won’t know they’ve been muted.",
|
||||
"you_wont_see_their_posts_or_reblogs_in_your_home_feed_they_wont_know_they_ve_been_muted": "You won’t see their posts or boosts in your home feed. They won’t know they’ve been muted.",
|
||||
"block_user": "Block %s",
|
||||
"they_will_no_longer_be_able_to_follow_or_see_your_posts_but_they_can_see_if_theyve_been_blocked": "They will no longer be able to follow or see your posts, but they can see if they’ve been blocked.",
|
||||
"while_we_review_this_you_can_take_action_against_user": "While we review this, you can take action against %s"
|
||||
|
@ -384,6 +384,38 @@ extension DataSourceFacade {
|
||||
let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel)
|
||||
alertController.addAction(cancelAction)
|
||||
dependency.present(alertController, animated: true)
|
||||
case .boostStatus(_):
|
||||
guard let status: MastodonStatus = menuContext.statusViewModel?.originalStatus?.reblog ?? menuContext.statusViewModel?.originalStatus else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
try await responseToStatusReblogAction(provider: dependency, status: status)
|
||||
case .favoriteStatus(_):
|
||||
guard let status: MastodonStatus = menuContext.statusViewModel?.originalStatus?.reblog ?? menuContext.statusViewModel?.originalStatus else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
try await responseToStatusFavoriteAction(provider: dependency, status: status)
|
||||
case .copyLink:
|
||||
guard let status: MastodonStatus = menuContext.statusViewModel?.originalStatus?.reblog ?? menuContext.statusViewModel?.originalStatus else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
UIPasteboard.general.string = status.entity.url
|
||||
case .openInBrowser:
|
||||
guard
|
||||
let status: MastodonStatus = menuContext.statusViewModel?.originalStatus?.reblog ?? menuContext.statusViewModel?.originalStatus,
|
||||
let urlString = status.entity.url,
|
||||
let url = URL(string: urlString)
|
||||
else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
dependency.coordinator.present(scene: .safari(url: url), transition: .safariPresent(animated: true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,9 +61,10 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider & Aut
|
||||
barButtonItem: nil
|
||||
)
|
||||
)
|
||||
case .translateStatus(_), .showOriginal, .shareUser(_), .blockDomain(_), .bookmarkStatus(_), .hideReblogs(_), .shareStatus, .deleteStatus, .editStatus, .followUser(_):
|
||||
case .translateStatus(_), .showOriginal, .shareUser(_), .blockDomain(_), .bookmarkStatus(_), .hideReblogs(_), .shareStatus, .deleteStatus, .editStatus, .followUser(_), .boostStatus(_), .favoriteStatus(_), .copyLink, .openInBrowser:
|
||||
// Do Nothing
|
||||
break
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -461,37 +461,26 @@ extension NotificationView {
|
||||
}
|
||||
|
||||
public func setupAuthorMenu(menuContext: AuthorMenuContext) -> (UIMenu, [UIAccessibilityCustomAction]) {
|
||||
var actions: [[MastodonMenu.Action]] = []
|
||||
var upperActions: [MastodonMenu.Action] = []
|
||||
|
||||
upperActions = [
|
||||
.muteUser(.init(
|
||||
name: menuContext.name,
|
||||
isMuting: menuContext.isMuting
|
||||
)),
|
||||
.blockUser(.init(
|
||||
name: menuContext.name,
|
||||
isBlocking: menuContext.isBlocking
|
||||
)),
|
||||
.reportUser(
|
||||
.init(name: menuContext.name)
|
||||
var items = [
|
||||
MastodonMenu.Submenu(actions: [
|
||||
.muteUser(.init(name: menuContext.name,isMuting: menuContext.isMuting)),
|
||||
.blockUser(.init(name: menuContext.name,isBlocking: menuContext.isBlocking)),
|
||||
.reportUser(.init(name: menuContext.name))]
|
||||
)
|
||||
]
|
||||
|
||||
actions.append(upperActions)
|
||||
|
||||
if menuContext.isMyself {
|
||||
actions.append([.deleteStatus])
|
||||
items.append(MastodonMenu.Submenu(actions: [.deleteStatus]))
|
||||
}
|
||||
|
||||
|
||||
let menu = MastodonMenu.setupMenu(
|
||||
actions: actions,
|
||||
submenus: items,
|
||||
delegate: self
|
||||
)
|
||||
|
||||
let accessibilityActions = MastodonMenu.setupAccessibilityActions(
|
||||
actions: actions,
|
||||
actions: items.compactMap { $0.actions } ,
|
||||
delegate: self
|
||||
)
|
||||
|
||||
|
@ -451,7 +451,7 @@ extension ProfileViewController {
|
||||
}
|
||||
|
||||
let menu = MastodonMenu.setupMenu(
|
||||
actions: [menuActions],
|
||||
submenus: [MastodonMenu.Submenu(actions: menuActions)],
|
||||
delegate: self
|
||||
)
|
||||
return menu
|
||||
@ -929,42 +929,36 @@ extension ProfileViewController: ProfileAboutViewControllerDelegate {
|
||||
extension ProfileViewController: MastodonMenuDelegate {
|
||||
func menuAction(_ action: MastodonMenu.Action) {
|
||||
switch action {
|
||||
case .muteUser(_),
|
||||
.blockUser(_),
|
||||
.blockDomain(_),
|
||||
.hideReblogs(_):
|
||||
Task {
|
||||
try await DataSourceFacade.responseToMenuAction(
|
||||
dependency: self,
|
||||
action: action,
|
||||
menuContext: DataSourceFacade.MenuContext(
|
||||
author: viewModel.account,
|
||||
statusViewModel: nil,
|
||||
button: nil,
|
||||
barButtonItem: self.moreMenuBarButtonItem
|
||||
))
|
||||
}
|
||||
case .reportUser(_), .shareUser(_):
|
||||
Task {
|
||||
try await DataSourceFacade.responseToMenuAction(
|
||||
dependency: self,
|
||||
action: action,
|
||||
menuContext: DataSourceFacade.MenuContext(
|
||||
author: viewModel.account,
|
||||
statusViewModel: nil,
|
||||
button: nil,
|
||||
barButtonItem: self.moreMenuBarButtonItem
|
||||
))
|
||||
}
|
||||
case .muteUser(_),
|
||||
.blockUser(_),
|
||||
.blockDomain(_),
|
||||
.hideReblogs(_):
|
||||
Task {
|
||||
try await DataSourceFacade.responseToMenuAction(
|
||||
dependency: self,
|
||||
action: action,
|
||||
menuContext: DataSourceFacade.MenuContext(
|
||||
author: viewModel.account,
|
||||
statusViewModel: nil,
|
||||
button: nil,
|
||||
barButtonItem: self.moreMenuBarButtonItem
|
||||
))
|
||||
}
|
||||
case .reportUser(_), .shareUser(_):
|
||||
Task {
|
||||
try await DataSourceFacade.responseToMenuAction(
|
||||
dependency: self,
|
||||
action: action,
|
||||
menuContext: DataSourceFacade.MenuContext(
|
||||
author: viewModel.account,
|
||||
statusViewModel: nil,
|
||||
button: nil,
|
||||
barButtonItem: self.moreMenuBarButtonItem
|
||||
))
|
||||
}
|
||||
|
||||
case .translateStatus(_),
|
||||
.showOriginal,
|
||||
.bookmarkStatus(_),
|
||||
.shareStatus,
|
||||
.deleteStatus,
|
||||
.editStatus,
|
||||
.followUser(_):
|
||||
break
|
||||
case .translateStatus(_), .showOriginal, .bookmarkStatus(_), .shareStatus, .deleteStatus, .editStatus, .followUser(_), .boostStatus(_), .favoriteStatus(_), .copyLink, .openInBrowser:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -259,8 +259,8 @@ public enum L10n {
|
||||
public static let follow = L10n.tr("Localizable", "Common.Controls.Friendship.Follow", fallback: "Follow")
|
||||
/// Following
|
||||
public static let following = L10n.tr("Localizable", "Common.Controls.Friendship.Following", fallback: "Following")
|
||||
/// Hide Reblogs
|
||||
public static let hideReblogs = L10n.tr("Localizable", "Common.Controls.Friendship.HideReblogs", fallback: "Hide Reblogs")
|
||||
/// Hide Boosts
|
||||
public static let hideReblogs = L10n.tr("Localizable", "Common.Controls.Friendship.HideReblogs", fallback: "Hide Boosts")
|
||||
/// Mute
|
||||
public static let mute = L10n.tr("Localizable", "Common.Controls.Friendship.Mute", fallback: "Mute")
|
||||
/// Muted
|
||||
@ -273,8 +273,8 @@ public enum L10n {
|
||||
public static let pending = L10n.tr("Localizable", "Common.Controls.Friendship.Pending", fallback: "Pending")
|
||||
/// Request
|
||||
public static let request = L10n.tr("Localizable", "Common.Controls.Friendship.Request", fallback: "Request")
|
||||
/// Show Reblogs
|
||||
public static let showReblogs = L10n.tr("Localizable", "Common.Controls.Friendship.ShowReblogs", fallback: "Show Reblogs")
|
||||
/// Show Boosts
|
||||
public static let showReblogs = L10n.tr("Localizable", "Common.Controls.Friendship.ShowReblogs", fallback: "Show Boosts")
|
||||
/// Unblock
|
||||
public static let unblock = L10n.tr("Localizable", "Common.Controls.Friendship.Unblock", fallback: "Unblock")
|
||||
/// Unblock %@
|
||||
@ -312,8 +312,8 @@ public enum L10n {
|
||||
public static let nextStatus = L10n.tr("Localizable", "Common.Controls.Keyboard.Timeline.NextStatus", fallback: "Next Post")
|
||||
/// Open Author's Profile
|
||||
public static let openAuthorProfile = L10n.tr("Localizable", "Common.Controls.Keyboard.Timeline.OpenAuthorProfile", fallback: "Open Author's Profile")
|
||||
/// Open Reblogger's Profile
|
||||
public static let openRebloggerProfile = L10n.tr("Localizable", "Common.Controls.Keyboard.Timeline.OpenRebloggerProfile", fallback: "Open Reblogger's Profile")
|
||||
/// Open Booster's Profile
|
||||
public static let openRebloggerProfile = L10n.tr("Localizable", "Common.Controls.Keyboard.Timeline.OpenRebloggerProfile", fallback: "Open Booster's Profile")
|
||||
/// Open Post
|
||||
public static let openStatus = L10n.tr("Localizable", "Common.Controls.Keyboard.Timeline.OpenStatus", fallback: "Open Post")
|
||||
/// Preview Image
|
||||
@ -326,8 +326,8 @@ public enum L10n {
|
||||
public static let toggleContentWarning = L10n.tr("Localizable", "Common.Controls.Keyboard.Timeline.ToggleContentWarning", fallback: "Toggle Content Warning")
|
||||
/// Toggle Favorite on Post
|
||||
public static let toggleFavorite = L10n.tr("Localizable", "Common.Controls.Keyboard.Timeline.ToggleFavorite", fallback: "Toggle Favorite on Post")
|
||||
/// Toggle Reblog on Post
|
||||
public static let toggleReblog = L10n.tr("Localizable", "Common.Controls.Keyboard.Timeline.ToggleReblog", fallback: "Toggle Reblog on Post")
|
||||
/// Toggle Boost on Post
|
||||
public static let toggleReblog = L10n.tr("Localizable", "Common.Controls.Keyboard.Timeline.ToggleReblog", fallback: "Toggle Boost on Post")
|
||||
}
|
||||
}
|
||||
public enum Status {
|
||||
@ -357,23 +357,25 @@ public enum L10n {
|
||||
public static let showUserProfile = L10n.tr("Localizable", "Common.Controls.Status.ShowUserProfile", fallback: "Show user profile")
|
||||
/// Tap to reveal
|
||||
public static let tapToReveal = L10n.tr("Localizable", "Common.Controls.Status.TapToReveal", fallback: "Tap to reveal")
|
||||
/// %@ reblogged
|
||||
/// %@ boosted
|
||||
public static func userReblogged(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "Common.Controls.Status.UserReblogged", String(describing: p1), fallback: "%@ reblogged")
|
||||
return L10n.tr("Localizable", "Common.Controls.Status.UserReblogged", String(describing: p1), fallback: "%@ boosted")
|
||||
}
|
||||
/// Replied to %@
|
||||
public static func userRepliedTo(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "Common.Controls.Status.UserRepliedTo", String(describing: p1), fallback: "Replied to %@")
|
||||
}
|
||||
public enum Actions {
|
||||
/// Copy Link
|
||||
public static let copyLink = L10n.tr("Localizable", "Common.Controls.Status.Actions.CopyLink", fallback: "Copy Link")
|
||||
/// Favorite
|
||||
public static let favorite = L10n.tr("Localizable", "Common.Controls.Status.Actions.Favorite", fallback: "Favorite")
|
||||
/// Hide
|
||||
public static let hide = L10n.tr("Localizable", "Common.Controls.Status.Actions.Hide", fallback: "Hide")
|
||||
/// Menu
|
||||
public static let menu = L10n.tr("Localizable", "Common.Controls.Status.Actions.Menu", fallback: "Menu")
|
||||
/// Reblog
|
||||
public static let reblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.Reblog", fallback: "Reblog")
|
||||
/// Boost
|
||||
public static let reblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.Reblog", fallback: "Boost")
|
||||
/// Reply
|
||||
public static let reply = L10n.tr("Localizable", "Common.Controls.Status.Actions.Reply", fallback: "Reply")
|
||||
/// Share Link in Post
|
||||
@ -388,13 +390,13 @@ public enum L10n {
|
||||
public static let tapThenHoldToShowMenu = L10n.tr("Localizable", "Common.Controls.Status.Actions.TapThenHoldToShowMenu", fallback: "Tap then hold to show menu")
|
||||
/// Unfavorite
|
||||
public static let unfavorite = L10n.tr("Localizable", "Common.Controls.Status.Actions.Unfavorite", fallback: "Unfavorite")
|
||||
/// Undo reblog
|
||||
public static let unreblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.Unreblog", fallback: "Undo reblog")
|
||||
/// Undo boost
|
||||
public static let unreblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.Unreblog", fallback: "Undo boost")
|
||||
public enum A11YLabels {
|
||||
/// Re-blog
|
||||
public static let reblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.A11YLabels.Reblog", fallback: "Re-blog")
|
||||
/// Undo re-blog
|
||||
public static let unreblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.A11YLabels.Unreblog", fallback: "Undo re-blog")
|
||||
/// Boost
|
||||
public static let reblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.A11YLabels.Reblog", fallback: "Boost")
|
||||
/// Undo boost
|
||||
public static let unreblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.A11YLabels.Unreblog", fallback: "Undo boost")
|
||||
}
|
||||
}
|
||||
public enum Buttons {
|
||||
@ -406,8 +408,8 @@ public enum L10n {
|
||||
public static let editHistoryTitle = L10n.tr("Localizable", "Common.Controls.Status.Buttons.EditHistoryTitle", fallback: "Edit History")
|
||||
/// Favorites
|
||||
public static let favoritesTitle = L10n.tr("Localizable", "Common.Controls.Status.Buttons.FavoritesTitle", fallback: "Favorites")
|
||||
/// Reblogs
|
||||
public static let reblogsTitle = L10n.tr("Localizable", "Common.Controls.Status.Buttons.ReblogsTitle", fallback: "Reblogs")
|
||||
/// Boosts
|
||||
public static let reblogsTitle = L10n.tr("Localizable", "Common.Controls.Status.Buttons.ReblogsTitle", fallback: "Boosts")
|
||||
}
|
||||
public enum EditHistory {
|
||||
/// Original Post · %@
|
||||
@ -898,8 +900,8 @@ public enum L10n {
|
||||
public static let mentionedYou = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.MentionedYou", fallback: "mentioned you")
|
||||
/// poll has ended
|
||||
public static let pollHasEnded = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.PollHasEnded", fallback: "poll has ended")
|
||||
/// reblogged your post
|
||||
public static let rebloggedYourPost = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.RebloggedYourPost", fallback: "reblogged your post")
|
||||
/// boosted your post
|
||||
public static let rebloggedYourPost = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.RebloggedYourPost", fallback: "boosted your post")
|
||||
/// request to follow you
|
||||
public static let requestToFollowYou = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.RequestToFollowYou", fallback: "request to follow you")
|
||||
}
|
||||
@ -1027,10 +1029,10 @@ public enum L10n {
|
||||
public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title", fallback: "Block Account")
|
||||
}
|
||||
public enum ConfirmHideReblogs {
|
||||
/// Confirm to hide reblogs
|
||||
public static let message = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Message", fallback: "Confirm to hide reblogs")
|
||||
/// Hide Reblogs
|
||||
public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Title", fallback: "Hide Reblogs")
|
||||
/// Confirm to hide boosts
|
||||
public static let message = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Message", fallback: "Confirm to hide boosts")
|
||||
/// Hide Boosts
|
||||
public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Title", fallback: "Hide Boosts")
|
||||
}
|
||||
public enum ConfirmMuteUser {
|
||||
/// Confirm to mute %@
|
||||
@ -1041,10 +1043,10 @@ public enum L10n {
|
||||
public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title", fallback: "Mute Account")
|
||||
}
|
||||
public enum ConfirmShowReblogs {
|
||||
/// Confirm to show reblogs
|
||||
public static let message = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmShowReblogs.Message", fallback: "Confirm to show reblogs")
|
||||
/// Show Reblogs
|
||||
public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmShowReblogs.Title", fallback: "Show Reblogs")
|
||||
/// Confirm to show boosts
|
||||
public static let message = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmShowReblogs.Message", fallback: "Confirm to show boosts")
|
||||
/// Show Boosts
|
||||
public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmShowReblogs.Title", fallback: "Show Boosts")
|
||||
}
|
||||
public enum ConfirmUnblockDomain {
|
||||
/// Confirm to unblock domain %@
|
||||
@ -1085,8 +1087,8 @@ public enum L10n {
|
||||
}
|
||||
}
|
||||
public enum RebloggedBy {
|
||||
/// Reblogged By
|
||||
public static let title = L10n.tr("Localizable", "Scene.RebloggedBy.Title", fallback: "Reblogged By")
|
||||
/// Boosted By
|
||||
public static let title = L10n.tr("Localizable", "Scene.RebloggedBy.Title", fallback: "Boosted By")
|
||||
}
|
||||
public enum Register {
|
||||
/// Create Account
|
||||
@ -1258,8 +1260,8 @@ public enum L10n {
|
||||
public static func whileWeReviewThisYouCanTakeActionAgainstUser(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "Scene.Report.StepFinal.WhileWeReviewThisYouCanTakeActionAgainstUser", String(describing: p1), fallback: "While we review this, you can take action against %@")
|
||||
}
|
||||
/// You won’t see their posts or reblogs in your home feed. They won’t know they’ve been muted.
|
||||
public static let youWontSeeTheirPostsOrReblogsInYourHomeFeedTheyWontKnowTheyVeBeenMuted = L10n.tr("Localizable", "Scene.Report.StepFinal.YouWontSeeTheirPostsOrReblogsInYourHomeFeedTheyWontKnowTheyVeBeenMuted", fallback: "You won’t see their posts or reblogs in your home feed. They won’t know they’ve been muted.")
|
||||
/// You won’t see their posts or boosts in your home feed. They won’t know they’ve been muted.
|
||||
public static let youWontSeeTheirPostsOrReblogsInYourHomeFeedTheyWontKnowTheyVeBeenMuted = L10n.tr("Localizable", "Scene.Report.StepFinal.YouWontSeeTheirPostsOrReblogsInYourHomeFeedTheyWontKnowTheyVeBeenMuted", fallback: "You won’t see their posts or boosts in your home feed. They won’t know they’ve been muted.")
|
||||
}
|
||||
public enum StepFour {
|
||||
/// Is there anything else we should know?
|
||||
|
@ -90,13 +90,13 @@ Please check your internet connection.";
|
||||
"Common.Controls.Friendship.EditInfo" = "Edit Info";
|
||||
"Common.Controls.Friendship.Follow" = "Follow";
|
||||
"Common.Controls.Friendship.Following" = "Following";
|
||||
"Common.Controls.Friendship.HideReblogs" = "Hide Reblogs";
|
||||
"Common.Controls.Friendship.HideReblogs" = "Hide Boosts";
|
||||
"Common.Controls.Friendship.Mute" = "Mute";
|
||||
"Common.Controls.Friendship.MuteUser" = "Mute %@";
|
||||
"Common.Controls.Friendship.Muted" = "Muted";
|
||||
"Common.Controls.Friendship.Pending" = "Pending";
|
||||
"Common.Controls.Friendship.Request" = "Request";
|
||||
"Common.Controls.Friendship.ShowReblogs" = "Show Reblogs";
|
||||
"Common.Controls.Friendship.ShowReblogs" = "Show Boosts";
|
||||
"Common.Controls.Friendship.Unblock" = "Unblock";
|
||||
"Common.Controls.Friendship.UnblockUser" = "Unblock %@";
|
||||
"Common.Controls.Friendship.Unmute" = "Unmute";
|
||||
@ -109,20 +109,21 @@ Please check your internet connection.";
|
||||
"Common.Controls.Keyboard.SegmentedControl.PreviousSection" = "Previous Section";
|
||||
"Common.Controls.Keyboard.Timeline.NextStatus" = "Next Post";
|
||||
"Common.Controls.Keyboard.Timeline.OpenAuthorProfile" = "Open Author's Profile";
|
||||
"Common.Controls.Keyboard.Timeline.OpenRebloggerProfile" = "Open Reblogger's Profile";
|
||||
"Common.Controls.Keyboard.Timeline.OpenRebloggerProfile" = "Open Booster's Profile";
|
||||
"Common.Controls.Keyboard.Timeline.OpenStatus" = "Open Post";
|
||||
"Common.Controls.Keyboard.Timeline.PreviewImage" = "Preview Image";
|
||||
"Common.Controls.Keyboard.Timeline.PreviousStatus" = "Previous Post";
|
||||
"Common.Controls.Keyboard.Timeline.ReplyStatus" = "Reply to Post";
|
||||
"Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "Toggle Content Warning";
|
||||
"Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Toggle Favorite on Post";
|
||||
"Common.Controls.Keyboard.Timeline.ToggleReblog" = "Toggle Reblog on Post";
|
||||
"Common.Controls.Status.Actions.A11YLabels.Reblog" = "Re-blog";
|
||||
"Common.Controls.Status.Actions.A11YLabels.Unreblog" = "Undo re-blog";
|
||||
"Common.Controls.Keyboard.Timeline.ToggleReblog" = "Toggle Boost on Post";
|
||||
"Common.Controls.Status.Actions.A11YLabels.Reblog" = "Boost";
|
||||
"Common.Controls.Status.Actions.A11YLabels.Unreblog" = "Undo boost";
|
||||
"Common.Controls.Status.Actions.CopyLink" = "Copy Link";
|
||||
"Common.Controls.Status.Actions.Favorite" = "Favorite";
|
||||
"Common.Controls.Status.Actions.Hide" = "Hide";
|
||||
"Common.Controls.Status.Actions.Menu" = "Menu";
|
||||
"Common.Controls.Status.Actions.Reblog" = "Reblog";
|
||||
"Common.Controls.Status.Actions.Reblog" = "Boost";
|
||||
"Common.Controls.Status.Actions.Reply" = "Reply";
|
||||
"Common.Controls.Status.Actions.ShareLinkInPost" = "Share Link in Post";
|
||||
"Common.Controls.Status.Actions.ShowGif" = "Show GIF";
|
||||
@ -130,11 +131,11 @@ Please check your internet connection.";
|
||||
"Common.Controls.Status.Actions.ShowVideoPlayer" = "Show video player";
|
||||
"Common.Controls.Status.Actions.TapThenHoldToShowMenu" = "Tap then hold to show menu";
|
||||
"Common.Controls.Status.Actions.Unfavorite" = "Unfavorite";
|
||||
"Common.Controls.Status.Actions.Unreblog" = "Undo reblog";
|
||||
"Common.Controls.Status.Actions.Unreblog" = "Undo boost";
|
||||
"Common.Controls.Status.Buttons.EditHistoryDetail" = "Last edit %@";
|
||||
"Common.Controls.Status.Buttons.EditHistoryTitle" = "Edit History";
|
||||
"Common.Controls.Status.Buttons.FavoritesTitle" = "Favorites";
|
||||
"Common.Controls.Status.Buttons.ReblogsTitle" = "Reblogs";
|
||||
"Common.Controls.Status.Buttons.ReblogsTitle" = "Boosts";
|
||||
"Common.Controls.Status.ContentWarning" = "Content Warning";
|
||||
"Common.Controls.Status.EditHistory.OriginalPost" = "Original Post · %@";
|
||||
"Common.Controls.Status.EditHistory.Title" = "Edit History";
|
||||
@ -167,7 +168,7 @@ Please check your internet connection.";
|
||||
"Common.Controls.Status.Translation.TranslatedFrom" = "Translated from %@ using %@";
|
||||
"Common.Controls.Status.Translation.UnknownLanguage" = "Unknown";
|
||||
"Common.Controls.Status.Translation.UnknownProvider" = "Unknown";
|
||||
"Common.Controls.Status.UserReblogged" = "%@ reblogged";
|
||||
"Common.Controls.Status.UserReblogged" = "%@ boosted";
|
||||
"Common.Controls.Status.UserRepliedTo" = "Replied to %@";
|
||||
"Common.Controls.Status.Visibility.Direct" = "Only mentioned user can see this post.";
|
||||
"Common.Controls.Status.Visibility.Private" = "Only their followers can see this post.";
|
||||
@ -319,7 +320,7 @@ uploaded to Mastodon.";
|
||||
"Scene.Notification.NotificationDescription.FollowedYou" = "followed you";
|
||||
"Scene.Notification.NotificationDescription.MentionedYou" = "mentioned you";
|
||||
"Scene.Notification.NotificationDescription.PollHasEnded" = "poll has ended";
|
||||
"Scene.Notification.NotificationDescription.RebloggedYourPost" = "reblogged your post";
|
||||
"Scene.Notification.NotificationDescription.RebloggedYourPost" = "boosted your post";
|
||||
"Scene.Notification.NotificationDescription.RequestToFollowYou" = "request to follow you";
|
||||
"Scene.Notification.Title.Everything" = "Everything";
|
||||
"Scene.Notification.Title.Mentions" = "Mentions";
|
||||
@ -361,12 +362,12 @@ uploaded to Mastodon.";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmBlockDomain.Title" = "Block domain";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirm to block %@";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Block Account";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Message" = "Confirm to hide reblogs";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Title" = "Hide Reblogs";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Message" = "Confirm to hide boosts";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Title" = "Hide Boosts";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirm to mute %@";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Mute Account";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmShowReblogs.Message" = "Confirm to show reblogs";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmShowReblogs.Title" = "Show Reblogs";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmShowReblogs.Message" = "Confirm to show boosts";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmShowReblogs.Title" = "Show Boosts";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.Message" = "Confirm to unblock domain %@";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.Title" = "Unblock domain";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirm to unblock %@";
|
||||
@ -378,7 +379,7 @@ uploaded to Mastodon.";
|
||||
"Scene.Profile.SegmentedControl.Posts" = "Posts";
|
||||
"Scene.Profile.SegmentedControl.PostsAndReplies" = "Posts and Replies";
|
||||
"Scene.Profile.SegmentedControl.Replies" = "Replies";
|
||||
"Scene.RebloggedBy.Title" = "Reblogged By";
|
||||
"Scene.RebloggedBy.Title" = "Boosted By";
|
||||
"Scene.Register.Error.Item.Agreement" = "Agreement";
|
||||
"Scene.Register.Error.Item.Email" = "Email";
|
||||
"Scene.Register.Error.Item.Locale" = "Locale";
|
||||
@ -431,7 +432,7 @@ uploaded to Mastodon.";
|
||||
"Scene.Report.StepFinal.Unfollowed" = "Unfollowed";
|
||||
"Scene.Report.StepFinal.WhenYouSeeSomethingYouDontLikeOnMastodonYouCanRemoveThePersonFromYourExperience." = "When you see something you don’t like on Mastodon, you can remove the person from your experience.";
|
||||
"Scene.Report.StepFinal.WhileWeReviewThisYouCanTakeActionAgainstUser" = "While we review this, you can take action against %@";
|
||||
"Scene.Report.StepFinal.YouWontSeeTheirPostsOrReblogsInYourHomeFeedTheyWontKnowTheyVeBeenMuted" = "You won’t see their posts or reblogs in your home feed. They won’t know they’ve been muted.";
|
||||
"Scene.Report.StepFinal.YouWontSeeTheirPostsOrReblogsInYourHomeFeedTheyWontKnowTheyVeBeenMuted" = "You won’t see their posts or boosts in your home feed. They won’t know they’ve been muted.";
|
||||
"Scene.Report.StepFour.IsThereAnythingElseWeShouldKnow" = "Is there anything else we should know?";
|
||||
"Scene.Report.StepFour.Step4Of4" = "Step 4 of 4";
|
||||
"Scene.Report.StepOne.IDontLikeIt" = "I don’t like it";
|
||||
|
@ -147,73 +147,68 @@ extension StatusAuthorView {
|
||||
public let isMuting: Bool
|
||||
public let isBlocking: Bool
|
||||
public let isMyself: Bool
|
||||
public let isBookmarking: Bool
|
||||
public let isBookmarked: Bool
|
||||
public let isFollowed: Bool
|
||||
|
||||
public let isTranslationEnabled: Bool
|
||||
public let isTranslated: Bool
|
||||
public let statusLanguage: String?
|
||||
public let isFavorited: Bool
|
||||
public let isBoosted: Bool
|
||||
}
|
||||
|
||||
public func setupAuthorMenu(menuContext: AuthorMenuContext) -> (UIMenu, [UIAccessibilityCustomAction]) {
|
||||
var actions: [[MastodonMenu.Action]] = []
|
||||
var postActions: [MastodonMenu.Action] = []
|
||||
var userActions: [MastodonMenu.Action] = []
|
||||
var items: [MastodonMenu.Submenu] = []
|
||||
|
||||
items.append(MastodonMenu.Submenu(
|
||||
actions: [
|
||||
.boostStatus(.init(isBoosted: menuContext.isBoosted)),
|
||||
.favoriteStatus(.init(isFavorited: menuContext.isFavorited)),
|
||||
.bookmarkStatus(.init(isBookmarked: menuContext.isBookmarked)),
|
||||
],
|
||||
preferredElementSize: .medium
|
||||
))
|
||||
|
||||
if menuContext.isMyself {
|
||||
postActions.append(.editStatus)
|
||||
}
|
||||
items.append(MastodonMenu.Submenu(actions: [.editStatus]))
|
||||
} else if menuContext.isTranslationEnabled,
|
||||
let statusLanguage = menuContext.statusLanguage,
|
||||
let deviceLanguage = Bundle.main.preferredLocalizations.first,
|
||||
deviceLanguage != statusLanguage {
|
||||
let action: MastodonMenu.Action
|
||||
|
||||
if menuContext.isTranslationEnabled,
|
||||
let statusLanguage = menuContext.statusLanguage,
|
||||
let deviceLanguage = Bundle.main.preferredLocalizations.first,
|
||||
deviceLanguage != statusLanguage {
|
||||
if menuContext.isTranslated == false {
|
||||
postActions.append(.translateStatus(.init(language: statusLanguage)))
|
||||
action = .translateStatus(.init(language: statusLanguage))
|
||||
} else {
|
||||
postActions.append(.showOriginal)
|
||||
action = .showOriginal
|
||||
}
|
||||
|
||||
items.append(MastodonMenu.Submenu(actions: [action]))
|
||||
}
|
||||
|
||||
postActions.append(.bookmarkStatus(.init(isBookmarking: menuContext.isBookmarking)))
|
||||
postActions.append(.shareStatus)
|
||||
|
||||
if menuContext.isMyself == false {
|
||||
|
||||
userActions.append(.followUser(.init(
|
||||
name: menuContext.name,
|
||||
isFollowing: menuContext.isFollowed
|
||||
)))
|
||||
|
||||
userActions.append(.muteUser(.init(
|
||||
name: menuContext.name,
|
||||
isMuting: menuContext.isMuting
|
||||
)))
|
||||
|
||||
userActions.append(.blockUser(.init(
|
||||
name: menuContext.name,
|
||||
isBlocking: menuContext.isBlocking
|
||||
)))
|
||||
|
||||
userActions.append(.reportUser(
|
||||
.init(name: menuContext.name)
|
||||
))
|
||||
}
|
||||
|
||||
actions.append(postActions)
|
||||
actions.append(userActions)
|
||||
items.append(MastodonMenu.Submenu(actions: [.shareStatus, .openInBrowser, .copyLink]))
|
||||
|
||||
if menuContext.isMyself {
|
||||
actions.append([.deleteStatus])
|
||||
items.append(MastodonMenu.Submenu(actions: [.deleteStatus]))
|
||||
} else {
|
||||
items.append(MastodonMenu.Submenu(actions: [
|
||||
.followUser(.init(name: menuContext.name, isFollowing: menuContext.isFollowed)),
|
||||
.muteUser(.init( name: menuContext.name, isMuting: menuContext.isMuting))
|
||||
]))
|
||||
|
||||
items.append(MastodonMenu.Submenu(actions: [
|
||||
.blockUser(.init(name: menuContext.name, isBlocking: menuContext.isBlocking)),
|
||||
.reportUser(.init(name: menuContext.name))
|
||||
]))
|
||||
}
|
||||
|
||||
let menu = MastodonMenu.setupMenu(
|
||||
actions: actions,
|
||||
submenus: items,
|
||||
delegate: self.statusView!
|
||||
)
|
||||
|
||||
let accessibilityActions = MastodonMenu.setupAccessibilityActions(
|
||||
actions: actions,
|
||||
actions: items.compactMap { $0.actions } ,
|
||||
delegate: self.statusView!
|
||||
)
|
||||
|
||||
|
@ -686,13 +686,18 @@ extension StatusView.ViewModel {
|
||||
$language
|
||||
)
|
||||
|
||||
let publisherTwo = Publishers.CombineLatest3(
|
||||
$isBookmark, $isFavorite, $isReblog
|
||||
)
|
||||
|
||||
Publishers.CombineLatest3(
|
||||
publisherOne.eraseToAnyPublisher(),
|
||||
$isBookmark,
|
||||
publisherTwo.eraseToAnyPublisher(),
|
||||
publishersThree.eraseToAnyPublisher()
|
||||
).eraseToAnyPublisher()
|
||||
.sink { tupleOne, isBookmark, tupleThree in
|
||||
.sink { tupleOne, tupleTwo, tupleThree in
|
||||
let (authorName, authorId, isMyself) = tupleOne
|
||||
let (isBookmark, isFavorite, isBoosted) = tupleTwo
|
||||
let (translatedFromLanguage, language) = tupleThree
|
||||
|
||||
guard let name = authorName?.string, let authorId = authorId, let context = self.context, let authContext = self.authContext else {
|
||||
@ -705,8 +710,8 @@ extension StatusView.ViewModel {
|
||||
let isTranslationEnabled = instance?.isTranslationEnabled ?? false
|
||||
|
||||
authorView.menuButton.menu = UIMenu(children: [
|
||||
UIDeferredMenuElement({ menuElement in
|
||||
|
||||
UIDeferredMenuElement.uncached({ menuElement in
|
||||
|
||||
let domain = authContext.mastodonAuthenticationBox.domain
|
||||
|
||||
Task { @MainActor in
|
||||
@ -724,11 +729,13 @@ extension StatusView.ViewModel {
|
||||
isMuting: rel.muting,
|
||||
isBlocking: rel.blocking,
|
||||
isMyself: isMyself,
|
||||
isBookmarking: isBookmark,
|
||||
isFollowed: rel.followedBy,
|
||||
isBookmarked: isBookmark,
|
||||
isFollowed: rel.following,
|
||||
isTranslationEnabled: isTranslationEnabled,
|
||||
isTranslated: translatedFromLanguage != nil,
|
||||
statusLanguage: language
|
||||
statusLanguage: language,
|
||||
isFavorited: isFavorite,
|
||||
isBoosted: isBoosted
|
||||
)
|
||||
|
||||
let (menu, actions) = authorView.setupAuthorMenu(menuContext: menuContext)
|
||||
@ -737,7 +744,11 @@ extension StatusView.ViewModel {
|
||||
menuElement(menu.children)
|
||||
}
|
||||
} else {
|
||||
menuElement(MastodonMenu.setupMenu(actions: [[.shareStatus]], delegate: statusView).children)
|
||||
menuElement(
|
||||
MastodonMenu.setupMenu(
|
||||
submenus: [MastodonMenu.Submenu(actions: [.shareStatus])],
|
||||
delegate: statusView).children
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -13,19 +13,33 @@ public protocol MastodonMenuDelegate: AnyObject {
|
||||
}
|
||||
|
||||
public enum MastodonMenu {
|
||||
|
||||
public struct Submenu {
|
||||
public let actions: [Action]
|
||||
public let options: UIMenu.Options
|
||||
public let preferredElementSize: UIMenu.ElementSize
|
||||
|
||||
public init(actions: [Action], options: UIMenu.Options = .displayInline, preferredElementSize: UIMenu.ElementSize = .large) {
|
||||
self.actions = actions
|
||||
self.options = options
|
||||
self.preferredElementSize = preferredElementSize
|
||||
}
|
||||
}
|
||||
|
||||
public static func setupMenu(
|
||||
actions: [[Action]],
|
||||
submenus: [Submenu],
|
||||
delegate: MastodonMenuDelegate
|
||||
) -> UIMenu {
|
||||
var children: [UIMenuElement] = []
|
||||
|
||||
for actionGroup in actions {
|
||||
for item in submenus {
|
||||
var submenuChildren: [UIMenuElement] = []
|
||||
for action in actionGroup {
|
||||
for action in item.actions {
|
||||
let element = action.build(delegate: delegate).menuElement
|
||||
submenuChildren.append(element)
|
||||
}
|
||||
let submenu = UIMenu(options: .displayInline, children: submenuChildren)
|
||||
let submenu = UIMenu(options: item.options, children: submenuChildren)
|
||||
submenu.preferredElementSize = item.preferredElementSize
|
||||
children.append(submenu)
|
||||
}
|
||||
|
||||
@ -60,6 +74,10 @@ extension MastodonMenu {
|
||||
case editStatus
|
||||
case followUser(FollowUserActionContext)
|
||||
case blockDomain(BlockDomainActionContext)
|
||||
case boostStatus(BoostStatusActionContext)
|
||||
case favoriteStatus(FavoriteStatusActionContext)
|
||||
case copyLink
|
||||
case openInBrowser
|
||||
|
||||
func build(delegate: MastodonMenuDelegate) -> LabeledAction {
|
||||
switch self {
|
||||
@ -96,7 +114,7 @@ extension MastodonMenu {
|
||||
title = L10n.Common.Controls.Friendship.blockUser(context.name)
|
||||
image = UIImage(systemName: "hand.raised")
|
||||
}
|
||||
let blockAction = LabeledAction(title: title, image: image) { [weak delegate] in
|
||||
let blockAction = LabeledAction(title: title, image: image, attributes: .destructive) { [weak delegate] in
|
||||
guard let delegate = delegate else { return }
|
||||
delegate.menuAction(self)
|
||||
}
|
||||
@ -104,7 +122,8 @@ extension MastodonMenu {
|
||||
case .reportUser(let context):
|
||||
let reportAction = LabeledAction(
|
||||
title: L10n.Common.Controls.Actions.reportUser(context.name),
|
||||
image: UIImage(systemName: "flag")
|
||||
image: UIImage(systemName: "flag"),
|
||||
attributes: .destructive
|
||||
) { [weak delegate] in
|
||||
guard let delegate = delegate else { return }
|
||||
delegate.menuAction(self)
|
||||
@ -122,7 +141,7 @@ extension MastodonMenu {
|
||||
case .bookmarkStatus(let context):
|
||||
let title: String
|
||||
let image: UIImage?
|
||||
if context.isBookmarking {
|
||||
if context.isBookmarked {
|
||||
title = L10n.Common.Controls.Actions.removeBookmark
|
||||
image = UIImage(systemName: "bookmark.slash.fill")
|
||||
} else {
|
||||
@ -215,6 +234,44 @@ extension MastodonMenu {
|
||||
delegate.menuAction(self)
|
||||
}
|
||||
return action
|
||||
|
||||
case .boostStatus(let context):
|
||||
let title: String
|
||||
|
||||
if context.isBoosted {
|
||||
title = L10n.Common.Controls.Status.Actions.unreblog
|
||||
} else {
|
||||
title = L10n.Common.Controls.Status.Actions.reblog
|
||||
}
|
||||
|
||||
return LabeledAction(title: title, image: UIImage(systemName: "arrow.2.squarepath")) { [weak delegate] in
|
||||
delegate?.menuAction(self)
|
||||
}
|
||||
case .favoriteStatus(let context):
|
||||
let title: String
|
||||
let image: UIImage?
|
||||
|
||||
if context.isFavorited {
|
||||
title = L10n.Common.Controls.Status.Actions.unfavorite
|
||||
image = UIImage(systemName: "star.slash")
|
||||
} else {
|
||||
title = L10n.Common.Controls.Status.Actions.favorite
|
||||
image = UIImage(systemName: "star")
|
||||
}
|
||||
|
||||
return LabeledAction(title: title, image: image) { [weak delegate] in
|
||||
delegate?.menuAction(self)
|
||||
}
|
||||
|
||||
case .copyLink:
|
||||
return LabeledAction(title: L10n.Common.Controls.Status.Actions.copyLink, image: UIImage(systemName: "doc.on.doc")) { [weak delegate] in
|
||||
delegate?.menuAction(self)
|
||||
}
|
||||
|
||||
case .openInBrowser:
|
||||
return LabeledAction(title: L10n.Common.Controls.Actions.openInBrowser, image: UIImage(systemName: "safari")) { [weak delegate] in
|
||||
delegate?.menuAction(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -242,10 +299,10 @@ extension MastodonMenu {
|
||||
}
|
||||
|
||||
public struct BookmarkStatusActionContext {
|
||||
public let isBookmarking: Bool
|
||||
public let isBookmarked: Bool
|
||||
|
||||
public init(isBookmarking: Bool) {
|
||||
self.isBookmarking = isBookmarking
|
||||
public init(isBookmarked: Bool) {
|
||||
self.isBookmarked = isBookmarked
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,4 +358,21 @@ extension MastodonMenu {
|
||||
self.isBlocking = isBlocking
|
||||
}
|
||||
}
|
||||
|
||||
public struct BoostStatusActionContext {
|
||||
public let isBoosted: Bool
|
||||
|
||||
public init(isBoosted: Bool) {
|
||||
self.isBoosted = isBoosted
|
||||
}
|
||||
}
|
||||
|
||||
public struct FavoriteStatusActionContext {
|
||||
public let isFavorited: Bool
|
||||
|
||||
public init(isFavorited: Bool) {
|
||||
self.isFavorited = isFavorited
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user