mastodon-app-ufficiale-ipho.../Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel...

115 lines
5.2 KiB
Swift

//
// MastodonPickServerViewController+Diffable.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021/3/5.
//
import UIKit
import Combine
import MastodonSDK
extension MastodonPickServerViewModel {
func setupDiffableDataSource(
for tableView: UITableView,
dependency: NeedsDependency,
pickServerServerSectionTableHeaderViewDelegate: PickServerServerSectionTableHeaderViewDelegate
) {
// set section header
serverSectionHeaderView.diffableDataSource = CategoryPickerSection.collectionViewDiffableDataSource(
for: serverSectionHeaderView.collectionView,
dependency: dependency,
viewModel: self
)
var sectionHeaderSnapshot = NSDiffableDataSourceSnapshot<CategoryPickerSection, CategoryPickerItem>()
sectionHeaderSnapshot.appendSections([.main])
sectionHeaderSnapshot.appendItems(categoryPickerItems, toSection: .main)
serverSectionHeaderView.delegate = pickServerServerSectionTableHeaderViewDelegate
serverSectionHeaderView.diffableDataSource?.apply(sectionHeaderSnapshot, animatingDifferences: false) { [weak self] in
guard let self = self else { return }
guard let indexPath = self.serverSectionHeaderView.diffableDataSource?.indexPath(for: .category(category: .init(category: Mastodon.Entity.Category.Kind.general.rawValue, serversCount: 0))) else { return }
self.serverSectionHeaderView.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .right)
let firstIndex = IndexPath(item: 0, section: 0)
self.serverSectionHeaderView.collectionView.scrollToItem(at: firstIndex, at: .left, animated: false)
}
// set tableView
diffableDataSource = PickServerSection.tableViewDiffableDataSource(
for: tableView,
dependency: dependency
)
var snapshot = NSDiffableDataSourceSnapshot<PickServerSection, PickServerItem>()
snapshot.appendSections([.header, .servers])
diffableDataSource?.apply(snapshot, animatingDifferences: false, completion: nil)
loadIndexedServerStateMachine.enter(LoadIndexedServerState.Loading.self)
Publishers.CombineLatest(
filteredIndexedServers,
unindexedServers
)
.receive(on: DispatchQueue.main)
.sink(receiveValue: { [weak self] indexedServers, unindexedServers in
guard let self = self else { return }
guard let diffableDataSource = self.diffableDataSource else { return }
let oldSnapshot = diffableDataSource.snapshot()
var oldSnapshotServerItemAttributeDict: [String : PickServerItem.ServerItemAttribute] = [:]
for item in oldSnapshot.itemIdentifiers {
guard case let .server(server, attribute) = item else { continue }
oldSnapshotServerItemAttributeDict[server.domain] = attribute
}
var snapshot = NSDiffableDataSourceSnapshot<PickServerSection, PickServerItem>()
snapshot.appendSections([.header, .servers])
// TODO: handle filter
var serverItems: [PickServerItem] = []
for server in indexedServers {
let attribute = oldSnapshotServerItemAttributeDict[server.domain] ?? PickServerItem.ServerItemAttribute(isLast: false, isExpand: false)
attribute.isLast.value = false
let item = PickServerItem.server(server: server, attribute: attribute)
guard !serverItems.contains(item) else { continue }
serverItems.append(item)
}
if let unindexedServers = unindexedServers {
if !unindexedServers.isEmpty {
for server in unindexedServers {
let attribute = oldSnapshotServerItemAttributeDict[server.domain] ?? PickServerItem.ServerItemAttribute(isLast: false, isExpand: false)
attribute.isLast.value = false
let item = PickServerItem.server(server: server, attribute: attribute)
guard !serverItems.contains(item) else { continue }
serverItems.append(item)
}
} else {
if indexedServers.isEmpty && !self.isLoadingIndexedServers.value {
serverItems.append(.loader(attribute: PickServerItem.LoaderItemAttribute(isLast: false, isEmptyResult: true)))
}
}
} else {
serverItems.append(.loader(attribute: PickServerItem.LoaderItemAttribute(isLast: false, isEmptyResult: false)))
}
if case let .server(_, attribute) = serverItems.last {
attribute.isLast.value = true
}
if case let .loader(attribute) = serverItems.last {
attribute.isLast = true
}
snapshot.appendItems(serverItems, toSection: .servers)
diffableDataSource.defaultRowAnimation = .fade
diffableDataSource.apply(snapshot, animatingDifferences: true, completion: nil)
})
.store(in: &disposeBag)
}
}