fix: refresh block state when view will appear

This commit is contained in:
sunxiaojian 2021-04-23 10:25:08 +08:00
parent 67f813a946
commit 61a26fbe66
3 changed files with 47 additions and 28 deletions

View File

@ -40,7 +40,7 @@ extension RecommendAccountSection {
guard let viewModel = viewModel else { return nil } guard let viewModel = viewModel else { return nil }
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SuggestionAccountTableViewCell.self)) as! SuggestionAccountTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SuggestionAccountTableViewCell.self)) as! SuggestionAccountTableViewCell
let user = managedObjectContext.object(with: objectID) as! MastodonUser 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.delegate = delegate
cell.config(with: user, isSelected: isSelected) cell.config(with: user, isSelected: isSelected)
return cell return cell

View File

@ -110,8 +110,7 @@ extension SuggestionAccountViewController {
super.viewWillLayoutSubviews() super.viewWillLayoutSubviews()
let avatarImageViewHeight: Double = 56 let avatarImageViewHeight: Double = 56
let avatarImageViewCount = Int(floor((Double(view.frame.width) - 20) / (avatarImageViewHeight + 15))) let avatarImageViewCount = Int(floor((Double(view.frame.width) - 20) / (avatarImageViewHeight + 15)))
viewModel.headerPlaceholderCount = avatarImageViewCount viewModel.headerPlaceholderCount.value = avatarImageViewCount
viewModel.applySelectedCollectionViewDataSource(accounts: [])
} }
func setupHeader(accounts: [NSManagedObjectID]) { func setupHeader(accounts: [NSManagedObjectID]) {
@ -179,7 +178,7 @@ extension SuggestionAccountViewController: UITableViewDelegate {
extension SuggestionAccountViewController: SuggestionAccountTableViewCellDelegate { extension SuggestionAccountViewController: SuggestionAccountTableViewCellDelegate {
func accountButtonPressed(objectID: NSManagedObjectID, cell: SuggestionAccountTableViewCell) { func accountButtonPressed(objectID: NSManagedObjectID, cell: SuggestionAccountTableViewCell) {
let selected = !viewModel.selectedAccounts.contains(objectID) let selected = !viewModel.selectedAccounts.value.contains(objectID)
cell.startAnimating() cell.startAnimating()
viewModel.followAction(objectID: objectID)? viewModel.followAction(objectID: objectID)?
.sink(receiveCompletion: { [weak self] completion in .sink(receiveCompletion: { [weak self] completion in
@ -189,13 +188,14 @@ extension SuggestionAccountViewController: SuggestionAccountTableViewCellDelegat
case .failure(let error): case .failure(let error):
os_log("%{public}s[%{public}ld], %{public}s: follow failed. %s", (#file as NSString).lastPathComponent, #line, #function, error.localizedDescription) os_log("%{public}s[%{public}ld], %{public}s: follow failed. %s", (#file as NSString).lastPathComponent, #line, #function, error.localizedDescription)
case .finished: case .finished:
var selectedAccounts = self.viewModel.selectedAccounts.value
if selected { if selected {
self.viewModel.selectedAccounts.append(objectID) selectedAccounts.append(objectID)
} else { } else {
self.viewModel.selectedAccounts.removeAll { $0 == objectID } selectedAccounts.removeAll { $0 == objectID }
} }
cell.button.isSelected = selected cell.button.isSelected = selected
self.viewModel.selectedAccountsDidChange.send() self.viewModel.selectedAccounts.value = selectedAccounts
} }
}, receiveValue: { _ in }, receiveValue: { _ in
}) })
@ -206,7 +206,7 @@ extension SuggestionAccountViewController: SuggestionAccountTableViewCellDelegat
extension SuggestionAccountViewController { extension SuggestionAccountViewController {
@objc func doneButtonDidClick(_ sender: UIButton) { @objc func doneButtonDidClick(_ sender: UIButton) {
dismiss(animated: true, completion: nil) dismiss(animated: true, completion: nil)
if viewModel.selectedAccounts.count > 0 { if viewModel.selectedAccounts.value.count > 0 {
viewModel.delegate?.homeTimelineNeedRefresh.send() viewModel.delegate?.homeTimelineNeedRefresh.send()
} }
} }

View File

@ -27,11 +27,13 @@ final class SuggestionAccountViewModel: NSObject {
weak var delegate: SuggestionAccountViewModelDelegate? weak var delegate: SuggestionAccountViewModelDelegate?
// output // output
let accounts = CurrentValueSubject<[NSManagedObjectID], Never>([]) let accounts = CurrentValueSubject<[NSManagedObjectID], Never>([])
var selectedAccounts = [NSManagedObjectID]() var selectedAccounts = CurrentValueSubject<[NSManagedObjectID], Never>([])
let selectedAccountsDidChange = PassthroughSubject<Void, Never>()
var headerPlaceholderCount: Int? var headerPlaceholderCount = CurrentValueSubject<Int?, Never>(nil)
var suggestionAccountsFallback = PassthroughSubject<Void, Never>() var suggestionAccountsFallback = PassthroughSubject<Void, Never>()
var viewWillAppear = PassthroughSubject<Void, Never>()
var diffableDataSource: UITableViewDiffableDataSource<RecommendAccountSection, NSManagedObjectID>? { var diffableDataSource: UITableViewDiffableDataSource<RecommendAccountSection, NSManagedObjectID>? {
didSet(value) { didSet(value) {
if !accounts.value.isEmpty { if !accounts.value.isEmpty {
@ -47,11 +49,22 @@ final class SuggestionAccountViewModel: NSObject {
super.init() super.init()
self.accounts Publishers.CombineLatest(self.accounts,self.selectedAccounts)
.receive(on: DispatchQueue.main) .sink { [weak self] accounts,selectedAccounts in
.sink { [weak self] accounts in
self?.applyTableViewDataSource(accounts: accounts) 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) .store(in: &disposeBag)
@ -59,14 +72,6 @@ final class SuggestionAccountViewModel: NSObject {
self.accounts.value = accounts 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 context.authenticationService.activeMastodonAuthentication
.sink { [weak self] activeMastodonAuthentication in .sink { [weak self] activeMastodonAuthentication in
guard let self = self else { return } guard let self = self else { return }
@ -136,7 +141,7 @@ final class SuggestionAccountViewModel: NSObject {
} }
func applySelectedCollectionViewDataSource(accounts: [NSManagedObjectID]) { func applySelectedCollectionViewDataSource(accounts: [NSManagedObjectID]) {
guard let count = headerPlaceholderCount else { return } guard let count = headerPlaceholderCount.value else { return }
guard let dataSource = collectionDiffableDataSource else { return } guard let dataSource = collectionDiffableDataSource else { return }
var snapshot = NSDiffableDataSourceSnapshot<SelectedAccountSection, SelectedAccountItem>() var snapshot = NSDiffableDataSourceSnapshot<SelectedAccountSection, SelectedAccountItem>()
snapshot.appendSections([.main]) snapshot.appendSections([.main])
@ -192,12 +197,26 @@ final class SuggestionAccountViewModel: NSObject {
guard let currentMastodonUser = currentMastodonUser.value else { guard let currentMastodonUser = currentMastodonUser.value else {
return 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 followingUsers = users.filter { user -> Bool in
let isFollowing = user.followingBy.flatMap { $0.contains(currentMastodonUser) } ?? false 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) }.map(\.objectID)
selectedAccounts = followingUsers
selectedAccountsDidChange.send() selectedAccounts.value = followingUsers
} }
} }