mastodon-ios/Mastodon/Scene/Search/SearchDetail/SearchResult/SearchResultViewModel+Diffa...

92 lines
3.4 KiB
Swift

//
// SearchResultViewModel+Diffable.swift
// Mastodon
//
// Created by MainasuK on 2022-1-19.
//
import UIKit
import Combine
extension SearchResultViewModel {
func setupDiffableDataSource(
tableView: UITableView,
statusTableViewCellDelegate: StatusTableViewCellDelegate
) {
diffableDataSource = SearchResultSection.tableViewDiffableDataSource(
tableView: tableView,
context: context,
configuration: .init(
authContext: authContext,
statusViewTableViewCellDelegate: statusTableViewCellDelegate
)
)
var snapshot = NSDiffableDataSourceSnapshot<SearchResultSection, SearchResultItem>()
snapshot.appendSections([.main])
// snapshot.appendItems(items.value, toSection: .main) // with initial items
diffableDataSource.apply(snapshot, animatingDifferences: false)
Publishers.CombineLatest3(
statusFetchedResultsController.$records,
userFetchedResultsController.$records,
$hashtags
)
.map { statusRecrods, userRecords, hashtags in
var items: [SearchResultItem] = []
let userItems = userRecords.map { SearchResultItem.user($0) }
items.append(contentsOf: userItems)
let hashtagItems = hashtags.map { SearchResultItem.hashtag(tag: $0) }
items.append(contentsOf: hashtagItems)
let statusItems = statusRecrods.map { SearchResultItem.status($0) }
items.append(contentsOf: statusItems)
return items
}
.assign(to: &$items)
$items
.receive(on: DispatchQueue.main)
.sink { [weak self] items in
guard let self = self else { return }
guard let diffableDataSource = self.diffableDataSource else { return }
var snapshot = NSDiffableDataSourceSnapshot<SearchResultSection, SearchResultItem>()
snapshot.appendSections([.main])
snapshot.appendItems(items, toSection: .main)
if let currentState = self.stateMachine.currentState {
switch currentState {
case is State.Loading,
is State.Fail,
is State.Idle:
let attribute = SearchResultItem.BottomLoaderAttribute(isEmptyResult: false)
snapshot.appendItems([.bottomLoader(attribute: attribute)], toSection: .main)
case is State.Fail:
break
case is State.NoMore:
if snapshot.itemIdentifiers.isEmpty {
let attribute = SearchResultItem.BottomLoaderAttribute(isEmptyResult: true)
snapshot.appendItems([.bottomLoader(attribute: attribute)], toSection: .main)
}
default:
break
}
}
diffableDataSource.defaultRowAnimation = .fade
diffableDataSource.apply(snapshot) { [weak self] in
guard let self = self else { return }
self.didDataSourceUpdate.send()
}
}
.store(in: &disposeBag)
}
}