From 242f351e104d53852762f80d151db2d114ceb169 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Tue, 24 Oct 2023 15:42:23 +0200 Subject: [PATCH] Update follow-button-state after (un)following a person --- .../View/Content/UserView+Configuration.swift | 5 +- .../UserTableViewCell+ViewModel.swift | 47 +++++++++---------- .../View/Content/UserView+ViewModel.swift | 1 + .../MastodonUI/View/Content/UserView.swift | 29 ++++++++++-- 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/Mastodon/Scene/Share/View/Content/UserView+Configuration.swift b/Mastodon/Scene/Share/View/Content/UserView+Configuration.swift index d67f2ec67..e3f91f462 100644 --- a/Mastodon/Scene/Share/View/Content/UserView+Configuration.swift +++ b/Mastodon/Scene/Share/View/Content/UserView+Configuration.swift @@ -21,6 +21,7 @@ extension UserView { self.delegate = delegate viewModel.user = user viewModel.account = nil + viewModel.relationship = nil Publishers.CombineLatest( user.publisher(for: \.avatar), @@ -67,9 +68,11 @@ extension UserView { .store(in: &disposeBag) } - func configure(with account: Mastodon.Entity.Account) { + func configure(with account: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?, delegate: UserViewDelegate?) { viewModel.account = account + viewModel.relationship = relationship viewModel.user = nil + self.delegate = delegate let authorUsername = PlaintextMetaContent(string: "@\(account.username)") authorUsernameLabel.configure(content: authorUsername) diff --git a/Mastodon/Scene/Share/View/TableviewCell/UserTableViewCell+ViewModel.swift b/Mastodon/Scene/Share/View/TableviewCell/UserTableViewCell+ViewModel.swift index 6c0541c2a..c96e203f0 100644 --- a/Mastodon/Scene/Share/View/TableviewCell/UserTableViewCell+ViewModel.swift +++ b/Mastodon/Scene/Share/View/TableviewCell/UserTableViewCell+ViewModel.swift @@ -38,28 +38,12 @@ extension UserTableViewCell { relationship: Mastodon.Entity.Relationship?, delegate: UserTableViewCellDelegate? ) { - userView.configure(with: account) + userView.configure(with: account, relationship: relationship, delegate: delegate) - let buttonState: UserView.ButtonState - if let relationship { - let isMe = account.id == me.id - if isMe { - buttonState = .none - } else if relationship.following { - buttonState = .unfollow - } else if relationship.blocking || (relationship.domainBlocking ?? false) { - buttonState = .blocked - } else if relationship.requested ?? false { - buttonState = .pending - } else { - buttonState = .follow - } - } else { - buttonState = .none - } + let isMe = account.id == me.id + userView.updateButtonState(with: relationship, isMe: isMe) - userView.setButtonState(buttonState) - + self.delegate = delegate } func configure( @@ -117,15 +101,30 @@ extension UserTableViewCellDelegate where Self: NeedsDependency & AuthContextPro ) } } - - func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for user: Mastodon.Entity.Account) { + func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for account: Mastodon.Entity.Account, me: MastodonUser?) { Task { + await MainActor.run { view.setButtonState(.loading) } + try await DataSourceFacade.responseToUserViewButtonAction( dependency: self, - user: user, + user: account, buttonState: state ) + + let relationship = try await self.context.apiService.relationship(forAccounts: [account], authenticationBox: authContext.mastodonAuthenticationBox).value.first + + let isMe: Bool + if let me { + isMe = account.id == me.id + } else { + isMe = false + } + + await MainActor.run { + view.viewModel.relationship = relationship + view.updateButtonState(with: relationship, isMe: isMe) + } + } } - } diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/UserView+ViewModel.swift b/MastodonSDK/Sources/MastodonUI/View/Content/UserView+ViewModel.swift index c4c2edd9a..f35afb97b 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/UserView+ViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/UserView+ViewModel.swift @@ -28,6 +28,7 @@ extension UserView { @Published public var authorVerifiedLink: String? @Published public var user: MastodonUser? @Published public var account: Mastodon.Entity.Account? + @Published public var relationship: Mastodon.Entity.Relationship? } } diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/UserView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/UserView.swift index 242f6c44d..6ad31bc75 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/UserView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/UserView.swift @@ -16,7 +16,7 @@ import MastodonSDK public protocol UserViewDelegate: AnyObject { func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for user: MastodonUser) - func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for user: Mastodon.Entity.Account) + func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for user: Mastodon.Entity.Account, me: MastodonUser?) } public final class UserView: UIView { @@ -258,10 +258,33 @@ public extension UserView { if let user = viewModel.user { delegate?.userView(self, didTapButtonWith: currentButtonState, for: user) } else if let account = viewModel.account { - delegate?.userView(self, didTapButtonWith: currentButtonState, for: account) + delegate?.userView(self, didTapButtonWith: currentButtonState, for: account, me: nil) } } - + + func updateButtonState(with relationship: Mastodon.Entity.Relationship?, isMe: Bool) { + let buttonState: UserView.ButtonState + + if let relationship { + if isMe { + buttonState = .none + } else if relationship.following { + buttonState = .unfollow + } else if relationship.blocking || (relationship.domainBlocking ?? false) { + buttonState = .blocked + } else if relationship.requested ?? false { + buttonState = .pending + } else { + buttonState = .follow + } + } else { + buttonState = .none + } + + setButtonState(buttonState) + + } + func setButtonState(_ state: ButtonState) { currentButtonState = state prepareButtonStateLayout(for: state)