import UIKit import Shared import Models import Combine import XXModels final class ContactListTableController: UITableViewController { private var collation = UILocalizedIndexedCollation.current() private var sections: [[Contact]] = [] { didSet { self.tableView.reloadData() } } private let viewModel: ContactListViewModel private var cancellables = Set<AnyCancellable>() private let tapRelay = PassthroughSubject<Contact, Never>() var didTap: AnyPublisher<Contact, Never> { tapRelay.eraseToAnyPublisher() } override func viewDidLoad() { super.viewDidLoad() setupTableView() } init(_ viewModel: ContactListViewModel) { self.viewModel = viewModel super.init(style: .grouped) } required init?(coder: NSCoder) { nil } private func setupTableView() { tableView.separatorStyle = .none tableView.register(AvatarCell.self) tableView.backgroundColor = Asset.neutralWhite.color tableView.sectionIndexColor = Asset.neutralDark.color tableView.contentInset = UIEdgeInsets(top: -20, left: 0, bottom: 0, right: 0) viewModel.contacts .receive(on: DispatchQueue.main) .sink { [unowned self] in let results = IndexedListCollator().sectioned(items: $0) self.collation = results.collation self.sections = results.sections }.store(in: &cancellables) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: AvatarCell = tableView.dequeueReusableCell(forIndexPath: indexPath) let contact = sections[indexPath.section][indexPath.row] let name = (contact.nickname ?? contact.username) ?? "Fetching username..." cell.setup(title: name, image: contact.photo) return cell } override func numberOfSections(in: UITableView) -> Int { sections.count } override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int { sections[section].count } override func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) { tapRelay.send(sections[indexPath.section][indexPath.row]) } 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) } override func tableView(_: UITableView, heightForRowAt: IndexPath) -> CGFloat { 64 } }