From 910e101538f7c5929f6731e9e481a7990ba680bf Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Mon, 18 Dec 2023 19:59:22 +0100 Subject: [PATCH 1/8] Add domain-block for MastodonUser (IOS-5) --- .../Provider/DataSourceFacade+Block.swift | 13 ++++++++++ .../Service/API/APIService+DomainBlock.swift | 25 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Block.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Block.swift index c8f1f9405..298330219 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Block.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Block.swift @@ -52,4 +52,17 @@ extension DataSourceFacade { ) dependency.context.authenticationService.fetchFollowingAndBlockedAsync() } + + static func responseToDomainBlockAction( + dependency: NeedsDependency & AuthContextProvider, + user: ManagedObjectRecord + ) async throws { + let selectionFeedbackGenerator = await UISelectionFeedbackGenerator() + await selectionFeedbackGenerator.selectionChanged() + + let apiService = dependency.context.apiService + let authBox = dependency.authContext.mastodonAuthenticationBox + + _ = try await apiService.toggleDomainBlock(user: user, authenticationBox: authBox) + } } diff --git a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift index 3bfa519c7..6d8c2a6ce 100644 --- a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift +++ b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift @@ -66,7 +66,30 @@ extension APIService { } .eraseToAnyPublisher() } - + + public func toggleDomainBlock( + user: ManagedObjectRecord, + authenticationBox: MastodonAuthenticationBox + ) async throws -> Mastodon.Response.Content { + guard let relationship = try await relationship(records: [user], authenticationBox: authenticationBox).value.first else { + throw APIError.implicit(.badRequest) + } + + let response: Mastodon.Response.Content + let domainBlocking = relationship.domainBlocking ?? false + + let managedObjectContext = backgroundManagedObjectContext + guard let user = user.object(in: managedObjectContext) else { throw APIError.implicit(.badRequest) } + + if domainBlocking { + response = try await unblockDomain(user: user, authorizationBox: authenticationBox).singleOutput() + } else { + response = try await blockDomain(user: user, authorizationBox: authenticationBox).singleOutput() + } + + return response + } + func blockDomain( user: MastodonUser, authorizationBox: MastodonAuthenticationBox From 30314cdd347a47d43b9b31a1906ecec47c35f579 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Mon, 18 Dec 2023 20:20:32 +0100 Subject: [PATCH 2/8] Update relationship (IOS-5) --- .../Service/API/APIService+DomainBlock.swift | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift index 6d8c2a6ce..d50eaa099 100644 --- a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift +++ b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift @@ -71,20 +71,43 @@ extension APIService { user: ManagedObjectRecord, authenticationBox: MastodonAuthenticationBox ) async throws -> Mastodon.Response.Content { - guard let relationship = try await relationship(records: [user], authenticationBox: authenticationBox).value.first else { + guard let originalRelationship = try await relationship(records: [user], authenticationBox: authenticationBox).value.first else { throw APIError.implicit(.badRequest) } let response: Mastodon.Response.Content - let domainBlocking = relationship.domainBlocking ?? false + let domainBlocking = originalRelationship.domainBlocking ?? false let managedObjectContext = backgroundManagedObjectContext - guard let user = user.object(in: managedObjectContext) else { throw APIError.implicit(.badRequest) } + + guard let _user = user.object(in: managedObjectContext) else { throw APIError.implicit(.badRequest) } if domainBlocking { - response = try await unblockDomain(user: user, authorizationBox: authenticationBox).singleOutput() + response = try await unblockDomain(user: _user, authorizationBox: authenticationBox).singleOutput() } else { - response = try await blockDomain(user: user, authorizationBox: authenticationBox).singleOutput() + response = try await blockDomain(user: _user, authorizationBox: authenticationBox).singleOutput() + } + + guard let relationship = try await self.relationship(records: [user], authenticationBox: authenticationBox).value.first else { + throw APIError.implicit(.badRequest) + } + + try await managedObjectContext.performChanges { + let authentication = authenticationBox.authentication + + guard + let user = user.object(in: managedObjectContext), + let me = authentication.user(in: managedObjectContext) + else { return } + + Persistence.MastodonUser.update( + mastodonUser: user, + context: Persistence.MastodonUser.RelationshipContext( + entity: relationship, + me: me, + networkDate: response.networkDate + ) + ) } return response From 7a67b595a3f2734202c59b266f1a24972fa0abb1 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Mon, 18 Dec 2023 20:26:27 +0100 Subject: [PATCH 3/8] Add block-action to profile-menu (IOS-5) --- .../Provider/DataSourceFacade+Status.swift | 42 ++++++++++++++++++- .../Scene/Profile/ProfileViewController.swift | 29 +++++++++++-- .../MastodonUI/View/Menu/MastodonMenu.swift | 37 +++++++++++++--- .../ViewModel/RelationshipViewModel.swift | 13 +++--- 4 files changed, 106 insertions(+), 15 deletions(-) diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift index d304816d0..ee55de483 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift @@ -394,8 +394,48 @@ extension DataSourceFacade { try await DataSourceFacade.responseToUserFollowAction(dependency: dependency, user: author) + case .blockDomain(let context): + let title: String + let message: String + let actionTitle: String + + #warning("Localization") + if context.isBlocking { + title = "Unblock \(context.domain)" + message = "Really unblock \(context.domain)" + actionTitle = L10n.Common.Controls.Friendship.unblockUser(context.domain) + } else { + title = "Block \(context.domain)" + message = "Really block \(context.domain)" + actionTitle = L10n.Common.Controls.Friendship.blockUser(context.domain) + } + let alertController = UIAlertController( + title: title, + message: message, + preferredStyle: .alert + ) + + let confirmAction = UIAlertAction(title: actionTitle, style: .destructive ) { [weak dependency] _ in + guard let dependency = dependency else { return } + Task { + let managedObjectContext = dependency.context.managedObjectContext + let _user: ManagedObjectRecord? = try? await managedObjectContext.perform { + guard let user = menuContext.author?.object(in: managedObjectContext) else { return nil } + return ManagedObjectRecord(objectID: user.objectID) + } + guard let user = _user else { return } + try await DataSourceFacade.responseToDomainBlockAction( + dependency: dependency, + user: user + ) + } + } + alertController.addAction(confirmAction) + let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel) + alertController.addAction(cancelAction) + dependency.present(alertController, animated: true) } - } // end func + } } extension DataSourceFacade { diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index a1c5e3925..3b7174c13 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -395,16 +395,16 @@ extension ProfileViewController { viewModel.relationshipViewModel.$optionSet ) .asyncMap { [weak self] user, relationshipSet -> UIMenu? in - guard let self = self else { return nil } - guard let user = user else { - return nil - } + guard let self, let user else { return nil } + let name = user.displayNameWithFallback + let domain = user.domainFromAcct let _ = ManagedObjectRecord(objectID: user.objectID) var menuActions: [MastodonMenu.Action] = [ .muteUser(.init(name: name, isMuting: self.viewModel.relationshipViewModel.isMuting)), .blockUser(.init(name: name, isBlocking: self.viewModel.relationshipViewModel.isBlocking)), + .blockDomain(.init(domain: domain, isBlocking: self.viewModel.relationshipViewModel.isDomainBlocking)), .reportUser(.init(name: name)), .shareUser(.init(name: name)), ] @@ -829,6 +829,27 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate { let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel, handler: nil) alertController.addAction(cancelAction) present(alertController, animated: true, completion: nil) + case .domainBlocking: + guard let user = viewModel.user else { return } + let name = user.displayNameWithFallback + + let alertController = UIAlertController( + title: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.title, + message: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.message(name), + preferredStyle: .alert + ) + let record = ManagedObjectRecord(objectID: user.objectID) + let unblockAction = UIAlertAction(title: L10n.Common.Controls.Friendship.unblock, style: .default) { [weak self] _ in + guard let self = self else { return } + Task { + try await DataSourceFacade.responseToDomainBlockAction(dependency: self, user: record) + } + } + alertController.addAction(unblockAction) + let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel, handler: nil) + alertController.addAction(cancelAction) + present(alertController, animated: true, completion: nil) + case .blocking: guard let user = viewModel.user else { return } let name = user.displayNameWithFallback diff --git a/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift b/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift index 65231c51d..08085d561 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift @@ -59,7 +59,8 @@ extension MastodonMenu { case deleteStatus case editStatus case followUser(FollowUserActionContext) - + case blockDomain(BlockDomainActionContext) + func build(delegate: MastodonMenuDelegate) -> LabeledAction { switch self { case .hideReblogs(let context): @@ -194,14 +195,30 @@ extension MastodonMenu { image = UIImage(systemName: "person.fill.badge.plus") } let action = LabeledAction(title: title, image: image) { [weak delegate] in - guard let delegate = delegate else { return } + guard let delegate else { return } delegate.menuAction(self) } return action + case .blockDomain(let context): + let title: String + let image: UIImage? + //TODO: Add localization + if context.isBlocking { + title = "Unblock \(context.domain)" + image = UIImage(systemName: "hand.raised.slash.fill") + } else { + title = "Block \(context.domain)" + image = UIImage(systemName: "hand.raised.fill") + } + let action = LabeledAction(title: title, image: image) { [weak delegate] in + guard let delegate else { return } - } // end switch - } // end func build - } // end enum Action + delegate.menuAction(self) + } + return action + } + } + } } extension MastodonMenu { @@ -275,4 +292,14 @@ extension MastodonMenu { self.isFollowing = isFollowing } } + + public struct BlockDomainActionContext { + public let domain: String + public let isBlocking: Bool + + public init(domain: String, isBlocking: Bool) { + self.domain = domain + self.isBlocking = isBlocking + } + } } diff --git a/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift b/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift index 20f720d20..4d1a7eece 100644 --- a/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift @@ -28,6 +28,7 @@ public enum RelationshipAction: Int, CaseIterable { case edit case editing case updating + case domainBlocking public var option: RelationshipActionOptionSet { return RelationshipActionOptionSet(rawValue: 1 << rawValue) @@ -60,7 +61,8 @@ public struct RelationshipActionOptionSet: OptionSet { public static let updating = RelationshipAction.updating.option public static let showReblogs = RelationshipAction.showReblogs.option public static let editOptions: RelationshipActionOptionSet = [.edit, .editing, .updating] - + public static let domainBlocking = RelationshipAction.domainBlocking.option + public func highPriorityAction(except: RelationshipActionOptionSet) -> RelationshipAction? { let set = subtracting(except) for action in RelationshipAction.allCases.reversed() where set.contains(action.option) { @@ -92,6 +94,7 @@ public struct RelationshipActionOptionSet: OptionSet { case .editing: return L10n.Common.Controls.Actions.done case .updating: return " " case .showReblogs: return " " + case .domainBlocking: return " " } } } @@ -119,7 +122,8 @@ public final class RelationshipViewModel { @Published public var isBlocking = false @Published public var isBlockingBy = false @Published public var isSuspended = false - + @Published public var isDomainBlocking = false + public init() { Publishers.CombineLatest3( $user, @@ -171,9 +175,7 @@ extension RelationshipViewModel { extension RelationshipViewModel { private func update(user: MastodonUser?, me: MastodonUser?) { - guard let user = user, - let me = me - else { + guard let user, let me else { reset() return } @@ -188,6 +190,7 @@ extension RelationshipViewModel { self.isBlocking = optionSet.contains(.blocking) self.isSuspended = optionSet.contains(.suspended) self.showReblogs = optionSet.contains(.showReblogs) + self.isDomainBlocking = optionSet.contains(.domainBlocking) self.optionSet = optionSet } From 7efe949c8efcfcff8f35b63833e69cd1231ca1b6 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Mon, 18 Dec 2023 20:38:20 +0100 Subject: [PATCH 4/8] Remove duplicate code (IOS-5) Stuff gets already updated in the other methods --- .../Service/API/APIService+DomainBlock.swift | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift index d50eaa099..5f1427ef6 100644 --- a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift +++ b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+DomainBlock.swift @@ -88,28 +88,6 @@ extension APIService { response = try await blockDomain(user: _user, authorizationBox: authenticationBox).singleOutput() } - guard let relationship = try await self.relationship(records: [user], authenticationBox: authenticationBox).value.first else { - throw APIError.implicit(.badRequest) - } - - try await managedObjectContext.performChanges { - let authentication = authenticationBox.authentication - - guard - let user = user.object(in: managedObjectContext), - let me = authentication.user(in: managedObjectContext) - else { return } - - Persistence.MastodonUser.update( - mastodonUser: user, - context: Persistence.MastodonUser.RelationshipContext( - entity: relationship, - me: me, - networkDate: response.networkDate - ) - ) - } - return response } From bc915e2ef99a7da2bf78bf3792c0ef77f636e49b Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Tue, 19 Dec 2023 11:28:12 +0100 Subject: [PATCH 5/8] Fix context for menu (IOS-5) --- .../MastodonUI/ViewModel/RelationshipViewModel.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift b/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift index 4d1a7eece..6daafc0fe 100644 --- a/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift @@ -204,6 +204,7 @@ extension RelationshipViewModel { isBlocking = false optionSet = nil showReblogs = false + isDomainBlocking = false } } @@ -223,6 +224,7 @@ extension RelationshipViewModel { let isBlockingBy = me.blockingBy.contains(user) let isBlocking = user.blockingBy.contains(me) let isShowingReblogs = me.showingReblogsBy.contains(user) + let isDomainBlocking = user.domainBlockingBy.contains(me) var optionSet: RelationshipActionOptionSet = [.follow] @@ -266,6 +268,10 @@ extension RelationshipViewModel { optionSet.insert(.showReblogs) } + if isDomainBlocking { + optionSet.insert(.domainBlocking) + } + return optionSet } } From 8b02ba29dd7e8548574ee4b3feb513f8dcf7d18c Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Tue, 19 Dec 2023 12:14:58 +0100 Subject: [PATCH 6/8] UI/UX improvements and fixes (IOS-5) - Blur images and hide bio/timeline - Show correct texts (localization is about to come) --- .../Profile/Header/View/ProfileHeaderView+ViewModel.swift | 4 ++-- Mastodon/Scene/Profile/ProfileViewController.swift | 7 ++++--- .../Profile/Timeline/UserTimelineViewModel+Diffable.swift | 7 ++++--- .../Scene/Profile/Timeline/UserTimelineViewModel.swift | 1 + .../MastodonUI/ViewModel/RelationshipViewModel.swift | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView+ViewModel.swift b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView+ViewModel.swift index be0dce929..fdfef4a2e 100644 --- a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView+ViewModel.swift +++ b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView+ViewModel.swift @@ -119,7 +119,7 @@ extension ProfileHeaderView.ViewModel { .store(in: &disposeBag) // blur for blocking & blockingBy $relationshipActionOptionSet - .map { $0.contains(.blocking) || $0.contains(.blockingBy) } + .map { $0.contains(.blocking) || $0.contains(.blockingBy) || $0.contains(.domainBlocking) } .sink { needsImageOverlayBlurred in UIView.animate(withDuration: 0.33) { let bannerEffect: UIVisualEffect? = needsImageOverlayBlurred ? ProfileHeaderView.bannerImageViewOverlayBlurEffect : nil @@ -185,7 +185,7 @@ extension ProfileHeaderView.ViewModel { $relationshipActionOptionSet .receive(on: DispatchQueue.main) .sink { optionSet in - let isBlocking = optionSet.contains(.blocking) + let isBlocking = optionSet.contains(.blocking) || optionSet.contains(.domainBlocking) let isBlockedBy = optionSet.contains(.blockingBy) let isSuspended = optionSet.contains(.suspended) let isNeedsHidden = isBlocking || isBlockedBy || isSuspended diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index 3b7174c13..9fd5e1c02 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -325,6 +325,7 @@ extension ProfileViewController { viewModel.relationshipViewModel.$isBlocking.assign(to: \.isBlocking, on: userTimelineViewModel).store(in: &disposeBag) viewModel.relationshipViewModel.$isBlockingBy.assign(to: \.isBlockedBy, on: userTimelineViewModel).store(in: &disposeBag) viewModel.relationshipViewModel.$isSuspended.assign(to: \.isSuspended, on: userTimelineViewModel).store(in: &disposeBag) + viewModel.relationshipViewModel.$isDomainBlocking.assign(to: \.isDomainBlocking, on: userTimelineViewModel).store(in: &disposeBag) } // about @@ -831,11 +832,11 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate { present(alertController, animated: true, completion: nil) case .domainBlocking: guard let user = viewModel.user else { return } - let name = user.displayNameWithFallback + let domain = user.domainFromAcct let alertController = UIAlertController( - title: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.title, - message: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.message(name), + title: "Unblock domain \(domain)", + message: "Really unblock domain \(domain)?!", preferredStyle: .alert ) let record = ManagedObjectRecord(objectID: user.objectID) diff --git a/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel+Diffable.swift b/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel+Diffable.swift index 67f2b8035..422440020 100644 --- a/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel+Diffable.swift +++ b/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel+Diffable.swift @@ -41,11 +41,12 @@ extension UserTimelineViewModel { } .store(in: &disposeBag) - let needsTimelineHidden = Publishers.CombineLatest3( + let needsTimelineHidden = Publishers.CombineLatest4( $isBlocking, $isBlockedBy, - $isSuspended - ).map { $0 || $1 || $2 } + $isSuspended, + $isDomainBlocking + ).map { $0 || $1 || $2 || $3 } Publishers.CombineLatest( statusFetchedResultsController.$records, diff --git a/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel.swift b/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel.swift index 0c8d634e5..7a4925b8d 100644 --- a/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel.swift +++ b/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel.swift @@ -27,6 +27,7 @@ final class UserTimelineViewModel { @Published var queryFilter: QueryFilter @Published var isBlocking = false + @Published var isDomainBlocking = false @Published var isBlockedBy = false @Published var isSuspended = false diff --git a/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift b/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift index 6daafc0fe..e0c7060d1 100644 --- a/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift @@ -94,7 +94,7 @@ public struct RelationshipActionOptionSet: OptionSet { case .editing: return L10n.Common.Controls.Actions.done case .updating: return " " case .showReblogs: return " " - case .domainBlocking: return " " + case .domainBlocking: return "Unblock domain" } } } From 43226075525b3ba49a7a12d5893893dc4c1f27ae Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Tue, 19 Dec 2023 13:12:32 +0100 Subject: [PATCH 7/8] Localize Domain Block (IOS-5) --- Localization/app.json | 11 ++++++++++- .../Provider/DataSourceFacade+Status.swift | 14 +++++++------- .../Generated/Strings.swift | 18 ++++++++++++++++++ .../Resources/Base.lproj/Localizable.strings | 7 ++++++- .../MastodonUI/View/Menu/MastodonMenu.swift | 5 ++--- .../ViewModel/RelationshipViewModel.swift | 2 +- 6 files changed, 44 insertions(+), 13 deletions(-) diff --git a/Localization/app.json b/Localization/app.json index 734169df0..9d8ce91b4 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -222,10 +222,11 @@ "pending": "Pending", "block": "Block", "block_user": "Block %s", - "block_domain": "Block %s", + "block_domain": "Block domain %s", "unblock": "Unblock", "unblock_user": "Unblock %s", "blocked": "Blocked", + "domain_blocked": "Domain Blocked", "mute": "Mute", "mute_user": "Mute %s", "unmute": "Unmute", @@ -603,6 +604,14 @@ "confirm_hide_reblogs": { "title": "Hide Reblogs", "message": "Confirm to hide reblogs" + }, + "confirm_block_domain": { + "title": "Block domain", + "message": "Confirm to block domain %s" + }, + "confirm_unblock_domain": { + "title": "Unblock domain", + "message": "Confirm to unblock domain %s" } }, "accessibility": { diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift index ee55de483..c324da73b 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift @@ -399,16 +399,16 @@ extension DataSourceFacade { let message: String let actionTitle: String - #warning("Localization") if context.isBlocking { - title = "Unblock \(context.domain)" - message = "Really unblock \(context.domain)" - actionTitle = L10n.Common.Controls.Friendship.unblockUser(context.domain) + title = L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.title + message = L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.message(context.domain) + actionTitle = L10n.Common.Controls.Friendship.unblockDomain(context.domain) } else { - title = "Block \(context.domain)" - message = "Really block \(context.domain)" - actionTitle = L10n.Common.Controls.Friendship.blockUser(context.domain) + title = L10n.Scene.Profile.RelationshipActionAlert.ConfirmBlockDomain.title + message = L10n.Common.Alerts.BlockDomain.title(context.domain) + actionTitle = L10n.Common.Alerts.BlockDomain.blockEntireDomain } + let alertController = UIAlertController( title: title, message: message, diff --git a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift index 99c061f91..fae0ddc50 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift +++ b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift @@ -216,6 +216,8 @@ public enum L10n { public static func blockUser(_ p1: Any) -> String { return L10n.tr("Localizable", "Common.Controls.Friendship.BlockUser", String(describing: p1), fallback: "Block %@") } + /// Domain Blocked + public static let domainBlocked = L10n.tr("Localizable", "Common.Controls.Friendship.DomainBlocked", fallback: "Domain Blocked") /// Edit Info public static let editInfo = L10n.tr("Localizable", "Common.Controls.Friendship.EditInfo", fallback: "Edit Info") /// Follow @@ -241,6 +243,10 @@ public enum L10n { /// Unblock public static let unblock = L10n.tr("Localizable", "Common.Controls.Friendship.Unblock", fallback: "Unblock") /// Unblock %@ + public static func unblockDomain(_ p1: Any) -> String { + return L10n.tr("Localizable", "Common.Controls.Friendship.UnblockDomain", String(describing: p1), fallback: "Unblock %@") + } + /// Unblock %@ public static func unblockUser(_ p1: Any) -> String { return L10n.tr("Localizable", "Common.Controls.Friendship.UnblockUser", String(describing: p1), fallback: "Unblock %@") } @@ -953,6 +959,10 @@ public enum L10n { public static let followsYou = L10n.tr("Localizable", "Scene.Profile.Header.FollowsYou", fallback: "Follows You") } public enum RelationshipActionAlert { + public enum ConfirmBlockDomain { + /// Block Domain + public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmBlockDomain.Title", fallback: "Block Domain") + } public enum ConfirmBlockUser { /// Confirm to block %@ public static func message(_ p1: Any) -> String { @@ -981,6 +991,14 @@ public enum L10n { /// Show Reblogs public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmShowReblogs.Title", fallback: "Show Reblogs") } + public enum ConfirmUnblockDomain { + /// Confirm to unblock domain %@ + public static func message(_ p1: Any) -> String { + return L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.Message", String(describing: p1), fallback: "Confirm to unblock domain %@") + } + /// Unblock Domain + public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.Title", fallback: "Unblock Domain") + } public enum ConfirmUnblockUser { /// Confirm to unblock %@ public static func message(_ p1: Any) -> String { diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/Base.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/Base.lproj/Localizable.strings index 2faf5ebb7..bd1bfc949 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/Base.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/Base.lproj/Localizable.strings @@ -73,6 +73,7 @@ Please check your internet connection."; "Common.Controls.Friendship.BlockDomain" = "Block %@"; "Common.Controls.Friendship.BlockUser" = "Block %@"; "Common.Controls.Friendship.Blocked" = "Blocked"; +"Common.Controls.Friendship.DomainBlocked" = "Domain Blocked"; "Common.Controls.Friendship.EditInfo" = "Edit Info"; "Common.Controls.Friendship.Follow" = "Follow"; "Common.Controls.Friendship.Following" = "Following"; @@ -85,6 +86,7 @@ Please check your internet connection."; "Common.Controls.Friendship.ShowReblogs" = "Show Reblogs"; "Common.Controls.Friendship.Unblock" = "Unblock"; "Common.Controls.Friendship.UnblockUser" = "Unblock %@"; +"Common.Controls.Friendship.UnblockDomain" = "Unblock %@"; "Common.Controls.Friendship.Unmute" = "Unmute"; "Common.Controls.Friendship.UnmuteUser" = "Unmute %@"; "Common.Controls.Keyboard.Common.ComposeNewPost" = "Compose New Post"; @@ -336,6 +338,9 @@ uploaded to Mastodon."; "Scene.Profile.Header.FollowsYou" = "Follows You"; "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirm to block %@"; "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Block Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockDomain.Title" = "Block Domain"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.Message" = "Confirm to unblock domain %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.Title" = "Unblock Domain"; "Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Message" = "Confirm to hide reblogs"; "Scene.Profile.RelationshipActionAlert.ConfirmHideReblogs.Title" = "Hide Reblogs"; "Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirm to mute %@"; @@ -563,4 +568,4 @@ uploaded to Mastodon."; "Widget.MultipleFollowers.ConfigurationDescription" = "Show number of followers for multiple accounts."; "Widget.MultipleFollowers.ConfigurationDisplayName" = "Multiple followers"; "Widget.MultipleFollowers.MockUser.AccountName" = "another@follower.social"; -"Widget.MultipleFollowers.MockUser.DisplayName" = "Another follower"; \ No newline at end of file +"Widget.MultipleFollowers.MockUser.DisplayName" = "Another follower"; diff --git a/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift b/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift index 08085d561..72f2877a9 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift @@ -202,12 +202,11 @@ extension MastodonMenu { case .blockDomain(let context): let title: String let image: UIImage? - //TODO: Add localization if context.isBlocking { - title = "Unblock \(context.domain)" + title = L10n.Common.Controls.Actions.unblockDomain(context.domain) image = UIImage(systemName: "hand.raised.slash.fill") } else { - title = "Block \(context.domain)" + title = L10n.Common.Controls.Actions.blockDomain(context.domain) image = UIImage(systemName: "hand.raised.fill") } let action = LabeledAction(title: title, image: image) { [weak delegate] in diff --git a/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift b/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift index e0c7060d1..b8a579199 100644 --- a/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/ViewModel/RelationshipViewModel.swift @@ -94,7 +94,7 @@ public struct RelationshipActionOptionSet: OptionSet { case .editing: return L10n.Common.Controls.Actions.done case .updating: return " " case .showReblogs: return " " - case .domainBlocking: return "Unblock domain" + case .domainBlocking: return L10n.Common.Controls.Friendship.domainBlocked } } } From 66c152754db48f80ed27a58177f869f790e4e933 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Tue, 2 Jan 2024 11:42:07 +0100 Subject: [PATCH 8/8] Add missing localization (IOS-5) --- Mastodon/Scene/Profile/ProfileViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index 9fd5e1c02..6fa6c1372 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -835,8 +835,8 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate { let domain = user.domainFromAcct let alertController = UIAlertController( - title: "Unblock domain \(domain)", - message: "Really unblock domain \(domain)?!", + title: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.title, + message: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockDomain.message(domain), preferredStyle: .alert ) let record = ManagedObjectRecord(objectID: user.objectID)