Skip to content
Snippets Groups Projects
ContactListTableController.swift 2.73 KiB
Newer Older
Bruno Muniz's avatar
Bruno Muniz committed
import UIKit
import Shared
import Models
import Combine
import XXModels
Bruno Muniz's avatar
Bruno Muniz committed

final class ContactListTableController: UITableViewController {
    private var collation = UILocalizedIndexedCollation.current()
    private var sections: [[Contact]] = [] {
        didSet { self.tableView.reloadData() }
    }

Bruno Muniz's avatar
Bruno Muniz committed
    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)
Bruno Muniz's avatar
Bruno Muniz committed
        tableView.backgroundColor = Asset.neutralWhite.color
        tableView.sectionIndexColor = Asset.neutralDark.color
Bruno Muniz's avatar
Bruno Muniz committed
        tableView.contentInset = UIEdgeInsets(top: -20, left: 0, bottom: 0, right: 0)

        viewModel.contacts
Bruno Muniz's avatar
Bruno Muniz committed
            .receive(on: DispatchQueue.main)
            .sink { [unowned self] in
                let results = IndexedListCollator().sectioned(items: $0)
                self.collation = results.collation
                self.sections = results.sections
Bruno Muniz's avatar
Bruno Muniz committed
            }.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)
Bruno Muniz's avatar
Bruno Muniz committed
        return cell
    }

    override func numberOfSections(in: UITableView) -> Int {
        sections.count
    }

    override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
        sections[section].count
    }
Bruno Muniz's avatar
Bruno Muniz committed

    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)
Bruno Muniz's avatar
Bruno Muniz committed
    }

    override func tableView(_: UITableView, heightForRowAt: IndexPath) -> CGFloat {
Bruno Muniz's avatar
Bruno Muniz committed
        64
    }
}