From a1315b90060b1d0bc507f3cbb712b02ed7fc5779 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Mon, 22 May 2023 13:30:05 +0200 Subject: [PATCH] Re-introduce viewModel for each cell and set button-state (IOS-157) We need this viewModel for the button--state of the follow-button. There's still a runtime-issue that resets the button-state to follow. --- Mastodon.xcodeproj/project.pbxproj | 4 ++ .../RecommendAccountSection.swift | 7 +++- ...estionAccountTableViewCell+ViewModel.swift | 22 +++++++++++ .../SuggestionAccountTableViewCell.swift | 37 +++++++++++++++---- 4 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 Mastodon/Scene/SuggestionAccount/TableView-Components/SuggestionAccountTableViewCell+ViewModel.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 3e480ec54..ed6afbc58 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -147,6 +147,7 @@ D8916DC029211BE500124085 /* ContentSizedTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8916DBF29211BE500124085 /* ContentSizedTableView.swift */; }; D8A6AB6C291C5136003AB663 /* MastodonLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A6AB6B291C5136003AB663 /* MastodonLoginViewController.swift */; }; D8BE30B32A179E26006B8270 /* SuggestionAccountTableViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8BE30B22A179E26006B8270 /* SuggestionAccountTableViewFooter.swift */; }; + D8BEBCB62A1B7FFD0004F475 /* SuggestionAccountTableViewCell+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8BEBCB52A1B7FFD0004F475 /* SuggestionAccountTableViewCell+ViewModel.swift */; }; D8E5C346296DAB84007E76A7 /* DataSourceFacade+Status+History.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E5C345296DAB84007E76A7 /* DataSourceFacade+Status+History.swift */; }; D8E5C349296DB8A3007E76A7 /* StatusEditHistoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E5C348296DB8A3007E76A7 /* StatusEditHistoryViewController.swift */; }; D8F0372C29D232730027DE2E /* HashtagIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F0372B29D232730027DE2E /* HashtagIntentHandler.swift */; }; @@ -796,6 +797,7 @@ D8A6FE6529325F5900666A47 /* ios-infoPlist.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "ios-infoPlist.json"; sourceTree = ""; }; D8A6FE6629325F5900666A47 /* Localizable.stringsdict */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; path = Localizable.stringsdict; sourceTree = ""; }; D8BE30B22A179E26006B8270 /* SuggestionAccountTableViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionAccountTableViewFooter.swift; sourceTree = ""; }; + D8BEBCB52A1B7FFD0004F475 /* SuggestionAccountTableViewCell+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SuggestionAccountTableViewCell+ViewModel.swift"; sourceTree = ""; }; D8E5C345296DAB84007E76A7 /* DataSourceFacade+Status+History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataSourceFacade+Status+History.swift"; sourceTree = ""; }; D8E5C348296DB8A3007E76A7 /* StatusEditHistoryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEditHistoryViewController.swift; sourceTree = ""; }; D8F0372B29D232730027DE2E /* HashtagIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagIntentHandler.swift; sourceTree = ""; }; @@ -1681,6 +1683,7 @@ isa = PBXGroup; children = ( 2DAC9E45262FC9FD0062E1A6 /* SuggestionAccountTableViewCell.swift */, + D8BEBCB52A1B7FFD0004F475 /* SuggestionAccountTableViewCell+ViewModel.swift */, D8BE30B22A179E26006B8270 /* SuggestionAccountTableViewFooter.swift */, ); path = "TableView-Components"; @@ -3853,6 +3856,7 @@ DB6B74FC272FF55800C70B6E /* UserSection.swift in Sources */, DB0FCB862796BDA1006C02E2 /* SearchSection.swift in Sources */, DB1D61CF26F1B33600DA8662 /* WelcomeViewModel.swift in Sources */, + D8BEBCB62A1B7FFD0004F475 /* SuggestionAccountTableViewCell+ViewModel.swift in Sources */, DBD376B2269302A4007FEC24 /* UITableViewCell.swift in Sources */, DB4F0966269ED52200D62E92 /* SearchResultViewModel.swift in Sources */, DB6180FA26391F2E0018D199 /* MediaPreviewViewModel.swift in Sources */, diff --git a/Mastodon/Scene/SuggestionAccount/RecommendAccountSection.swift b/Mastodon/Scene/SuggestionAccount/RecommendAccountSection.swift index 15d259d0e..70c2a5077 100644 --- a/Mastodon/Scene/SuggestionAccount/RecommendAccountSection.swift +++ b/Mastodon/Scene/SuggestionAccount/RecommendAccountSection.swift @@ -38,7 +38,12 @@ extension RecommendAccountSection { cell.delegate = configuration.suggestionAccountTableViewCellDelegate context.managedObjectContext.performAndWait { guard let user = record.object(in: context.managedObjectContext) else { return } - cell.configure(user: user) + cell.configure(viewModel: + SuggestionAccountTableViewCell.ViewModel(user: user, + followedUsers: configuration.authContext.mastodonAuthenticationBox.inMemoryCache.$followingUserIds.eraseToAnyPublisher(), + blockedUsers: configuration.authContext.mastodonAuthenticationBox.inMemoryCache.$blockedUserIds.eraseToAnyPublisher(), + followRequestedUsers: configuration.authContext.mastodonAuthenticationBox.inMemoryCache.$followRequestedUserIDs.eraseToAnyPublisher()) + ) } diff --git a/Mastodon/Scene/SuggestionAccount/TableView-Components/SuggestionAccountTableViewCell+ViewModel.swift b/Mastodon/Scene/SuggestionAccount/TableView-Components/SuggestionAccountTableViewCell+ViewModel.swift new file mode 100644 index 000000000..937cb2262 --- /dev/null +++ b/Mastodon/Scene/SuggestionAccount/TableView-Components/SuggestionAccountTableViewCell+ViewModel.swift @@ -0,0 +1,22 @@ +// Copyright © 2023 Mastodon gGmbH. All rights reserved. + +import Combine +import MastodonUI +import CoreDataStack + +extension SuggestionAccountTableViewCell { + final class ViewModel { + let user: MastodonUser + + let followedUsers: AnyPublisher<[String], Never> + let blockedUsers: AnyPublisher<[String], Never> + let followRequestedUsers: AnyPublisher<[String], Never> + + init(user: MastodonUser, followedUsers: AnyPublisher<[String], Never>, blockedUsers: AnyPublisher<[String], Never>, followRequestedUsers: AnyPublisher<[String], Never>) { + self.user = user + self.followedUsers = followedUsers + self.followRequestedUsers = followRequestedUsers + self.blockedUsers = blockedUsers + } + } +} diff --git a/Mastodon/Scene/SuggestionAccount/TableView-Components/SuggestionAccountTableViewCell.swift b/Mastodon/Scene/SuggestionAccount/TableView-Components/SuggestionAccountTableViewCell.swift index f05f87a10..9b88742ea 100644 --- a/Mastodon/Scene/SuggestionAccount/TableView-Components/SuggestionAccountTableViewCell.swift +++ b/Mastodon/Scene/SuggestionAccount/TableView-Components/SuggestionAccountTableViewCell.swift @@ -79,20 +79,43 @@ final class SuggestionAccountTableViewCell: UITableViewCell { disposeBag.removeAll() } - func configure(user: MastodonUser) { - userView.configure(user: user, delegate: delegate) - //TODO: Fix Button State - userView.setButtonState(.follow) + func configure(viewModel: SuggestionAccountTableViewCell.ViewModel) { + userView.configure(user: viewModel.user, delegate: delegate) + Publishers.CombineLatest3( + viewModel.followedUsers, + viewModel.followRequestedUsers, + viewModel.blockedUsers + ) + .receive(on: DispatchQueue.main) + .sink { [weak self] followed, requested, blocked in + + guard let self else { return } + + if blocked.contains(viewModel.user.id) { + self.userView.setButtonState(.blocked) + } else if followed.contains(viewModel.user.id) { + self.userView.setButtonState(.unfollow) + } else if requested.contains(viewModel.user.id) { + self.userView.setButtonState(.pending) + } else if viewModel.user.locked { + self.userView.setButtonState(.request) + } else { + self.userView.setButtonState(.follow) + } + } + .store(in: &disposeBag) + let metaContent: MetaContent = { do { - let mastodonContent = MastodonContent(content: user.note ?? "", emojis: [:]) + //TODO: Add emojis + let mastodonContent = MastodonContent(content: viewModel.user.note ?? "", emojis: [:]) return try MastodonMetaContent.convert(document: mastodonContent) } catch { assertionFailure() - return PlaintextMetaContent(string: user.note ?? "") + return PlaintextMetaContent(string: viewModel.user.note ?? "") } - } () + }() bioMetaLabel.configure(content: metaContent) }