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:
parent
0e207cf65d
commit
62cc9105a9
|
@ -330,43 +330,45 @@ extension ProfileHeaderViewController: ProfileHeaderViewDelegate {
|
||||||
dashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView,
|
dashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView,
|
||||||
meter: ProfileStatusDashboardView.Meter
|
meter: ProfileStatusDashboardView.Meter
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
guard profileHeaderView.viewModel.isEditing == false else { return }
|
||||||
|
|
||||||
switch meter {
|
switch meter {
|
||||||
case .post:
|
case .post:
|
||||||
// do nothing
|
// do nothing
|
||||||
break
|
break
|
||||||
case .follower:
|
case .follower:
|
||||||
guard let domain = viewModel.account.domain else { return }
|
guard let domain = viewModel.account.domain else { return }
|
||||||
let userID = viewModel.account.id
|
let userID = viewModel.account.id
|
||||||
let followerListViewModel = FollowerListViewModel(
|
let followerListViewModel = FollowerListViewModel(
|
||||||
context: context,
|
context: context,
|
||||||
authContext: viewModel.authContext,
|
authContext: viewModel.authContext,
|
||||||
domain: domain,
|
domain: domain,
|
||||||
userID: userID
|
userID: userID
|
||||||
)
|
)
|
||||||
_ = coordinator.present(
|
_ = coordinator.present(
|
||||||
scene: .follower(viewModel: followerListViewModel),
|
scene: .follower(viewModel: followerListViewModel),
|
||||||
from: self,
|
from: self,
|
||||||
transition: .show
|
transition: .show
|
||||||
)
|
)
|
||||||
|
|
||||||
case .following:
|
|
||||||
guard let domain = viewModel.account.domain else { return }
|
|
||||||
|
|
||||||
let userID = viewModel.account.id
|
case .following:
|
||||||
let followingListViewModel = FollowingListViewModel(
|
guard let domain = viewModel.account.domain else { return }
|
||||||
context: context,
|
|
||||||
authContext: viewModel.authContext,
|
let userID = viewModel.account.id
|
||||||
domain: domain,
|
let followingListViewModel = FollowingListViewModel(
|
||||||
userID: userID
|
context: context,
|
||||||
)
|
authContext: viewModel.authContext,
|
||||||
_ = coordinator.present(
|
domain: domain,
|
||||||
scene: .following(viewModel: followingListViewModel),
|
userID: userID
|
||||||
from: self,
|
)
|
||||||
transition: .show
|
_ = coordinator.present(
|
||||||
)
|
scene: .following(viewModel: followingListViewModel),
|
||||||
|
from: self,
|
||||||
|
transition: .show
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - MetaTextDelegate
|
// MARK: - MetaTextDelegate
|
||||||
|
|
|
@ -49,7 +49,6 @@ extension ProfileHeaderView {
|
||||||
@Published var me: Mastodon.Entity.Account
|
@Published var me: Mastodon.Entity.Account
|
||||||
@Published var account: Mastodon.Entity.Account
|
@Published var account: Mastodon.Entity.Account
|
||||||
@Published var relationship: Mastodon.Entity.Relationship?
|
@Published var relationship: Mastodon.Entity.Relationship?
|
||||||
@Published var isRelationshipActionButtonHidden = false
|
|
||||||
@Published var isMyself = false
|
@Published var isMyself = false
|
||||||
|
|
||||||
init(account: Mastodon.Entity.Account, me: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?) {
|
init(account: Mastodon.Entity.Account, me: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?) {
|
||||||
|
@ -259,10 +258,6 @@ extension ProfileHeaderView.ViewModel {
|
||||||
animator.startAnimation()
|
animator.startAnimation()
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
// relationship
|
|
||||||
$isRelationshipActionButtonHidden
|
|
||||||
.assign(to: \.isHidden, on: view.relationshipActionButton)
|
|
||||||
.store(in: &disposeBag)
|
|
||||||
|
|
||||||
Publishers.CombineLatest3(
|
Publishers.CombineLatest3(
|
||||||
Publishers.CombineLatest3($me, $account, $relationship).eraseToAnyPublisher(),
|
Publishers.CombineLatest3($me, $account, $relationship).eraseToAnyPublisher(),
|
||||||
|
@ -272,9 +267,9 @@ extension ProfileHeaderView.ViewModel {
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { tuple, isEditing, isUpdating in
|
.sink { tuple, isEditing, isUpdating in
|
||||||
let (me, account, relationship) = tuple
|
let (me, account, relationship) = tuple
|
||||||
guard let relationship else { return }
|
|
||||||
|
|
||||||
view.relationshipActionButton.configure(relationship: relationship, between: account, and: me, isEditing: isEditing, isUpdating: isUpdating)
|
view.relationshipActionButton.configure(relationship: relationship, between: account, and: me, isEditing: isEditing, isUpdating: isUpdating)
|
||||||
|
view.configure(state: isEditing ? .editing : .normal)
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,7 +408,6 @@ final class ProfileHeaderView: UIView {
|
||||||
nameTextFieldBackgroundView.trailingAnchor.constraint(equalTo: nameMetaText.textView.trailingAnchor, constant: 5),
|
nameTextFieldBackgroundView.trailingAnchor.constraint(equalTo: nameMetaText.textView.trailingAnchor, constant: 5),
|
||||||
nameMetaText.textView.bottomAnchor.constraint(equalTo: nameTextFieldBackgroundView.bottomAnchor),
|
nameMetaText.textView.bottomAnchor.constraint(equalTo: nameTextFieldBackgroundView.bottomAnchor),
|
||||||
])
|
])
|
||||||
// nameMetaText.textView.setContentHuggingPriority(, for: <#T##NSLayoutConstraint.Axis#>)
|
|
||||||
|
|
||||||
nameContainerStackView.addArrangedSubview(displayNameStackView)
|
nameContainerStackView.addArrangedSubview(displayNameStackView)
|
||||||
nameContainerStackView.addArrangedSubview(usernameButton)
|
nameContainerStackView.addArrangedSubview(usernameButton)
|
||||||
|
|
|
@ -31,6 +31,7 @@ final class ProfileViewController: UIViewController, NeedsDependency, MediaPrevi
|
||||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
|
||||||
var disposeBag = Set<AnyCancellable>()
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
//TODO: Replace with something better than !
|
||||||
var viewModel: ProfileViewModel!
|
var viewModel: ProfileViewModel!
|
||||||
|
|
||||||
let mediaPreviewTransitionController = MediaPreviewTransitionController()
|
let mediaPreviewTransitionController = MediaPreviewTransitionController()
|
||||||
|
@ -389,31 +390,6 @@ extension ProfileViewController {
|
||||||
self.navigationItem.title = name
|
self.navigationItem.title = name
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.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() {
|
private func bindMoreBarButtonItem() {
|
||||||
|
@ -520,6 +496,7 @@ extension ProfileViewController {
|
||||||
|
|
||||||
@objc private func cancelEditingBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
@objc private func cancelEditingBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||||
viewModel.isEditing = false
|
viewModel.isEditing = false
|
||||||
|
profileHeaderViewController.viewModel.isEditing = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func settingBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
@objc private func settingBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||||
|
@ -717,7 +694,9 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
|
||||||
|
|
||||||
private func editProfile() {
|
private func editProfile() {
|
||||||
// do nothing when updating
|
// do nothing when updating
|
||||||
guard !viewModel.isUpdating else { return }
|
guard viewModel.isUpdating == false else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let profileHeaderViewModel = profileHeaderViewController.viewModel
|
let profileHeaderViewModel = profileHeaderViewController.viewModel
|
||||||
guard let profileAboutViewModel = profilePagingViewController.viewModel.profileAboutViewController.viewModel else { return }
|
guard let profileAboutViewModel = profilePagingViewController.viewModel.profileAboutViewController.viewModel else { return }
|
||||||
|
@ -751,30 +730,33 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
|
||||||
// finish updating
|
// finish updating
|
||||||
self.viewModel.isUpdating = false
|
self.viewModel.isUpdating = false
|
||||||
}
|
}
|
||||||
} else {
|
} else if viewModel.isEditing == false {
|
||||||
// set `updating` then toggle `edit` state
|
// set `updating` then toggle `edit` state
|
||||||
viewModel.isUpdating = true
|
viewModel.isUpdating = true
|
||||||
|
profileHeaderViewController.viewModel.isUpdating = true
|
||||||
viewModel.fetchEditProfileInfo()
|
viewModel.fetchEditProfileInfo()
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] completion in
|
.sink { [weak self] completion in
|
||||||
guard let self = self else { return }
|
guard let self else { return }
|
||||||
defer {
|
defer {
|
||||||
// finish updating
|
// finish updating
|
||||||
self.viewModel.isUpdating = false
|
self.viewModel.isUpdating = false
|
||||||
|
self.profileHeaderViewController.viewModel.isUpdating = false
|
||||||
}
|
}
|
||||||
switch completion {
|
switch completion {
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
let alertController = UIAlertController(for: error, title: L10n.Common.Alerts.EditProfileFailure.title, preferredStyle: .alert)
|
let alertController = UIAlertController(for: error, title: L10n.Common.Alerts.EditProfileFailure.title, preferredStyle: .alert)
|
||||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
|
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
|
||||||
alertController.addAction(okAction)
|
alertController.addAction(okAction)
|
||||||
_ = self.coordinator.present(
|
_ = self.coordinator.present(
|
||||||
scene: .alertController(alertController: alertController),
|
scene: .alertController(alertController: alertController),
|
||||||
from: nil,
|
from: nil,
|
||||||
transition: .alertController(animated: true, completion: nil)
|
transition: .alertController(animated: true, completion: nil)
|
||||||
)
|
)
|
||||||
case .finished:
|
case .finished:
|
||||||
// enter editing mode
|
// enter editing mode
|
||||||
self.viewModel.isEditing.toggle()
|
self.viewModel.isEditing = true
|
||||||
|
self.profileHeaderViewController.viewModel.isEditing = true
|
||||||
}
|
}
|
||||||
} receiveValue: { [weak self] response in
|
} receiveValue: { [weak self] response in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
@ -785,7 +767,9 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func editRelationship() {
|
private func editRelationship() {
|
||||||
guard let relationship = viewModel.relationship else { return }
|
guard let relationship = viewModel.relationship, viewModel.isUpdating == false else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let account = viewModel.account
|
let account = viewModel.account
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ class ProfileViewModel: NSObject {
|
||||||
|
|
||||||
@Published var userIdentifier: UserIdentifier? = nil
|
@Published var userIdentifier: UserIdentifier? = nil
|
||||||
|
|
||||||
@Published var isRelationshipActionButtonHidden: Bool = true
|
|
||||||
@Published var isReplyBarButtonItemHidden: Bool = true
|
@Published var isReplyBarButtonItemHidden: Bool = true
|
||||||
@Published var isMoreMenuBarButtonItemHidden: Bool = true
|
@Published var isMoreMenuBarButtonItemHidden: Bool = true
|
||||||
@Published var isMeBarButtonItemsHidden: Bool = true
|
@Published var isMeBarButtonItemsHidden: Bool = true
|
||||||
|
|
|
@ -11,7 +11,7 @@ import MastodonSDK
|
||||||
import MastodonLocalization
|
import MastodonLocalization
|
||||||
|
|
||||||
public final class ProfileRelationshipActionButton: UIButton {
|
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)
|
let isMyself = (account == me)
|
||||||
|
|
||||||
|
@ -22,40 +22,39 @@ public final class ProfileRelationshipActionButton: UIButton {
|
||||||
configuration.activityIndicatorColorTransformer = UIConfigurationColorTransformer({ _ in return Asset.Colors.Label.primaryReverse.color })
|
configuration.activityIndicatorColorTransformer = UIConfigurationColorTransformer({ _ in return Asset.Colors.Label.primaryReverse.color })
|
||||||
configuration.background.cornerRadius = 10
|
configuration.background.cornerRadius = 10
|
||||||
|
|
||||||
var title: String
|
let title: String
|
||||||
|
|
||||||
if isMyself {
|
switch (isMyself, isUpdating, relationship) {
|
||||||
|
case (true, _, _):
|
||||||
if isEditing {
|
if isEditing {
|
||||||
title = L10n.Common.Controls.Actions.save
|
title = L10n.Common.Controls.Actions.save
|
||||||
} else {
|
} else {
|
||||||
title = L10n.Common.Controls.Friendship.editInfo
|
title = L10n.Common.Controls.Friendship.editInfo
|
||||||
}
|
}
|
||||||
} else if relationship.blocking {
|
configuration.showsActivityIndicator = false
|
||||||
title = L10n.Common.Controls.Friendship.blocked
|
case (_, true, _):
|
||||||
} else if relationship.domainBlocking {
|
title = ""
|
||||||
title = L10n.Common.Controls.Friendship.domainBlocked
|
configuration.showsActivityIndicator = true
|
||||||
} else if relationship.requested {
|
case (false, false, .some(let relationship)):
|
||||||
title = L10n.Common.Controls.Friendship.pending
|
configuration.showsActivityIndicator = false
|
||||||
} else if relationship.muting {
|
|
||||||
title = L10n.Common.Controls.Friendship.muted
|
if relationship.blocking {
|
||||||
} else if relationship.following {
|
title = L10n.Common.Controls.Friendship.blocked
|
||||||
title = L10n.Common.Controls.Friendship.following
|
} else if relationship.domainBlocking {
|
||||||
} else if account.locked {
|
title = L10n.Common.Controls.Friendship.domainBlocked
|
||||||
title = L10n.Common.Controls.Friendship.request
|
} else if relationship.requested {
|
||||||
} else {
|
title = L10n.Common.Controls.Friendship.pending
|
||||||
title = L10n.Common.Controls.Friendship.follow
|
} else if relationship.muting {
|
||||||
}
|
title = L10n.Common.Controls.Friendship.muted
|
||||||
|
} else if relationship.following {
|
||||||
if relationship.blockedBy || account.suspended ?? false {
|
title = L10n.Common.Controls.Friendship.following
|
||||||
isEnabled = false
|
} else if account.locked {
|
||||||
} else {
|
title = L10n.Common.Controls.Friendship.request
|
||||||
isEnabled = true
|
} else {
|
||||||
}
|
title = L10n.Common.Controls.Friendship.follow
|
||||||
|
}
|
||||||
if isUpdating {
|
case (_, _, nil):
|
||||||
configuration.showsActivityIndicator = true
|
|
||||||
title = ""
|
title = ""
|
||||||
} else {
|
|
||||||
configuration.showsActivityIndicator = false
|
configuration.showsActivityIndicator = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue