123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- import Foundation
- import UIKit
- import DcCore
- protocol ChatListDelegate: class {
- func onChatSelected(chatId: Int)
- }
- class ChatListController: UITableViewController {
- let dcContext: DcContext
- let viewModel: ChatListViewModel
- let contactCellReuseIdentifier = "contactCellReuseIdentifier"
- weak var chatListDelegate: ChatListDelegate?
- /// MARK - search
- private lazy var searchController: UISearchController = {
- let searchController = UISearchController(searchResultsController: nil)
- searchController.searchResultsUpdater = viewModel
- searchController.obscuresBackgroundDuringPresentation = false
- searchController.searchBar.placeholder = String.localized("search")
- searchController.dimsBackgroundDuringPresentation = false
- searchController.hidesNavigationBarDuringPresentation = true
- searchController.searchBar.delegate = self
- return searchController
- }()
- private lazy var emptySearchStateLabel: EmptyStateLabel = {
- let label = EmptyStateLabel()
- label.isHidden = true
- return label
- }()
- init(dcContext: DcContext, chatListDelegate: ChatListDelegate) {
- self.dcContext = dcContext
- self.chatListDelegate = chatListDelegate
- self.viewModel = ChatListViewModel(dcContext: dcContext)
- super.init(style: .grouped)
- viewModel.onChatListUpdate = handleChatListUpdate
- }
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- override func viewWillAppear(_ animated: Bool) {
- preferredContentSize = UIScreen.main.bounds.size
- navigationItem.hidesSearchBarWhenScrolling = false
- }
- override func viewDidAppear(_ animated: Bool) {
- navigationItem.hidesSearchBarWhenScrolling = true
- let nc = NotificationCenter.default
- nc.addObserver(self,
- selector: #selector(keyboardWillShow(_:)),
- name: UIResponder.keyboardWillShowNotification,
- object: nil)
- nc.addObserver(self,
- selector: #selector(keyboardWillHide(_:)),
- name: UIResponder.keyboardWillHideNotification,
- object: nil)
- }
- override func viewDidLoad() {
- super.viewDidLoad()
- navigationItem.searchController = searchController
- configureTableView()
- setupSubviews()
- }
- override func viewDidDisappear(_ animated: Bool) {
- NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
- NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
- }
- @objc func keyboardWillShow(_ notification: Notification) {
- if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
- tableView.tableFooterView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: keyboardSize.height))
- }
- }
- @objc func keyboardWillHide(_ notification: Notification) {
- tableView.tableFooterView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: Double.leastNormalMagnitude))
- }
- // MARK: - setup
- private func setupSubviews() {
- emptySearchStateLabel.addCenteredTo(parentView: view)
- }
- // MARK: - configuration
- private func configureTableView() {
- tableView.register(ChatListCell.self, forCellReuseIdentifier: contactCellReuseIdentifier)
- tableView.rowHeight = 64
- tableView.tableHeaderView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: Double.leastNormalMagnitude))
- tableView.tableFooterView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: Double.leastNormalMagnitude))
- }
- override func numberOfSections(in tableView: UITableView) -> Int {
- return viewModel.numberOfSections
- }
- override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return viewModel.numberOfRowsIn(section: section)
- }
- override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- guard let cell = tableView.dequeueReusableCell(withIdentifier: contactCellReuseIdentifier, for: indexPath) as? ChatListCell else {
- fatalError("could not deque TableViewCell")
- }
- let cellData = viewModel.cellDataFor(section: indexPath.section, row: indexPath.row)
- cell.updateCell(cellViewModel: cellData)
- return cell
- }
- override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- if let chatId = viewModel.getChatId(section: indexPath.section, row: indexPath.row) {
- chatListDelegate?.onChatSelected(chatId: chatId)
- }
- let cellData = viewModel.cellDataFor(section: indexPath.section, row: indexPath.row)
- switch cellData.type {
- case .chat(let data):
- chatListDelegate?.onChatSelected(chatId: data.chatId)
- case .contact(let data):
- if let chatId = data.chatId {
- chatListDelegate?.onChatSelected(chatId: chatId)
- } else {
- let chatId = dcContext.createChatByContactId(contactId: data.contactId)
- chatListDelegate?.onChatSelected(chatId: chatId)
- }
- default:
- fatalError("Other types are not allowed in Share contact search")
- }
- }
- override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
- return viewModel.titleForHeaderIn(section: section)
- }
- func handleChatListUpdate() {
- tableView.reloadData()
- if let emptySearchText = viewModel.emptySearchText {
- let text = String.localizedStringWithFormat(
- String.localized("search_no_result_for_x"),
- emptySearchText
- )
- emptySearchStateLabel.text = text
- emptySearchStateLabel.isHidden = false
- } else {
- emptySearchStateLabel.text = nil
- emptySearchStateLabel.isHidden = true
- }
- }
- }
- // MARK: - uisearchbardelegate
- extension ChatListController: UISearchBarDelegate {
- func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
- viewModel.beginSearch()
- return true
- }
- func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
- // searchBar will be set to "" by system
- viewModel.endSearch()
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
- self.tableView.scrollToTop()
- }
- }
- func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
- tableView.scrollToTop()
- return true
- }
- }
|