From a7f792c3016a61f300f9cc19ecf1e9043d714994 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Mon, 20 May 2024 11:30:27 +0200 Subject: [PATCH 1/2] Update menu for profiles (IOS-231) --- .../Provider/DataSourceFacade+Status.swift | 10 ++- ...er+NotificationTableViewCellDelegate.swift | 4 +- .../Scene/Profile/ProfileViewController.swift | 62 ++++++++-------- .../View/Content/StatusAuthorView.swift | 2 +- .../MastodonUI/View/Menu/MastodonMenu.swift | 73 ++++++++----------- 5 files changed, 69 insertions(+), 82 deletions(-) diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift index 7fe8fe639..91ea06633 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift @@ -398,14 +398,14 @@ extension DataSourceFacade { } try await responseToStatusFavoriteAction(provider: dependency, status: status) - case .copyLink: + case .copyStatusLink: guard let status: MastodonStatus = menuContext.statusViewModel?.originalStatus?.reblog ?? menuContext.statusViewModel?.originalStatus else { assertionFailure() return } UIPasteboard.general.string = status.entity.url - case .openInBrowser: + case .openStatusInBrowser: guard let status: MastodonStatus = menuContext.statusViewModel?.originalStatus?.reblog ?? menuContext.statusViewModel?.originalStatus, let urlString = status.entity.url, @@ -415,6 +415,12 @@ extension DataSourceFacade { return } + dependency.coordinator.present(scene: .safari(url: url), transition: .safariPresent(animated: true)) + case .copyProfileLink(let url): + UIPasteboard.general.string = url?.absoluteString + case .openUserInBrowser(let url): + guard let url else { return } + dependency.coordinator.present(scene: .safari(url: url), transition: .safariPresent(animated: true)) } } diff --git a/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift b/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift index 9e7f6e047..aa71991d3 100644 --- a/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift +++ b/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift @@ -61,10 +61,8 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider & Aut barButtonItem: nil ) ) - case .translateStatus(_), .showOriginal, .shareUser(_), .blockDomain(_), .bookmarkStatus(_), .hideReblogs(_), .shareStatus, .deleteStatus, .editStatus, .followUser(_), .boostStatus(_), .favoriteStatus(_), .copyLink, .openInBrowser: - // Do Nothing + case .translateStatus(_), .showOriginal, .shareUser(_), .blockDomain(_), .bookmarkStatus(_), .hideReblogs(_), .shareStatus, .deleteStatus, .editStatus, .followUser(_), .boostStatus(_), .favoriteStatus(_), .copyStatusLink, .openStatusInBrowser, .openUserInBrowser(_), .copyProfileLink(_): break - } } } diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index 4d35a361c..8820e8c05 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -417,6 +417,7 @@ extension ProfileViewController { .store(in: &disposeBag) } + // This More-button is only visible for other users, but not myself private func bindMoreBarButtonItem() { Publishers.CombineLatest3( viewModel.$account, @@ -428,30 +429,41 @@ extension ProfileViewController { let name = user.displayNameWithFallback - var menuActions: [MastodonMenu.Action] = [ - .muteUser(.init(name: name, isMuting: relationship.muting)), - .blockUser(.init(name: name, isBlocking: relationship.blocking)) + var items: [MastodonMenu.Submenu] = [] + + items.append(MastodonMenu.Submenu(actions: [ + .shareUser(.init(name: name)), + .openUserInBrowser(URL(string: user.url)), + .copyProfileLink(URL(string: user.url)) + ])) + + + var relationshipActions: [MastodonMenu.Action] = [ + .followUser(.init(name: name, isFollowing: relationship.following)), + .muteUser(.init(name: name, isMuting: relationship.muting)) + ] + + if relationship.following { + relationshipActions.append(.hideReblogs(.init(showReblogs: relationship.showingReblogs))) + } + + items.append(MastodonMenu.Submenu(actions: relationshipActions)) + + var destructiveActions: [MastodonMenu.Action] = [ + .blockUser(.init(name: name, isBlocking: relationship.blocking)), + .reportUser(.init(name: name)), ] if myDomain != domain { - menuActions.append( + destructiveActions.append( .blockDomain(.init(domain: domain, isBlocking: relationship.domainBlocking)) ) } - menuActions.append(contentsOf: [ - .reportUser(.init(name: name)), - .shareUser(.init(name: name)), - ]) - - if relationship.following { - let showReblogs = relationship.showingReblogs// me.showingReblogsBy.contains(user) - let context = MastodonMenu.HideReblogsActionContext(showReblogs: showReblogs) - menuActions.insert(.hideReblogs(context), at: 1) - } + items.append(MastodonMenu.Submenu(actions: destructiveActions)) let menu = MastodonMenu.setupMenu( - submenus: [MastodonMenu.Submenu(actions: menuActions)], + submenus: items, delegate: self ) return menu @@ -929,10 +941,7 @@ extension ProfileViewController: ProfileAboutViewControllerDelegate { extension ProfileViewController: MastodonMenuDelegate { func menuAction(_ action: MastodonMenu.Action) { switch action { - case .muteUser(_), - .blockUser(_), - .blockDomain(_), - .hideReblogs(_): + case .muteUser(_), .blockUser(_), .blockDomain(_), .hideReblogs(_), .reportUser(_), .shareUser(_), .openUserInBrowser(_), .copyProfileLink(_), .followUser(_): Task { try await DataSourceFacade.responseToMenuAction( dependency: self, @@ -944,20 +953,7 @@ extension ProfileViewController: MastodonMenuDelegate { 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(_), .boostStatus(_), .favoriteStatus(_), .copyLink, .openInBrowser: + case .translateStatus(_), .showOriginal, .bookmarkStatus(_), .shareStatus, .deleteStatus, .editStatus, .boostStatus(_), .favoriteStatus(_), .copyStatusLink, .openStatusInBrowser: break } } diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/StatusAuthorView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/StatusAuthorView.swift index ee85e3fa9..9f6fe6ad9 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/StatusAuthorView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/StatusAuthorView.swift @@ -186,7 +186,7 @@ extension StatusAuthorView { items.append(MastodonMenu.Submenu(actions: [action])) } - items.append(MastodonMenu.Submenu(actions: [.shareStatus, .openInBrowser, .copyLink])) + items.append(MastodonMenu.Submenu(actions: [.shareStatus, .openStatusInBrowser, .copyStatusLink])) if menuContext.isMyself { items.append(MastodonMenu.Submenu(actions: [.deleteStatus])) diff --git a/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift b/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift index 40d13c787..4c023c30e 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift @@ -76,16 +76,17 @@ extension MastodonMenu { case blockDomain(BlockDomainActionContext) case boostStatus(BoostStatusActionContext) case favoriteStatus(FavoriteStatusActionContext) - case copyLink - case openInBrowser + case copyStatusLink + case openStatusInBrowser + case openUserInBrowser(URL?) + case copyProfileLink(URL?) func build(delegate: MastodonMenuDelegate) -> LabeledAction { switch self { case .hideReblogs(let context): let title = context.showReblogs ? L10n.Common.Controls.Friendship.hideReblogs : L10n.Common.Controls.Friendship.showReblogs let reblogAction = LabeledAction(title: title, image: UIImage(systemName: "arrow.2.squarepath")) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return reblogAction @@ -100,8 +101,7 @@ extension MastodonMenu { image = UIImage(systemName: "speaker.slash") } let muteAction = LabeledAction(title: title, image: image) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return muteAction case .blockUser(let context): @@ -115,8 +115,7 @@ extension MastodonMenu { image = UIImage(systemName: "hand.raised") } let blockAction = LabeledAction(title: title, image: image, attributes: .destructive) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return blockAction case .reportUser(let context): @@ -125,8 +124,7 @@ extension MastodonMenu { image: UIImage(systemName: "flag"), attributes: .destructive ) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return reportAction case .shareUser(let context): @@ -134,8 +132,7 @@ extension MastodonMenu { title: L10n.Common.Controls.Actions.shareUser(context.name), image: UIImage(systemName: "square.and.arrow.up") ) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return shareAction case .bookmarkStatus(let context): @@ -149,8 +146,7 @@ extension MastodonMenu { image = UIImage(systemName: "bookmark") } let action = LabeledAction(title: title, image: image) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return action case .shareStatus: @@ -158,8 +154,7 @@ extension MastodonMenu { title: L10n.Common.Controls.Actions.sharePost, image: UIImage(systemName: "square.and.arrow.up") ) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return action case .deleteStatus: @@ -168,8 +163,7 @@ extension MastodonMenu { image: UIImage(systemName: "minus.circle"), attributes: .destructive ) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return deleteAction case let .translateStatus(context): @@ -178,8 +172,7 @@ extension MastodonMenu { title: L10n.Common.Controls.Actions.TranslatePost.title(language), image: UIImage(systemName: "character.book.closed") ) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return translateAction case .showOriginal: @@ -187,8 +180,7 @@ extension MastodonMenu { title: L10n.Common.Controls.Status.Translation.showOriginal, image: UIImage(systemName: "character.book.closed") ) { [weak delegate] in - guard let delegate = delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return action @@ -198,8 +190,7 @@ extension MastodonMenu { image: UIImage(systemName: "pencil") ) { [weak delegate] in - guard let delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return editStatusAction @@ -214,26 +205,22 @@ extension MastodonMenu { image = UIImage(systemName: "person.fill.badge.plus") } let action = LabeledAction(title: title, image: image) { [weak delegate] in - guard let delegate else { return } - delegate.menuAction(self) + delegate?.menuAction(self) } return action case .blockDomain(let context): - let title: String - let image: UIImage? - if context.isBlocking { - title = L10n.Common.Controls.Actions.unblockDomain(context.domain) - image = UIImage(systemName: "hand.raised.slash.fill") - } else { - title = L10n.Common.Controls.Actions.blockDomain(context.domain) - image = UIImage(systemName: "hand.raised.fill") - } - let action = LabeledAction(title: title, image: image) { [weak delegate] in - guard let delegate else { return } + let title: String - delegate.menuAction(self) - } - return action + if context.isBlocking { + title = L10n.Common.Controls.Actions.unblockDomain(context.domain) + } else { + title = L10n.Common.Controls.Actions.blockDomain(context.domain) + } + + let action = LabeledAction(title: title, image: UIImage(systemName: "globe"), attributes: .destructive) { [weak delegate] in + delegate?.menuAction(self) + } + return action case .boostStatus(let context): let title: String @@ -263,12 +250,12 @@ extension MastodonMenu { delegate?.menuAction(self) } - case .copyLink: + case .copyStatusLink, .copyProfileLink(_): return LabeledAction(title: L10n.Common.Controls.Status.Actions.copyLink, image: UIImage(systemName: "doc.on.doc")) { [weak delegate] in delegate?.menuAction(self) } - case .openInBrowser: + case .openStatusInBrowser, .openUserInBrowser(_): return LabeledAction(title: L10n.Common.Controls.Actions.openInBrowser, image: UIImage(systemName: "safari")) { [weak delegate] in delegate?.menuAction(self) } @@ -343,7 +330,7 @@ extension MastodonMenu { public let name: String public let isFollowing: Bool - init(name: String, isFollowing: Bool) { + public init(name: String, isFollowing: Bool) { self.name = name self.isFollowing = isFollowing } From aeb3717eb2e9ab7c15e3d4207bff616a8eca9736 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Tue, 21 May 2024 12:02:45 +0200 Subject: [PATCH 2/2] Update wording for boosts (IOS-231) --- .../StringsConvertor/input/en.lproj/app.json | 16 ++++++++-------- .../Resources/en.lproj/Localizable.strings | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Localization/StringsConvertor/input/en.lproj/app.json b/Localization/StringsConvertor/input/en.lproj/app.json index 1a6858950..3c5b31c83 100644 --- a/Localization/StringsConvertor/input/en.lproj/app.json +++ b/Localization/StringsConvertor/input/en.lproj/app.json @@ -222,7 +222,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 +251,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 +616,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", @@ -860,7 +860,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" diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings index 9c6b106d2..430b4c0d9 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings @@ -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"; @@ -134,7 +134,7 @@ Please check your internet connection."; "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"; @@ -351,12 +351,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 %@"; @@ -421,7 +421,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";