diff --git a/Mastodon/Diffiable/Section/RecommendAccountSection.swift b/Mastodon/Diffiable/Section/RecommendAccountSection.swift index 92def915..64019e58 100644 --- a/Mastodon/Diffiable/Section/RecommendAccountSection.swift +++ b/Mastodon/Diffiable/Section/RecommendAccountSection.swift @@ -40,7 +40,7 @@ extension RecommendAccountSection { guard let viewModel = viewModel else { return nil } let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SuggestionAccountTableViewCell.self)) as! SuggestionAccountTableViewCell let user = managedObjectContext.object(with: objectID) as! MastodonUser - let isSelected = viewModel.selectedAccounts.contains(objectID) + let isSelected = viewModel.selectedAccounts.value.contains(objectID) cell.delegate = delegate cell.config(with: user, isSelected: isSelected) return cell diff --git a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift index 017c1ee3..80cd73cc 100644 --- a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift +++ b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift @@ -110,8 +110,7 @@ extension SuggestionAccountViewController { super.viewWillLayoutSubviews() let avatarImageViewHeight: Double = 56 let avatarImageViewCount = Int(floor((Double(view.frame.width) - 20) / (avatarImageViewHeight + 15))) - viewModel.headerPlaceholderCount = avatarImageViewCount - viewModel.applySelectedCollectionViewDataSource(accounts: []) + viewModel.headerPlaceholderCount.value = avatarImageViewCount } func setupHeader(accounts: [NSManagedObjectID]) { @@ -179,7 +178,7 @@ extension SuggestionAccountViewController: UITableViewDelegate { extension SuggestionAccountViewController: SuggestionAccountTableViewCellDelegate { func accountButtonPressed(objectID: NSManagedObjectID, cell: SuggestionAccountTableViewCell) { - let selected = !viewModel.selectedAccounts.contains(objectID) + let selected = !viewModel.selectedAccounts.value.contains(objectID) cell.startAnimating() viewModel.followAction(objectID: objectID)? .sink(receiveCompletion: { [weak self] completion in @@ -189,13 +188,14 @@ extension SuggestionAccountViewController: SuggestionAccountTableViewCellDelegat case .failure(let error): os_log("%{public}s[%{public}ld], %{public}s: follow failed. %s", (#file as NSString).lastPathComponent, #line, #function, error.localizedDescription) case .finished: + var selectedAccounts = self.viewModel.selectedAccounts.value if selected { - self.viewModel.selectedAccounts.append(objectID) + selectedAccounts.append(objectID) } else { - self.viewModel.selectedAccounts.removeAll { $0 == objectID } + selectedAccounts.removeAll { $0 == objectID } } cell.button.isSelected = selected - self.viewModel.selectedAccountsDidChange.send() + self.viewModel.selectedAccounts.value = selectedAccounts } }, receiveValue: { _ in }) @@ -206,7 +206,7 @@ extension SuggestionAccountViewController: SuggestionAccountTableViewCellDelegat extension SuggestionAccountViewController { @objc func doneButtonDidClick(_ sender: UIButton) { dismiss(animated: true, completion: nil) - if viewModel.selectedAccounts.count > 0 { + if viewModel.selectedAccounts.value.count > 0 { viewModel.delegate?.homeTimelineNeedRefresh.send() } } diff --git a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel.swift b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel.swift index 3a89d143..d5ef6f6c 100644 --- a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel.swift +++ b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel.swift @@ -27,11 +27,13 @@ final class SuggestionAccountViewModel: NSObject { weak var delegate: SuggestionAccountViewModelDelegate? // output let accounts = CurrentValueSubject<[NSManagedObjectID], Never>([]) - var selectedAccounts = [NSManagedObjectID]() - let selectedAccountsDidChange = PassthroughSubject() - var headerPlaceholderCount: Int? + var selectedAccounts = CurrentValueSubject<[NSManagedObjectID], Never>([]) + + var headerPlaceholderCount = CurrentValueSubject(nil) var suggestionAccountsFallback = PassthroughSubject() + var viewWillAppear = PassthroughSubject() + var diffableDataSource: UITableViewDiffableDataSource? { didSet(value) { if !accounts.value.isEmpty { @@ -47,11 +49,22 @@ final class SuggestionAccountViewModel: NSObject { super.init() - self.accounts - .receive(on: DispatchQueue.main) - .sink { [weak self] accounts in + Publishers.CombineLatest(self.accounts,self.selectedAccounts) + .sink { [weak self] accounts,selectedAccounts in self?.applyTableViewDataSource(accounts: accounts) - self?.applySelectedCollectionViewDataSource(accounts: []) + self?.applySelectedCollectionViewDataSource(accounts: selectedAccounts) + } + .store(in: &disposeBag) + + Publishers.CombineLatest(self.selectedAccounts,self.headerPlaceholderCount) + .sink { [weak self] selectedAccount,count in + self?.applySelectedCollectionViewDataSource(accounts: selectedAccount) + } + .store(in: &disposeBag) + + viewWillAppear + .sink { [weak self] _ in + self?.checkAccountsFollowState() } .store(in: &disposeBag) @@ -59,14 +72,6 @@ final class SuggestionAccountViewModel: NSObject { self.accounts.value = accounts } - selectedAccountsDidChange - .sink { [weak self] _ in - guard let self = self else { return } - self.applyTableViewDataSource(accounts: self.accounts.value) - self.applySelectedCollectionViewDataSource(accounts: self.selectedAccounts) - } - .store(in: &disposeBag) - context.authenticationService.activeMastodonAuthentication .sink { [weak self] activeMastodonAuthentication in guard let self = self else { return } @@ -136,7 +141,7 @@ final class SuggestionAccountViewModel: NSObject { } func applySelectedCollectionViewDataSource(accounts: [NSManagedObjectID]) { - guard let count = headerPlaceholderCount else { return } + guard let count = headerPlaceholderCount.value else { return } guard let dataSource = collectionDiffableDataSource else { return } var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.main]) @@ -192,12 +197,26 @@ final class SuggestionAccountViewModel: NSObject { guard let currentMastodonUser = currentMastodonUser.value else { return } - let users = accounts.value.compactMap { context.managedObjectContext.object(with: $0) as? MastodonUser } + let users: [MastodonUser] = accounts.value.compactMap { + guard let user = context.managedObjectContext.object(with: $0) as? MastodonUser else { + return nil + } + let isBlock = user.blockingBy.flatMap { $0.contains(currentMastodonUser) } ?? false + let isDomainBlock = user.domainBlockingBy.flatMap { $0.contains(currentMastodonUser) } ?? false + if isBlock || isDomainBlock { + return nil + } else { + return user + } + } + accounts.value = users.map(\.objectID) + let followingUsers = users.filter { user -> Bool in let isFollowing = user.followingBy.flatMap { $0.contains(currentMastodonUser) } ?? false - return isFollowing + let isPending = user.followRequestedBy.flatMap { $0.contains(currentMastodonUser) } ?? false + return isFollowing || isPending }.map(\.objectID) - selectedAccounts = followingUsers - selectedAccountsDidChange.send() + + selectedAccounts.value = followingUsers } }