feat: make diffable data source works with category picker

This commit is contained in:
CMK 2021-03-06 14:46:04 +08:00
parent 8568debab0
commit 893dc2a668
8 changed files with 64 additions and 145 deletions

View File

@ -25,6 +25,22 @@ extension CategoryPickerSection {
cell.categoryView.titleLabel.font = .systemFont(ofSize: 28) cell.categoryView.titleLabel.font = .systemFont(ofSize: 28)
} }
cell.categoryView.titleLabel.text = item.title cell.categoryView.titleLabel.text = item.title
cell.observe(\.isSelected, options: [.initial, .new]) { cell, _ in
if cell.isSelected {
cell.categoryView.bgView.backgroundColor = Asset.Colors.lightBrandBlue.color
cell.categoryView.bgView.applyShadow(color: Asset.Colors.lightBrandBlue.color, alpha: 1, x: 0, y: 0, blur: 4.0)
if case .all = item {
cell.categoryView.titleLabel.textColor = Asset.Colors.lightWhite.color
}
} else {
cell.categoryView.bgView.backgroundColor = Asset.Colors.lightWhite.color
cell.categoryView.bgView.applyShadow(color: Asset.Colors.lightBrandBlue.color, alpha: 0, x: 0, y: 0, blur: 0.0)
if case .all = item {
cell.categoryView.titleLabel.textColor = Asset.Colors.lightBrandBlue.color
}
}
}
.store(in: &cell.observations)
return cell return cell
} }
} }

View File

@ -21,16 +21,18 @@ extension PickServerSection {
static func tableViewDiffableDataSource( static func tableViewDiffableDataSource(
for tableView: UITableView, for tableView: UITableView,
dependency: NeedsDependency, dependency: NeedsDependency,
pickServerCategoriesCellDelegate: PickServerCategoriesCellDelegate,
pickServerSearchCellDelegate: PickServerSearchCellDelegate, pickServerSearchCellDelegate: PickServerSearchCellDelegate,
pickServerCellDelegate: PickServerCellDelegate pickServerCellDelegate: PickServerCellDelegate
) -> UITableViewDiffableDataSource<PickServerSection, PickServerItem> { ) -> UITableViewDiffableDataSource<PickServerSection, PickServerItem> {
UITableViewDiffableDataSource(tableView: tableView) { [weak pickServerSearchCellDelegate, weak pickServerCellDelegate] tableView, indexPath, item -> UITableViewCell? in UITableViewDiffableDataSource(tableView: tableView) { [weak pickServerCategoriesCellDelegate, weak pickServerSearchCellDelegate, weak pickServerCellDelegate] tableView, indexPath, item -> UITableViewCell? in
switch item { switch item {
case .header: case .header:
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerTitleCell.self), for: indexPath) as! PickServerTitleCell let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerTitleCell.self), for: indexPath) as! PickServerTitleCell
return cell return cell
case .categoryPicker(let items): case .categoryPicker(let items):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerCategoriesCell.self), for: indexPath) as! PickServerCategoriesCell let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerCategoriesCell.self), for: indexPath) as! PickServerCategoriesCell
cell.delegate = pickServerCategoriesCellDelegate
cell.diffableDataSource = CategoryPickerSection.collectionViewDiffableDataSource( cell.diffableDataSource = CategoryPickerSection.collectionViewDiffableDataSource(
for: cell.collectionView, for: cell.collectionView,
dependency: dependency dependency: dependency
@ -48,19 +50,6 @@ extension PickServerSection {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerCell.self), for: indexPath) as! PickServerCell let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerCell.self), for: indexPath) as! PickServerCell
PickServerSection.configure(cell: cell, server: server, attribute: attribute) PickServerSection.configure(cell: cell, server: server, attribute: attribute)
cell.delegate = pickServerCellDelegate cell.delegate = pickServerCellDelegate
// cell.server = server
// if expandServerDomainSet.contains(server.domain) {
// cell.mode = .expand
// } else {
// cell.mode = .collapse
// }
// if server == viewModel.selectedServer.value {
// tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
// } else {
// tableView.deselectRow(at: indexPath, animated: false)
// }
//
// cell.delegate = self
return cell return cell
} }
} }

View File

@ -9,16 +9,17 @@ import UIKit
class PickServerCategoryCollectionViewCell: UICollectionViewCell { class PickServerCategoryCollectionViewCell: UICollectionViewCell {
var observations = Set<NSKeyValueObservation>()
var categoryView: PickServerCategoryView = { var categoryView: PickServerCategoryView = {
let view = PickServerCategoryView() let view = PickServerCategoryView()
view.translatesAutoresizingMaskIntoConstraints = false view.translatesAutoresizingMaskIntoConstraints = false
return view return view
}() }()
override var isSelected: Bool { override func prepareForReuse() {
didSet { super.prepareForReuse()
categoryView.selected = isSelected observations.removeAll()
}
} }
override init(frame: CGRect) { override init(frame: CGRect) {

View File

@ -122,6 +122,7 @@ extension MastodonPickServerViewController {
viewModel.setupDiffableDataSource( viewModel.setupDiffableDataSource(
for: tableView, for: tableView,
dependency: self, dependency: self,
pickServerCategoriesCellDelegate: self,
pickServerSearchCellDelegate: self, pickServerSearchCellDelegate: self,
pickServerCellDelegate: self pickServerCellDelegate: self
) )
@ -398,6 +399,28 @@ extension MastodonPickServerViewController: UITableViewDelegate {
viewModel.selectedServer.send(nil) viewModel.selectedServer.send(nil)
} }
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let diffableDataSource = viewModel.diffableDataSource else { return }
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
switch item {
case .categoryPicker:
guard let cell = cell as? PickServerCategoriesCell else { return }
guard let diffableDataSource = cell.diffableDataSource else { return }
let snapshot = diffableDataSource.snapshot()
let item = viewModel.selectCategoryItem.value
guard let section = snapshot.indexOfSection(.main),
let row = snapshot.indexOfItem(item) else { return }
cell.collectionView.selectItem(at: IndexPath(item: row, section: section), animated: false, scrollPosition: .centeredHorizontally)
case .search:
guard let cell = cell as? PickServerSearchCell else { return }
cell.searchTextField.text = viewModel.searchText.value
default:
break
}
}
} }
extension MastodonPickServerViewController { extension MastodonPickServerViewController {
@ -409,38 +432,15 @@ extension MastodonPickServerViewController {
emptyStateView.topPaddingViewTopLayoutConstraint.constant = rectInTableView.maxY emptyStateView.topPaddingViewTopLayoutConstraint.constant = rectInTableView.maxY
} }
} }
//extension MastodonPickServerViewController: UITableViewDataSource {
// func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // MARK: - PickServerCategoriesCellDelegate
// extension MastodonPickServerViewController: PickServerCategoriesCellDelegate {
// let section = Self.Section.allCases[indexPath.section] func pickServerCategoriesCell(_ cell: PickServerCategoriesCell, collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// switch section { guard let diffableDataSource = cell.diffableDataSource else { return }
// case .title: let item = diffableDataSource.itemIdentifier(for: indexPath)
// viewModel.selectCategoryItem.value = item ?? .all
// case .categories: }
// }
// case .search:
//
// case .serverList:
// let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerCell.self), for: indexPath) as! PickServerCell
// let server = viewModel.servers.value[indexPath.row]
// // cell.server = server
//// if expandServerDomainSet.contains(server.domain) {
//// cell.mode = .expand
//// } else {
//// cell.mode = .collapse
//// }
// if server == viewModel.selectedServer.value {
// tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
// } else {
// tableView.deselectRow(at: indexPath, animated: false)
// }
//
// cell.delegate = self
// return cell
// }
// }
//}
// MARK: - PickServerSearchCellDelegate // MARK: - PickServerSearchCellDelegate
extension MastodonPickServerViewController: PickServerSearchCellDelegate { extension MastodonPickServerViewController: PickServerSearchCellDelegate {
@ -465,41 +465,7 @@ extension MastodonPickServerViewController: PickServerCellDelegate {
// expand attribute change do not needs apply snapshot to diffable data source // expand attribute change do not needs apply snapshot to diffable data source
// but should I block the viewModel data binding during tableView.beginUpdates/endUpdates? // but should I block the viewModel data binding during tableView.beginUpdates/endUpdates?
} }
// func pickServerCell(modeChange server: Mastodon.Entity.Server, newMode: PickServerCell.Mode, updates: (() -> Void)) {
// if newMode == .collapse {
// expandServerDomainSet.remove(server.domain)
// } else {
// expandServerDomainSet.insert(server.domain)
// }
//
// tableView.beginUpdates()
// updates()
// tableView.endUpdates()
//
// if newMode == .expand, let modeChangeIndex = self.viewModel.servers.value.firstIndex(where: { $0 == server }), self.tableView.indexPathsForVisibleRows?.last?.row == modeChangeIndex {
// self.tableView.scrollToRow(at: IndexPath(row: modeChangeIndex, section: 3), at: .bottom, animated: true)
// }
// }
} }
//extension MastodonPickServerViewController: PickServerCategoriesDataSource, PickServerCategoriesCellDelegate {
// func numberOfCategories() -> Int {
// return viewModel.categories.count
// }
//
// func category(at index: Int) -> MastodonPickServerViewModel.Category {
// return viewModel.categories[index]
// }
//
// func selectedIndex() -> Int {
// return viewModel.selectCategoryIndex.value
// }
//
// func pickServerCategoriesCell(_ cell: PickServerCategoriesCell, didSelect index: Int) {
// return viewModel.selectCategoryIndex.send(index)
// }
//}
// MARK: - OnboardingViewControllerAppearance // MARK: - OnboardingViewControllerAppearance
extension MastodonPickServerViewController: OnboardingViewControllerAppearance { } extension MastodonPickServerViewController: OnboardingViewControllerAppearance { }

View File

@ -12,12 +12,14 @@ extension MastodonPickServerViewModel {
func setupDiffableDataSource( func setupDiffableDataSource(
for tableView: UITableView, for tableView: UITableView,
dependency: NeedsDependency, dependency: NeedsDependency,
pickServerCategoriesCellDelegate: PickServerCategoriesCellDelegate,
pickServerSearchCellDelegate: PickServerSearchCellDelegate, pickServerSearchCellDelegate: PickServerSearchCellDelegate,
pickServerCellDelegate: PickServerCellDelegate pickServerCellDelegate: PickServerCellDelegate
) { ) {
diffableDataSource = PickServerSection.tableViewDiffableDataSource( diffableDataSource = PickServerSection.tableViewDiffableDataSource(
for: tableView, for: tableView,
dependency: dependency, dependency: dependency,
pickServerCategoriesCellDelegate: pickServerCategoriesCellDelegate,
pickServerSearchCellDelegate: pickServerSearchCellDelegate, pickServerSearchCellDelegate: pickServerSearchCellDelegate,
pickServerCellDelegate: pickServerCellDelegate pickServerCellDelegate: pickServerCellDelegate
) )

View File

@ -89,9 +89,11 @@ extension PickServerCategoriesCell {
// MARK: - UICollectionViewDelegateFlowLayout // MARK: - UICollectionViewDelegateFlowLayout
extension PickServerCategoriesCell: UICollectionViewDelegateFlowLayout { extension PickServerCategoriesCell: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: indexPath: %s", ((#file as NSString).lastPathComponent), #line, #function, indexPath.debugDescription)
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally) collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally)
// delegate.pickServerCategoriesCell(self, didSelect: indexPath.row) delegate?.pickServerCategoriesCell(self, collectionView: collectionView, didSelectItemAt: indexPath)
} }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
@ -106,27 +108,5 @@ extension PickServerCategoriesCell: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 60, height: 80) return CGSize(width: 60, height: 80)
} }
} }
//extension PickServerCategoriesCell: UICollectionViewDataSource {
// func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// return dataSource.numberOfCategories()
// }
//
// func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// let category = dataSource.category(at: indexPath.row)
// let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: PickServerCategoryCollectionViewCell.self), for: indexPath) as! PickServerCategoryCollectionViewCell
// cell.category = category
//
// // Select the default category by default
// if indexPath.row == dataSource.selectedIndex() {
// // Use `[]` as the scrollPosition to avoid contentOffset change
// collectionView.selectItem(at: indexPath, animated: false, scrollPosition: [])
// cell.isSelected = true
// }
// return cell
// }
//
//
//}

View File

@ -38,7 +38,7 @@ class PickServerSearchCell: UITableViewCell {
return view return view
}() }()
private var searchTextField: UITextField = { let searchTextField: UITextField = {
let textField = UITextField() let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false textField.translatesAutoresizingMaskIntoConstraints = false
textField.font = .preferredFont(forTextStyle: .headline) textField.font = .preferredFont(forTextStyle: .headline)

View File

@ -9,16 +9,6 @@ import UIKit
import MastodonSDK import MastodonSDK
class PickServerCategoryView: UIView { class PickServerCategoryView: UIView {
// var category: MastodonPickServerViewModel.Category? {
// didSet {
// updateCategory()
// }
// }
var selected: Bool = false {
didSet {
// updateSelectStatus()
}
}
var bgShadowView: UIView = { var bgShadowView: UIView = {
let view = UIView() let view = UIView()
@ -53,6 +43,7 @@ class PickServerCategoryView: UIView {
} }
extension PickServerCategoryView { extension PickServerCategoryView {
private func configure() { private func configure() {
addSubview(bgView) addSubview(bgView)
addSubview(titleLabel) addSubview(titleLabel)
@ -69,33 +60,7 @@ extension PickServerCategoryView {
titleLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor), titleLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor),
]) ])
} }
// private func updateCategory() {
// guard let category = category else { return }
// titleLabel.text = category.title
// switch category {
// case .all:
// titleLabel.font = UIFont.systemFont(ofSize: 17)
// case .some:
// titleLabel.font = UIFont.systemFont(ofSize: 28)
// }
// }
//
// private func updateSelectStatus() {
// if selected {
// bgView.backgroundColor = Asset.Colors.lightBrandBlue.color
// bgView.applyShadow(color: Asset.Colors.lightBrandBlue.color, alpha: 1, x: 0, y: 0, blur: 4.0)
// if case .all = category {
// titleLabel.textColor = Asset.Colors.lightWhite.color
// }
// } else {
// bgView.backgroundColor = Asset.Colors.lightWhite.color
// bgView.applyShadow(color: Asset.Colors.lightBrandBlue.color, alpha: 0, x: 0, y: 0, blur: 0.0)
// if case .all = category {
// titleLabel.textColor = Asset.Colors.lightBrandBlue.color
// }
// }
// }
} }
#if DEBUG && canImport(SwiftUI) #if DEBUG && canImport(SwiftUI)