Fix Profile Editing (#1245)

* Fix image-editing (#1244)

Probably introduced in 76304e5 and we just missed that :)

* Removed unused property (#1244)

* Don't allow tapping on followers/followees when editing my profile

* Remove obsolete code

relationship-update on viewDidAppear is not needed anylonger as we use update user/relationship using notifications like in the good ol days

* Make relationship optional and use switch-pattern-matching for button-configuration

* Don't change relationship when relationship is updating

* [WIP] don't toggle, but just set booleans.
This commit is contained in:
Nathan Mattes 2024-03-18 16:27:12 +01:00 committed by GitHub
parent 0e207cf65d
commit 62cc9105a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 86 additions and 108 deletions

View File

@ -330,43 +330,45 @@ extension ProfileHeaderViewController: ProfileHeaderViewDelegate {
dashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView,
meter: ProfileStatusDashboardView.Meter
) {
guard profileHeaderView.viewModel.isEditing == false else { return }
switch meter {
case .post:
// do nothing
break
case .follower:
guard let domain = viewModel.account.domain else { return }
let userID = viewModel.account.id
let followerListViewModel = FollowerListViewModel(
context: context,
authContext: viewModel.authContext,
domain: domain,
userID: userID
)
_ = coordinator.present(
scene: .follower(viewModel: followerListViewModel),
from: self,
transition: .show
)
case .following:
guard let domain = viewModel.account.domain else { return }
break
case .follower:
guard let domain = viewModel.account.domain else { return }
let userID = viewModel.account.id
let followerListViewModel = FollowerListViewModel(
context: context,
authContext: viewModel.authContext,
domain: domain,
userID: userID
)
_ = coordinator.present(
scene: .follower(viewModel: followerListViewModel),
from: self,
transition: .show
)
let userID = viewModel.account.id
let followingListViewModel = FollowingListViewModel(
context: context,
authContext: viewModel.authContext,
domain: domain,
userID: userID
)
_ = coordinator.present(
scene: .following(viewModel: followingListViewModel),
from: self,
transition: .show
)
case .following:
guard let domain = viewModel.account.domain else { return }
let userID = viewModel.account.id
let followingListViewModel = FollowingListViewModel(
context: context,
authContext: viewModel.authContext,
domain: domain,
userID: userID
)
_ = coordinator.present(
scene: .following(viewModel: followingListViewModel),
from: self,
transition: .show
)
}
}
}
// MARK: - MetaTextDelegate

View File

@ -49,7 +49,6 @@ extension ProfileHeaderView {
@Published var me: Mastodon.Entity.Account
@Published var account: Mastodon.Entity.Account
@Published var relationship: Mastodon.Entity.Relationship?
@Published var isRelationshipActionButtonHidden = false
@Published var isMyself = false
init(account: Mastodon.Entity.Account, me: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?) {
@ -259,10 +258,6 @@ extension ProfileHeaderView.ViewModel {
animator.startAnimation()
}
.store(in: &disposeBag)
// relationship
$isRelationshipActionButtonHidden
.assign(to: \.isHidden, on: view.relationshipActionButton)
.store(in: &disposeBag)
Publishers.CombineLatest3(
Publishers.CombineLatest3($me, $account, $relationship).eraseToAnyPublisher(),
@ -272,9 +267,9 @@ extension ProfileHeaderView.ViewModel {
.receive(on: DispatchQueue.main)
.sink { tuple, isEditing, isUpdating in
let (me, account, relationship) = tuple
guard let relationship else { return }
view.relationshipActionButton.configure(relationship: relationship, between: account, and: me, isEditing: isEditing, isUpdating: isUpdating)
view.configure(state: isEditing ? .editing : .normal)
}
.store(in: &disposeBag)
}

View File

@ -408,7 +408,6 @@ final class ProfileHeaderView: UIView {
nameTextFieldBackgroundView.trailingAnchor.constraint(equalTo: nameMetaText.textView.trailingAnchor, constant: 5),
nameMetaText.textView.bottomAnchor.constraint(equalTo: nameTextFieldBackgroundView.bottomAnchor),
])
// nameMetaText.textView.setContentHuggingPriority(, for: <#T##NSLayoutConstraint.Axis#>)
nameContainerStackView.addArrangedSubview(displayNameStackView)
nameContainerStackView.addArrangedSubview(usernameButton)

View File

@ -31,6 +31,7 @@ final class ProfileViewController: UIViewController, NeedsDependency, MediaPrevi
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
var disposeBag = Set<AnyCancellable>()
//TODO: Replace with something better than !
var viewModel: ProfileViewModel!
let mediaPreviewTransitionController = MediaPreviewTransitionController()
@ -389,31 +390,6 @@ extension ProfileViewController {
self.navigationItem.title = name
}
.store(in: &disposeBag)
profileHeaderViewController.profileHeaderView.viewModel.viewDidAppear
.sink(receiveValue: { [weak self] _ in
guard let self else { return }
let account = self.viewModel.account
guard let domain = account.domainFromAcct else { return }
Task {
let account = try await self.context.apiService.fetchUser(
username: account.username,
domain: domain,
authenticationBox: self.authContext.mastodonAuthenticationBox
)
guard let account else { return }
let relationship = try await self.context.apiService.relationship(forAccounts: [account], authenticationBox: self.authContext.mastodonAuthenticationBox).value.first
guard let relationship else { return }
self.viewModel.relationship = relationship
self.viewModel.account = account
}
})
.store(in: &disposeBag)
}
private func bindMoreBarButtonItem() {
@ -520,6 +496,7 @@ extension ProfileViewController {
@objc private func cancelEditingBarButtonItemPressed(_ sender: UIBarButtonItem) {
viewModel.isEditing = false
profileHeaderViewController.viewModel.isEditing = false
}
@objc private func settingBarButtonItemPressed(_ sender: UIBarButtonItem) {
@ -717,7 +694,9 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
private func editProfile() {
// do nothing when updating
guard !viewModel.isUpdating else { return }
guard viewModel.isUpdating == false else {
return
}
let profileHeaderViewModel = profileHeaderViewController.viewModel
guard let profileAboutViewModel = profilePagingViewController.viewModel.profileAboutViewController.viewModel else { return }
@ -751,30 +730,33 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
// finish updating
self.viewModel.isUpdating = false
}
} else {
} else if viewModel.isEditing == false {
// set `updating` then toggle `edit` state
viewModel.isUpdating = true
profileHeaderViewController.viewModel.isUpdating = true
viewModel.fetchEditProfileInfo()
.receive(on: DispatchQueue.main)
.sink { [weak self] completion in
guard let self = self else { return }
guard let self else { return }
defer {
// finish updating
self.viewModel.isUpdating = false
self.profileHeaderViewController.viewModel.isUpdating = false
}
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)
alertController.addAction(okAction)
_ = self.coordinator.present(
scene: .alertController(alertController: alertController),
from: nil,
transition: .alertController(animated: true, completion: nil)
)
case .finished:
// enter editing mode
self.viewModel.isEditing.toggle()
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)
alertController.addAction(okAction)
_ = self.coordinator.present(
scene: .alertController(alertController: alertController),
from: nil,
transition: .alertController(animated: true, completion: nil)
)
case .finished:
// enter editing mode
self.viewModel.isEditing = true
self.profileHeaderViewController.viewModel.isEditing = true
}
} receiveValue: { [weak self] response in
guard let self = self else { return }
@ -785,7 +767,9 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
}
private func editRelationship() {
guard let relationship = viewModel.relationship else { return }
guard let relationship = viewModel.relationship, viewModel.isUpdating == false else {
return
}
let account = viewModel.account

View File

@ -46,7 +46,6 @@ class ProfileViewModel: NSObject {
@Published var userIdentifier: UserIdentifier? = nil
@Published var isRelationshipActionButtonHidden: Bool = true
@Published var isReplyBarButtonItemHidden: Bool = true
@Published var isMoreMenuBarButtonItemHidden: Bool = true
@Published var isMeBarButtonItemsHidden: Bool = true

View File

@ -11,7 +11,7 @@ import MastodonSDK
import MastodonLocalization
public final class ProfileRelationshipActionButton: UIButton {
public func configure(relationship: Mastodon.Entity.Relationship, between account: Mastodon.Entity.Account, and me: Mastodon.Entity.Account, isEditing: Bool = false, isUpdating: Bool = false) {
public func configure(relationship: Mastodon.Entity.Relationship?, between account: Mastodon.Entity.Account, and me: Mastodon.Entity.Account, isEditing: Bool = false, isUpdating: Bool = false) {
let isMyself = (account == me)
@ -22,40 +22,39 @@ public final class ProfileRelationshipActionButton: UIButton {
configuration.activityIndicatorColorTransformer = UIConfigurationColorTransformer({ _ in return Asset.Colors.Label.primaryReverse.color })
configuration.background.cornerRadius = 10
var title: String
let title: String
if isMyself {
switch (isMyself, isUpdating, relationship) {
case (true, _, _):
if isEditing {
title = L10n.Common.Controls.Actions.save
} else {
title = L10n.Common.Controls.Friendship.editInfo
}
} else if relationship.blocking {
title = L10n.Common.Controls.Friendship.blocked
} else if relationship.domainBlocking {
title = L10n.Common.Controls.Friendship.domainBlocked
} else if relationship.requested {
title = L10n.Common.Controls.Friendship.pending
} else if relationship.muting {
title = L10n.Common.Controls.Friendship.muted
} else if relationship.following {
title = L10n.Common.Controls.Friendship.following
} else if account.locked {
title = L10n.Common.Controls.Friendship.request
} else {
title = L10n.Common.Controls.Friendship.follow
}
if relationship.blockedBy || account.suspended ?? false {
isEnabled = false
} else {
isEnabled = true
}
if isUpdating {
configuration.showsActivityIndicator = true
configuration.showsActivityIndicator = false
case (_, true, _):
title = ""
configuration.showsActivityIndicator = true
case (false, false, .some(let relationship)):
configuration.showsActivityIndicator = false
if relationship.blocking {
title = L10n.Common.Controls.Friendship.blocked
} else if relationship.domainBlocking {
title = L10n.Common.Controls.Friendship.domainBlocked
} else if relationship.requested {
title = L10n.Common.Controls.Friendship.pending
} else if relationship.muting {
title = L10n.Common.Controls.Friendship.muted
} else if relationship.following {
title = L10n.Common.Controls.Friendship.following
} else if account.locked {
title = L10n.Common.Controls.Friendship.request
} else {
title = L10n.Common.Controls.Friendship.follow
}
case (_, _, nil):
title = ""
} else {
configuration.showsActivityIndicator = false
}