Make button-state work (IOS-157)

Reason for button-state not working/updating feels like to be a weird combination of Combine, UIKit, Snapshots, CoreData and me being stupid and not getting a hang on it.
This commit is contained in:
Nathan Mattes 2023-05-22 16:14:06 +02:00
parent 25e4b732ed
commit 11bab5e337
6 changed files with 50 additions and 79 deletions

View File

@ -415,7 +415,6 @@
DBB45B5927B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5827B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift */; };
DBB45B5B27B3A109002DC5A7 /* MediaPreviewTransitionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5A27B3A109002DC5A7 /* MediaPreviewTransitionViewController.swift */; };
DBB45B6027B50A4F002DC5A7 /* RecommendAccountItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5F27B50A4F002DC5A7 /* RecommendAccountItem.swift */; };
DBB45B6227B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B6127B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift */; };
DBB525212611EBD6002F1F29 /* ProfilePagingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB525202611EBD6002F1F29 /* ProfilePagingViewController.swift */; };
DBB525302611EBF3002F1F29 /* ProfilePagingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB5252F2611EBF3002F1F29 /* ProfilePagingViewModel.swift */; };
DBB525362611ECEB002F1F29 /* UserTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB525352611ECEB002F1F29 /* UserTimelineViewController.swift */; };
@ -1132,7 +1131,6 @@
DBB45B5827B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewVideoViewModel.swift; sourceTree = "<group>"; };
DBB45B5A27B3A109002DC5A7 /* MediaPreviewTransitionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewTransitionViewController.swift; sourceTree = "<group>"; };
DBB45B5F27B50A4F002DC5A7 /* RecommendAccountItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendAccountItem.swift; sourceTree = "<group>"; };
DBB45B6127B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SuggestionAccountViewModel+Diffable.swift"; sourceTree = "<group>"; };
DBB525202611EBD6002F1F29 /* ProfilePagingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilePagingViewController.swift; sourceTree = "<group>"; };
DBB5252F2611EBF3002F1F29 /* ProfilePagingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilePagingViewModel.swift; sourceTree = "<group>"; };
DBB525352611ECEB002F1F29 /* UserTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserTimelineViewController.swift; sourceTree = "<group>"; };
@ -1673,7 +1671,6 @@
DBB45B5F27B50A4F002DC5A7 /* RecommendAccountItem.swift */,
2DAC9E37262FC2320062E1A6 /* SuggestionAccountViewController.swift */,
2DAC9E3D262FC2400062E1A6 /* SuggestionAccountViewModel.swift */,
DBB45B6127B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift */,
2DAC9E43262FC9DE0062E1A6 /* TableView-Components */,
);
path = SuggestionAccount;
@ -3602,7 +3599,6 @@
DBDFF1952805561700557A48 /* DiscoveryPostsViewModel+Diffable.swift in Sources */,
DB03A795272A981400EE37C5 /* ContentSplitViewController.swift in Sources */,
DBDFF19C28055BD600557A48 /* DiscoveryViewModel.swift in Sources */,
DBB45B6227B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift in Sources */,
DBB3BA2A26A81C020004F2D4 /* FLAnimatedImageView.swift in Sources */,
DB3E6FF32806D97400B035AE /* DiscoveryNewsViewModel+State.swift in Sources */,
DB6746ED278F45F0008A6B94 /* AutoGenerateProtocolRelayDelegate.swift in Sources */,

View File

@ -39,14 +39,13 @@ extension RecommendAccountSection {
context.managedObjectContext.performAndWait {
guard let user = record.object(in: context.managedObjectContext) else { return }
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())
SuggestionAccountTableViewCell.ViewModel(
user: user,
followedUsers: configuration.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds,
blockedUsers: configuration.authContext.mastodonAuthenticationBox.inMemoryCache.blockedUserIds,
followRequestedUsers: configuration.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs)
)
}
}
return cell
}

View File

@ -1,41 +0,0 @@
//
// SuggestionAccountViewModel+Diffable.swift
// Mastodon
//
// Created by MainasuK on 2022-2-10.
//
import UIKit
extension SuggestionAccountViewModel {
func setupDiffableDataSource(
tableView: UITableView,
suggestionAccountTableViewCellDelegate: SuggestionAccountTableViewCellDelegate
) {
tableViewDiffableDataSource = RecommendAccountSection.tableViewDiffableDataSource(
tableView: tableView,
context: context,
configuration: RecommendAccountSection.Configuration(
authContext: authContext,
suggestionAccountTableViewCellDelegate: suggestionAccountTableViewCellDelegate
)
)
userFetchedResultsController.$records
.removeDuplicates()
.receive(on: DispatchQueue.main)
.sink { [weak self] records in
guard let self = self else { return }
guard let tableViewDiffableDataSource = self.tableViewDiffableDataSource else { return }
var snapshot = NSDiffableDataSourceSnapshot<RecommendAccountSection, RecommendAccountItem>()
snapshot.appendSections([.main])
let items: [RecommendAccountItem] = records.map { RecommendAccountItem.account($0) }
snapshot.appendItems(items, toSection: .main)
tableViewDiffableDataSource.applySnapshotUsingReloadData(snapshot, completion: nil)
}
.store(in: &disposeBag)
}
}

View File

@ -85,7 +85,36 @@ final class SuggestionAccountViewModel: NSObject {
.store(in: &disposeBag)
}
func followAllSuggestedAccounts(_ dependency: NeedsDependency & AuthContextProvider ) {
func setupDiffableDataSource(
tableView: UITableView,
suggestionAccountTableViewCellDelegate: SuggestionAccountTableViewCellDelegate
) {
tableViewDiffableDataSource = RecommendAccountSection.tableViewDiffableDataSource(
tableView: tableView,
context: context,
configuration: RecommendAccountSection.Configuration(
authContext: authContext,
suggestionAccountTableViewCellDelegate: suggestionAccountTableViewCellDelegate
)
)
userFetchedResultsController.$records
.receive(on: DispatchQueue.main)
.sink { [weak self] records in
guard let self = self else { return }
guard let tableViewDiffableDataSource = self.tableViewDiffableDataSource else { return }
var snapshot = NSDiffableDataSourceSnapshot<RecommendAccountSection, RecommendAccountItem>()
snapshot.appendSections([.main])
let items: [RecommendAccountItem] = records.map { RecommendAccountItem.account($0) }
snapshot.appendItems(items, toSection: .main)
tableViewDiffableDataSource.applySnapshotUsingReloadData(snapshot)
}
.store(in: &disposeBag)
}
func followAllSuggestedAccounts(_ dependency: NeedsDependency & AuthContextProvider) {
let userRecords = userFetchedResultsController.records.compactMap {
$0.object(in: dependency.context.managedObjectContext)?.asRecord

View File

@ -8,11 +8,11 @@ extension SuggestionAccountTableViewCell {
final class ViewModel {
let user: MastodonUser
let followedUsers: AnyPublisher<[String], Never>
let blockedUsers: AnyPublisher<[String], Never>
let followRequestedUsers: AnyPublisher<[String], Never>
let followedUsers: [String]
let blockedUsers: [String]
let followRequestedUsers: [String]
init(user: MastodonUser, followedUsers: AnyPublisher<[String], Never>, blockedUsers: AnyPublisher<[String], Never>, followRequestedUsers: AnyPublisher<[String], Never>) {
init(user: MastodonUser, followedUsers: [String], blockedUsers: [String], followRequestedUsers: [String]) {
self.user = user
self.followedUsers = followedUsers
self.followRequestedUsers = followRequestedUsers

View File

@ -82,30 +82,18 @@ final class SuggestionAccountTableViewCell: UITableViewCell {
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)
}
if viewModel.blockedUsers.contains(viewModel.user.id) {
self.userView.setButtonState(.blocked)
} else if viewModel.followedUsers.contains(viewModel.user.id) {
self.userView.setButtonState(.unfollow)
} else if viewModel.followRequestedUsers.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: viewModel.user.note ?? "", emojis: viewModel.user.emojis.asDictionary)