Refactor Mute/Block/HideReblogs to work with relationships (IOS-192)

Also: Connect Blocking/BlockedBy
This commit is contained in:
Nathan Mattes 2023-12-25 14:38:11 +01:00
parent b7bb271b40
commit 2f0614d9c9
5 changed files with 89 additions and 33 deletions

View File

@ -35,14 +35,14 @@ extension DataSourceFacade {
static func responseToUserBlockAction(
dependency: NeedsDependency & AuthContextProvider,
user: Mastodon.Entity.Account
) async throws {
) async throws -> Mastodon.Entity.Relationship {
let selectionFeedbackGenerator = await UISelectionFeedbackGenerator()
await selectionFeedbackGenerator.selectionChanged()
let apiService = dependency.context.apiService
let authBox = dependency.authContext.mastodonAuthenticationBox
_ = try await apiService.toggleBlock(
let response = try await apiService.toggleBlock(
user: user,
authenticationBox: authBox
)
@ -50,6 +50,9 @@ extension DataSourceFacade {
try await dependency.context.apiService.getBlocked(
authenticationBox: authBox
)
dependency.context.authenticationService.fetchFollowingAndBlockedAsync()
return response.value
}
}

View File

@ -13,13 +13,15 @@ extension DataSourceFacade {
static func responseToUserMuteAction(
dependency: NeedsDependency & AuthContextProvider,
account: Mastodon.Entity.Account
) async throws {
) async throws -> Mastodon.Entity.Relationship {
let selectionFeedbackGenerator = await UISelectionFeedbackGenerator()
await selectionFeedbackGenerator.selectionChanged()
_ = try await dependency.context.apiService.toggleMute(
let response = try await dependency.context.apiService.toggleMute(
authenticationBox: dependency.authContext.mastodonAuthenticationBox,
account: account
)
} // end func
return response.value
}
}

View File

@ -151,10 +151,11 @@ extension DataSourceFacade {
}
@MainActor
static func responseToMenuAction(
static func responseToMenuAction<T>(
dependency: UIViewController & NeedsDependency & AuthContextProvider & DataSourceProvider,
action: MastodonMenu.Action,
menuContext: MenuContext
menuContext: MenuContext,
completion: ((T) -> Void)? = { (param: Void) in }
) async throws {
switch action {
case .hideReblogs(let actionContext):
@ -200,11 +201,15 @@ extension DataSourceFacade {
) { [weak dependency] _ in
guard let dependency else { return }
Task {
try await DataSourceFacade.responseToUserMuteAction(
let newRelationship = try await DataSourceFacade.responseToUserMuteAction(
dependency: dependency,
account: menuContext.author
)
} // end Task
if let completion {
completion(newRelationship as! T)
}
}
}
alertController.addAction(confirmAction)
let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel)
@ -222,10 +227,14 @@ extension DataSourceFacade {
) { [weak dependency] _ in
guard let dependency else { return }
Task {
try await DataSourceFacade.responseToUserBlockAction(
let newRelationship = try await DataSourceFacade.responseToUserBlockAction(
dependency: dependency,
user: menuContext.author
)
if let completion {
completion(newRelationship as! T)
}
}
}
alertController.addAction(confirmAction)

View File

@ -30,8 +30,8 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider & Aut
assertionFailure("only works for status data provider")
return
}
try await DataSourceFacade.responseToMenuAction(
_ = try await DataSourceFacade.responseToMenuAction(
dependency: self,
action: action,
menuContext: .init(

View File

@ -316,17 +316,28 @@ extension ProfileViewController {
viewModel.$accountForEdit
.assign(to: \.accountForEdit, on: headerViewModel)
.store(in: &disposeBag)
#warning("TODO: Implement")
// timeline
// [
// viewModel.postsUserTimelineViewModel,
// viewModel.repliesUserTimelineViewModel,
// viewModel.mediaUserTimelineViewModel,
// ].forEach { userTimelineViewModel in
// 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.postsUserTimelineViewModel,
viewModel.repliesUserTimelineViewModel,
viewModel.mediaUserTimelineViewModel,
].forEach { userTimelineViewModel in
viewModel.relationship.publisher
.map { $0.blocking }
.assign(to: \UserTimelineViewModel.isBlocking, on: userTimelineViewModel)
.store(in: &disposeBag)
viewModel.relationship.publisher
.compactMap { $0.blockedBy }
.assign(to: \UserTimelineViewModel.isBlockedBy, on: userTimelineViewModel)
.store(in: &disposeBag)
viewModel.$account
.compactMap { $0.suspended }
.assign(to: \UserTimelineViewModel.isSuspended, on: userTimelineViewModel)
.store(in: &disposeBag)
}
// about
let aboutViewModel = viewModel.profileAboutViewModel
@ -843,18 +854,49 @@ extension ProfileViewController: ProfileAboutViewControllerDelegate {
// MARK: - MastodonMenuDelegate
extension ProfileViewController: MastodonMenuDelegate {
func menuAction(_ action: MastodonMenu.Action) {
switch action {
case .muteUser(_),
.blockUser(_),
.hideReblogs(_):
Task {
try await DataSourceFacade.responseToMenuAction(
dependency: self,
action: action,
menuContext: DataSourceFacade.MenuContext(
author: viewModel.account,
statusViewModel: nil,
button: nil,
barButtonItem: self.moreMenuBarButtonItem
)) { [weak self] newRelationship in
guard let self else { return }
self.viewModel.relationship = newRelationship
}
}
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
}
Task {
try await DataSourceFacade.responseToMenuAction(
dependency: self,
action: action,
menuContext: DataSourceFacade.MenuContext(
author: viewModel.account,
statusViewModel: nil,
button: nil,
barButtonItem: self.moreMenuBarButtonItem
)
)
}
}
}