diff --git a/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift b/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift index 81f723402..c242220d8 100644 --- a/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift +++ b/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift @@ -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 diff --git a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView+ViewModel.swift b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView+ViewModel.swift index 809eb9a4c..7c01850be 100644 --- a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView+ViewModel.swift +++ b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView+ViewModel.swift @@ -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) } diff --git a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift index 046b74876..a3af8379c 100644 --- a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift +++ b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift @@ -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) diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index 35702c0d8..992e7d9b1 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -31,6 +31,7 @@ final class ProfileViewController: UIViewController, NeedsDependency, MediaPrevi weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } var disposeBag = Set() + //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 diff --git a/Mastodon/Scene/Profile/ProfileViewModel.swift b/Mastodon/Scene/Profile/ProfileViewModel.swift index 76969dedc..388a733bf 100644 --- a/Mastodon/Scene/Profile/ProfileViewModel.swift +++ b/Mastodon/Scene/Profile/ProfileViewModel.swift @@ -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 diff --git a/MastodonSDK/Sources/MastodonUI/View/Control/ProfileRelationshipActionButton.swift b/MastodonSDK/Sources/MastodonUI/View/Control/ProfileRelationshipActionButton.swift index e7408f5f7..187a3618e 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Control/ProfileRelationshipActionButton.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Control/ProfileRelationshipActionButton.swift @@ -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 }