Skip to content
Snippets Groups Projects
Commit f13e0ba8 authored by Bruno Muniz's avatar Bruno Muniz :apple:
Browse files

Added contact list indexing

parent 71c7a8df
Branches
No related tags found
1 merge request!58Migrating lists to compositional layout
...@@ -11,9 +11,9 @@ public final class ContactListController: UIViewController { ...@@ -11,9 +11,9 @@ public final class ContactListController: UIViewController {
lazy private var screenView = ContactListView() lazy private var screenView = ContactListView()
private var dataSource: IndexedContactList!
private let viewModel = ContactListViewModel() private let viewModel = ContactListViewModel()
private var cancellables = Set<AnyCancellable>() private var cancellables = Set<AnyCancellable>()
private var dataSource: UICollectionViewDiffableDataSource<Int, Contact>!
public override func loadView() { public override func loadView() {
view = screenView view = screenView
...@@ -38,8 +38,9 @@ public final class ContactListController: UIViewController { ...@@ -38,8 +38,9 @@ public final class ContactListController: UIViewController {
screenView.collectionView.delegate = self screenView.collectionView.delegate = self
screenView.collectionView.register(AvatarCell.self) screenView.collectionView.register(AvatarCell.self)
screenView.collectionView.dataSource = dataSource screenView.collectionView.dataSource = dataSource
screenView.collectionView.tintColor = Asset.neutralDark.color
dataSource = UICollectionViewDiffableDataSource<Int, Contact>( dataSource = IndexedContactList(
collectionView: screenView.collectionView collectionView: screenView.collectionView
) { collectionView, indexPath, contact in ) { collectionView, indexPath, contact in
let cell: AvatarCell = collectionView.dequeueReusableCell(forIndexPath: indexPath) let cell: AvatarCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
...@@ -125,15 +126,25 @@ public final class ContactListController: UIViewController { ...@@ -125,15 +126,25 @@ public final class ContactListController: UIViewController {
viewModel.snapshotPublisher viewModel.snapshotPublisher
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [unowned self] in .sink { [unowned self] snapshot in
screenView.emptyView.isHidden = $0.numberOfItems > 0 screenView.emptyView.isHidden = snapshot.numberOfItems > 0
if $0.numberOfItems == 0 { if snapshot.numberOfItems == 0 {
screenView.bringSubviewToFront(screenView.emptyView) screenView.bringSubviewToFront(screenView.emptyView)
} }
let animatingDifferences = dataSource.snapshot().numberOfItems > 0 let animatingDifferences = dataSource.snapshot().numberOfItems > 0
dataSource.apply($0, animatingDifferences: animatingDifferences) dataSource.apply(snapshot, animatingDifferences: animatingDifferences) { [weak self] in
guard let self = self else { return }
self.dataSource.set(indexTitles: snapshot.itemIdentifiers.map { contact -> String in
let name = (contact.nickname ?? contact.username) ?? ""
return "\(name.first!)"
})
self.screenView.collectionView.reloadData()
}
}.store(in: &cancellables) }.store(in: &cancellables)
} }
...@@ -157,19 +168,3 @@ extension ContactListController: UICollectionViewDelegate { ...@@ -157,19 +168,3 @@ extension ContactListController: UICollectionViewDelegate {
} }
} }
} }
//final class ContactListTableController: UITableViewController {
// private var collation = UILocalizedIndexedCollation.current()
//
// override func sectionIndexTitles(for: UITableView) -> [String]? {
// collation.sectionIndexTitles
// }
//
// override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
// collation.sectionTitles[section]
// }
//
// override func tableView(_: UITableView, sectionForSectionIndexTitle: String, at index: Int) -> Int {
// collation.section(forSectionIndexTitle: index)
// }
import UIKit
import XXModels
public protocol IndexableItem {
var indexedOn: NSString { get }
}
class IndexedListCollator<Item: IndexableItem> {
private final class CollationWrapper: NSObject {
let value: Any
@objc let indexedOn: NSString
init(value: Any, indexedOn: NSString) {
self.value = value
self.indexedOn = indexedOn
}
func unwrappedValue<UnwrappedType>() -> UnwrappedType {
return value as! UnwrappedType
}
}
public init() {}
public func sectioned(items: [Item]) -> (sections: [[Item]], collation: UILocalizedIndexedCollation) {
let collation = UILocalizedIndexedCollation.current()
let selector = #selector(getter: CollationWrapper.indexedOn)
let wrappedItems = items.map { item in
CollationWrapper(value: item, indexedOn: item.indexedOn)
}
let sortedObjects = collation.sortedArray(from: wrappedItems, collationStringSelector: selector) as! [CollationWrapper]
var sections = collation.sectionIndexTitles.map { _ in [Item]() }
sortedObjects.forEach { item in
let sectionNumber = collation.section(for: item, collationStringSelector: selector)
sections[sectionNumber].append(item.unwrappedValue())
}
return (sections: sections.filter { !$0.isEmpty }, collation: collation)
}
}
extension Contact: IndexableItem {
public var indexedOn: NSString {
guard let nickname = nickname else {
return "\(username!.first!)" as NSString
}
return "\(nickname.first!)" as NSString
}
}
import UIKit
import XXModels
final class IndexedContactList: UICollectionViewDiffableDataSource<Int, Contact> {
private var indexTitles: [String] = []
func set(indexTitles: [String]) {
self.indexTitles = indexTitles
}
override func indexTitles(for collectionView: UICollectionView) -> [String]? {
indexTitles
}
override func collectionView(
_ collectionView: UICollectionView,
indexPathForIndexTitle title: String,
at index: Int
) -> IndexPath {
guard let index = indexTitles.firstIndex(where: { $0 == title }) else {
return IndexPath(item: 0, section: 0)
}
return IndexPath(item: index, section: 0)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment