Add some actions to Relationship-action-button (IOS-192)
Well, it's basically just unblock, unmute or follow/unfollow
This commit is contained in:
parent
59fe79fe49
commit
6225c50008
|
@ -14,27 +14,6 @@ extension DataSourceFacade {
|
|||
static func responseToUserBlockAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
account: Mastodon.Entity.Account
|
||||
) async throws {
|
||||
let selectionFeedbackGenerator = await UISelectionFeedbackGenerator()
|
||||
await selectionFeedbackGenerator.selectionChanged()
|
||||
|
||||
let apiService = dependency.context.apiService
|
||||
let authBox = dependency.authContext.mastodonAuthenticationBox
|
||||
|
||||
_ = try await apiService.toggleBlock(
|
||||
account: account,
|
||||
authenticationBox: authBox
|
||||
)
|
||||
|
||||
try await dependency.context.apiService.getBlocked(
|
||||
authenticationBox: authBox
|
||||
)
|
||||
dependency.context.authenticationService.fetchFollowingAndBlockedAsync()
|
||||
}
|
||||
|
||||
static func responseToUserBlockAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
user: Mastodon.Entity.Account
|
||||
) async throws -> Mastodon.Entity.Relationship {
|
||||
let selectionFeedbackGenerator = await UISelectionFeedbackGenerator()
|
||||
await selectionFeedbackGenerator.selectionChanged()
|
||||
|
@ -43,7 +22,7 @@ extension DataSourceFacade {
|
|||
let authBox = dependency.authContext.mastodonAuthenticationBox
|
||||
|
||||
let response = try await apiService.toggleBlock(
|
||||
user: user,
|
||||
account: account,
|
||||
authenticationBox: authBox
|
||||
)
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ extension DataSourceFacade {
|
|||
Task {
|
||||
let newRelationship = try await DataSourceFacade.responseToUserBlockAction(
|
||||
dependency: dependency,
|
||||
user: menuContext.author
|
||||
account: menuContext.author
|
||||
)
|
||||
|
||||
if let completion {
|
||||
|
|
|
@ -21,21 +21,21 @@ extension DataSourceFacade {
|
|||
|
||||
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.append(account.id)
|
||||
case .request:
|
||||
_ = try await DataSourceFacade.responseToUserFollowAction(
|
||||
_ = try await DataSourceFacade.responseToUserFollowAction(
|
||||
dependency: dependency,
|
||||
account: account
|
||||
)
|
||||
|
||||
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs.append(account.id)
|
||||
case .unfollow:
|
||||
_ = try await DataSourceFacade.responseToUserFollowAction(
|
||||
_ = try await DataSourceFacade.responseToUserFollowAction(
|
||||
dependency: dependency,
|
||||
account: account
|
||||
)
|
||||
|
||||
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.removeAll(where: { $0 == account.id })
|
||||
case .blocked:
|
||||
try await DataSourceFacade.responseToUserBlockAction(
|
||||
_ = try await DataSourceFacade.responseToUserBlockAction(
|
||||
dependency: dependency,
|
||||
account: account
|
||||
)
|
||||
|
@ -43,7 +43,7 @@ extension DataSourceFacade {
|
|||
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.blockedUserIds.append(account.id)
|
||||
|
||||
case .pending:
|
||||
_ = try await DataSourceFacade.responseToUserFollowAction(
|
||||
_ = try await DataSourceFacade.responseToUserFollowAction(
|
||||
dependency: dependency,
|
||||
account: account
|
||||
)
|
||||
|
|
|
@ -686,62 +686,65 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
|
|||
profileHeaderView: ProfileHeaderView,
|
||||
relationshipButtonDidPressed button: ProfileRelationshipActionButton
|
||||
) {
|
||||
|
||||
// let relationshipActionSet = viewModel.relationshipViewModel.optionSet ?? .none
|
||||
#warning("TODO: Implement")
|
||||
// handle edit logic for editable profile
|
||||
// handle relationship logic for non-editable profile
|
||||
if viewModel.me == viewModel.account {
|
||||
// // do nothing when updating
|
||||
guard !viewModel.isUpdating else { return }
|
||||
editProfile()
|
||||
} else {
|
||||
editRelationship()
|
||||
}
|
||||
}
|
||||
|
||||
let profileHeaderViewModel = profileHeaderViewController.viewModel
|
||||
guard let profileAboutViewModel = profilePagingViewController.viewModel.profileAboutViewController.viewModel else { return }
|
||||
|
||||
let isEdited = profileHeaderViewModel.isEdited || profileAboutViewModel.isEdited
|
||||
|
||||
if isEdited {
|
||||
// update profile when edited
|
||||
viewModel.isUpdating = true
|
||||
Task { @MainActor in
|
||||
do {
|
||||
// TODO: handle error
|
||||
let updatedAccount = try await viewModel.updateProfileInfo(
|
||||
headerProfileInfo: profileHeaderViewModel.profileInfoEditing,
|
||||
aboutProfileInfo: profileAboutViewModel.profileInfoEditing
|
||||
).value
|
||||
self.viewModel.isEditing = false
|
||||
self.viewModel.account = updatedAccount
|
||||
|
||||
} catch {
|
||||
let alertController = UIAlertController(
|
||||
for: error,
|
||||
title: L10n.Common.Alerts.EditProfileFailure.title,
|
||||
preferredStyle: .alert
|
||||
)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
|
||||
alertController.addAction(okAction)
|
||||
self.present(alertController, animated: true)
|
||||
private func editProfile() {
|
||||
// do nothing when updating
|
||||
guard !viewModel.isUpdating else { return }
|
||||
|
||||
let profileHeaderViewModel = profileHeaderViewController.viewModel
|
||||
guard let profileAboutViewModel = profilePagingViewController.viewModel.profileAboutViewController.viewModel else { return }
|
||||
|
||||
let isEdited = profileHeaderViewModel.isEdited || profileAboutViewModel.isEdited
|
||||
|
||||
if isEdited {
|
||||
// update profile when edited
|
||||
viewModel.isUpdating = true
|
||||
Task { @MainActor in
|
||||
do {
|
||||
// TODO: handle error
|
||||
let updatedAccount = try await viewModel.updateProfileInfo(
|
||||
headerProfileInfo: profileHeaderViewModel.profileInfoEditing,
|
||||
aboutProfileInfo: profileAboutViewModel.profileInfoEditing
|
||||
).value
|
||||
self.viewModel.isEditing = false
|
||||
self.viewModel.account = updatedAccount
|
||||
|
||||
} catch {
|
||||
let alertController = UIAlertController(
|
||||
for: error,
|
||||
title: L10n.Common.Alerts.EditProfileFailure.title,
|
||||
preferredStyle: .alert
|
||||
)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
|
||||
alertController.addAction(okAction)
|
||||
self.present(alertController, animated: true)
|
||||
}
|
||||
|
||||
// finish updating
|
||||
self.viewModel.isUpdating = false
|
||||
}
|
||||
} else {
|
||||
// set `updating` then toggle `edit` state
|
||||
viewModel.isUpdating = true
|
||||
viewModel.fetchEditProfileInfo()
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] completion in
|
||||
guard let self = self else { return }
|
||||
defer {
|
||||
// finish updating
|
||||
self.viewModel.isUpdating = false
|
||||
}
|
||||
|
||||
// finish updating
|
||||
self.viewModel.isUpdating = false
|
||||
} // end Task
|
||||
} else {
|
||||
// set `updating` then toggle `edit` state
|
||||
viewModel.isUpdating = true
|
||||
viewModel.fetchEditProfileInfo()
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] completion in
|
||||
guard let self = self else { return }
|
||||
defer {
|
||||
// finish updating
|
||||
self.viewModel.isUpdating = false
|
||||
}
|
||||
switch completion {
|
||||
switch completion {
|
||||
case .failure(let error):
|
||||
let alertController = UIAlertController(for: error, title: L10n.Common.Alerts.EditProfileFailure.title, preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
|
||||
alertController.addAction(okAction)
|
||||
_ = self.coordinator.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
|
@ -751,82 +754,101 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
|
|||
case .finished:
|
||||
// enter editing mode
|
||||
self.viewModel.isEditing.toggle()
|
||||
}
|
||||
} receiveValue: { [weak self] response in
|
||||
guard let self = self else { return }
|
||||
self.viewModel.accountForEdit = response.value
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
} else {
|
||||
// guard let relationshipAction = relationshipActionSet.highPriorityAction(except: .editOptions) else { return }
|
||||
guard let relationship = viewModel.relationship else { return }
|
||||
|
||||
print(relationship)
|
||||
// switch relationshipAction {
|
||||
// case .none:
|
||||
// break
|
||||
// case .follow, .request, .pending, .following:
|
||||
// guard let user = viewModel.user else { return }
|
||||
// let record = ManagedObjectRecord<MastodonUser>(objectID: user.objectID)
|
||||
// Task {
|
||||
// try await DataSourceFacade.responseToUserFollowAction(
|
||||
// dependency: self,
|
||||
// user: record
|
||||
// )
|
||||
// }
|
||||
// case .muting:
|
||||
// guard let user = viewModel.user else { return }
|
||||
// let name = user.displayNameWithFallback
|
||||
//
|
||||
// let alertController = UIAlertController(
|
||||
// title: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.title,
|
||||
// message: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.message(name),
|
||||
// preferredStyle: .alert
|
||||
// )
|
||||
// let record = ManagedObjectRecord<MastodonUser>(objectID: user.objectID)
|
||||
// let unmuteAction = UIAlertAction(title: L10n.Common.Controls.Friendship.unmute, style: .default) { [weak self] _ in
|
||||
// guard let self = self else { return }
|
||||
// Task {
|
||||
// try await DataSourceFacade.responseToUserMuteAction(
|
||||
// dependency: self,
|
||||
// user: record
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// alertController.addAction(unmuteAction)
|
||||
// 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
|
||||
//
|
||||
// let alertController = UIAlertController(
|
||||
// title: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.title,
|
||||
// message: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.message(name),
|
||||
// preferredStyle: .alert
|
||||
// )
|
||||
// let record = ManagedObjectRecord<MastodonUser>(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.responseToUserBlockAction(
|
||||
// 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 .blocked, .showReblogs, .isMyself,.followingBy, .blockingBy, .suspended, .edit, .editing, .updating:
|
||||
// break
|
||||
// }
|
||||
} receiveValue: { [weak self] response in
|
||||
guard let self = self else { return }
|
||||
self.viewModel.accountForEdit = response.value
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func editRelationship() {
|
||||
guard let relationship = viewModel.relationship else { return }
|
||||
|
||||
let account = viewModel.account
|
||||
|
||||
if relationship.blocking {
|
||||
let name = account.displayNameWithFallback
|
||||
|
||||
let alertController = UIAlertController(
|
||||
title: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.title,
|
||||
message: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.message(name),
|
||||
preferredStyle: .alert
|
||||
)
|
||||
let unblockAction = UIAlertAction(title: L10n.Common.Controls.Friendship.unblock, style: .default) { [weak self] _ in
|
||||
guard let self else { return }
|
||||
Task {
|
||||
let newRelationship = try await DataSourceFacade.responseToUserBlockAction(
|
||||
dependency: self,
|
||||
account: account
|
||||
)
|
||||
|
||||
self.viewModel.relationship = newRelationship
|
||||
}
|
||||
}
|
||||
alertController.addAction(unblockAction)
|
||||
let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel)
|
||||
alertController.addAction(cancelAction)
|
||||
coordinator.present(scene: .alertController(alertController: alertController), transition: .alertController(animated: true))
|
||||
} else if relationship.muting {
|
||||
let name = account.displayNameWithFallback
|
||||
|
||||
let alertController = UIAlertController(
|
||||
title: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.title,
|
||||
message: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.message(name),
|
||||
preferredStyle: .alert
|
||||
)
|
||||
|
||||
let unmuteAction = UIAlertAction(title: L10n.Common.Controls.Friendship.unmute, style: .default) { [weak self] _ in
|
||||
guard let self else { return }
|
||||
Task {
|
||||
let newRelationship = try await DataSourceFacade.responseToUserMuteAction(
|
||||
dependency: self,
|
||||
account: account
|
||||
)
|
||||
|
||||
self.viewModel.relationship = newRelationship
|
||||
}
|
||||
}
|
||||
alertController.addAction(unmuteAction)
|
||||
let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel)
|
||||
alertController.addAction(cancelAction)
|
||||
coordinator.present(scene: .alertController(alertController: alertController), transition: .alertController(animated: true))
|
||||
} else {
|
||||
Task { [weak self] in
|
||||
guard let self else { return }
|
||||
|
||||
let newRelationship = try await DataSourceFacade.responseToUserFollowAction(
|
||||
dependency: self,
|
||||
account: viewModel.account
|
||||
)
|
||||
|
||||
self.viewModel.relationship = newRelationship
|
||||
// update account?
|
||||
// update me?
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// switch relationshipAction {
|
||||
// case .none:
|
||||
// break
|
||||
// case .follow, .request, .pending, .following:
|
||||
// guard let user = viewModel.user else { return }
|
||||
// let record = ManagedObjectRecord<MastodonUser>(objectID: user.objectID)
|
||||
// Task {
|
||||
// try await DataSourceFacade.responseToUserFollowAction(
|
||||
// dependency: self,
|
||||
// user: record
|
||||
// )
|
||||
// }
|
||||
// case .muting:
|
||||
// case .blocked, .showReblogs, .isMyself,.followingBy, .blockingBy, .suspended, .edit, .editing, .updating:
|
||||
// break
|
||||
// }
|
||||
}
|
||||
|
||||
func profileHeaderViewController(
|
||||
_ profileHeaderViewController: ProfileHeaderViewController,
|
||||
profileHeaderView: ProfileHeaderView,
|
||||
|
|
|
@ -108,7 +108,7 @@ extension ReportResultViewController {
|
|||
guard !self.viewModel.isRequestMute else { return }
|
||||
self.viewModel.isRequestMute = true
|
||||
do {
|
||||
try await DataSourceFacade.responseToUserMuteAction(
|
||||
_ = try await DataSourceFacade.responseToUserMuteAction(
|
||||
dependency: self,
|
||||
account: self.viewModel.account
|
||||
)
|
||||
|
@ -128,9 +128,9 @@ extension ReportResultViewController {
|
|||
guard !self.viewModel.isRequestBlock else { return }
|
||||
self.viewModel.isRequestBlock = true
|
||||
do {
|
||||
try await DataSourceFacade.responseToUserBlockAction(
|
||||
_ = try await DataSourceFacade.responseToUserBlockAction(
|
||||
dependency: self,
|
||||
user: self.viewModel.account
|
||||
account: self.viewModel.account
|
||||
)
|
||||
} catch {
|
||||
// handle error
|
||||
|
|
|
@ -147,7 +147,7 @@ extension Persistence.MastodonUser {
|
|||
let me = context.me
|
||||
|
||||
user.update(isFollowing: relationship.following, by: me)
|
||||
relationship.requested.flatMap { user.update(isFollowRequested: $0, by: me) }
|
||||
user.update(isFollowRequested: relationship.requested, by: me)
|
||||
// relationship.endorsed.flatMap { user.update(isEndorsed: $0, by: me) }
|
||||
me.update(isFollowing: relationship.followedBy, by: user)
|
||||
user.update(isMuting: relationship.muting, by: me)
|
||||
|
|
|
@ -64,51 +64,7 @@ extension APIService {
|
|||
account: Mastodon.Entity.Account,
|
||||
authenticationBox: MastodonAuthenticationBox
|
||||
) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> {
|
||||
|
||||
guard let me = authenticationBox.authentication.account(),
|
||||
let relationship = try await relationship(forAccounts: [account], authenticationBox: authenticationBox).value.first
|
||||
else { throw APIError.implicit(.badRequest) }
|
||||
|
||||
let blockContext = MastodonBlockContext(
|
||||
sourceUserID: me.id,
|
||||
targetUserID: account.id,
|
||||
targetUsername: account.username,
|
||||
isBlocking: relationship.blocking,
|
||||
isFollowing: relationship.following
|
||||
)
|
||||
|
||||
let result: Result<Mastodon.Response.Content<Mastodon.Entity.Relationship>, Error>
|
||||
do {
|
||||
if blockContext.isBlocking {
|
||||
let response = try await Mastodon.API.Account.unblock(
|
||||
session: session,
|
||||
domain: authenticationBox.domain,
|
||||
accountID: blockContext.targetUserID,
|
||||
authorization: authenticationBox.userAuthorization
|
||||
).singleOutput()
|
||||
result = .success(response)
|
||||
} else {
|
||||
let response = try await Mastodon.API.Account.block(
|
||||
session: session,
|
||||
domain: authenticationBox.domain,
|
||||
accountID: blockContext.targetUserID,
|
||||
authorization: authenticationBox.userAuthorization
|
||||
).singleOutput()
|
||||
result = .success(response)
|
||||
}
|
||||
} catch {
|
||||
result = .failure(error)
|
||||
}
|
||||
|
||||
let response = try result.get()
|
||||
return response
|
||||
}
|
||||
|
||||
public func toggleBlock(
|
||||
user: Mastodon.Entity.Account,
|
||||
authenticationBox: MastodonAuthenticationBox
|
||||
) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> {
|
||||
guard let relationship = try await relationship(forAccounts: [user], authenticationBox: authenticationBox).value.first else {
|
||||
guard let relationship = try await relationship(forAccounts: [account], authenticationBox: authenticationBox).value.first else {
|
||||
throw APIError.implicit(.badRequest)
|
||||
}
|
||||
|
||||
|
@ -118,14 +74,14 @@ extension APIService {
|
|||
response = try await Mastodon.API.Account.unblock(
|
||||
session: session,
|
||||
domain: authenticationBox.domain,
|
||||
accountID: user.id,
|
||||
accountID: account.id,
|
||||
authorization: authenticationBox.userAuthorization
|
||||
).singleOutput()
|
||||
} else {
|
||||
response = try await Mastodon.API.Account.block(
|
||||
session: session,
|
||||
domain: authenticationBox.domain,
|
||||
accountID: user.id,
|
||||
accountID: account.id,
|
||||
authorization: authenticationBox.userAuthorization
|
||||
).singleOutput()
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ extension Mastodon.Entity {
|
|||
/// Are you following this user?
|
||||
public let following: Bool
|
||||
/// Do you have a pending follow request for this user?
|
||||
public let requested: Bool?
|
||||
public let requested: Bool
|
||||
/// Are you featuring this user on your profile?
|
||||
public let endorsed: Bool
|
||||
/// Are you followed by this user?
|
||||
|
|
|
@ -87,7 +87,7 @@ extension ProfileRelationshipActionButton {
|
|||
|
||||
setTitle(title, for: .normal)
|
||||
|
||||
if relationship.blocking || account.suspended ?? false {
|
||||
if relationship.blockedBy || account.suspended ?? false {
|
||||
isEnabled = false
|
||||
} else {
|
||||
isEnabled = true
|
||||
|
|
Loading…
Reference in New Issue