/* * SearchViewModel on iOS that renders states emitted by the state machine. * This code lives in the iOS project. */ class SearchViewController: UIViewController, UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource { private let reuseIdentifier = "SearchTableViewCell" private var viewModel: KSearchViewModel? = nil var filterViewController: FilterViewController? = nil var tableView: UITableView! var searchBar: UISearchBar! var searchResults: [SearchResult] = [] var searchActive: Bool = false override func viewDidLoad() { super.viewDidLoad() analytics.trackEvent(AE.VIEW_SEARCH) filterViewController = FilterViewController() self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: self.makeFilterButton()) tableView = UITableView() tableView.register(SearchTableViewCell.self, forCellReuseIdentifier: "searchTableViewCell") searchBar = UISearchBar() view.addSubview(tableView) tableView.frame = view.frame navigationItem.titleView = searchBar searchBar.translatesAutoresizingMaskIntoConstraints = false searchBar.leadingAnchor.constraint(equalTo: view.leadingAnchor) searchBar.topAnchor.constraint(equalTo: view.topAnchor) applyBlueTheme() searchBar.delegate = self tableView.dataSource = self tableView.delegate = self self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: makeBackButton()) viewModel = KSearchViewModel(exitDb: kotlinDb) viewModel!.cStateFlow.watch { state in self.render(state: state!) } filterViewController?.attachViewModel(viewModel: viewModel!) } func releaseReferences() { viewModel?.clear() filterViewController = nil viewModel = nil } func render(state: Search.State) { switch(state.type) { case .initialstate: print("initial state") case .filteroptionsloaded: filterViewController?.setCountryList(countryList: state.filterOptions.filterCountryList) case .closefilterstate: print("close filter state") filterViewController?.dismiss(animated: true, completion: nil) case .openfilterstate: print("open filter test") filterViewController?.attachViewModel(viewModel: viewModel!) guard let controller = filterViewController else { return } controller.modalPresentationStyle = .fullScreen self.present(controller, animated: true, completion: nil) case .showresultsstate: print("show results state") self.searchResults = state.items self.tableView.reloadData() case .closepagestate: print("close page state") default: print("should never get here") } } func makeFilterButton() -> UIButton { let backButtonImage = UIImage(named: "backbutton")?.withRenderingMode(.alwaysTemplate) let filterBtn = UIButton(type: .custom) filterBtn.setImage(backButtonImage, for: .normal) filterBtn.tintColor = UIColor(named: "MainText") filterBtn.setTitle("Filter", for: .normal) filterBtn.setTitleColor(UIColor(named: "MainText"), for: .normal) filterBtn.addTarget(self, action: #selector(dispatchOpenFilter), for: .touchUpInside) return filterBtn } @objc func dispatchOpenFilter() { self.viewModel!.dispatchAction(action: Search.ActionTapOpenFilterIcon()) } @objc func backButtonPressed() { dismiss(animated: true, completion: nil) releaseReferences() } override func viewDidAppear(_ animated: Bool) { self.tableView.reloadData() } func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1; } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return searchResults.count; } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "searchTableViewCell", for: indexPath) as! SearchTableViewCell let currExit = self.searchResults[indexPath.row] cell.descriptionLabel.attributedText = makeExitListText(exit: currExit) return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let controller = ExitViewController() let currExit = self.searchResults[indexPath.row] //controller.exit = allExits[currExit.name] as! Exit! controller.exitId = currExit._id let uiNavController = UINavigationController(rootViewController: controller) uiNavController.modalPresentationStyle = .fullScreen self.present(uiNavController, animated: true, completion: nil) } func populateResults(_ exitList: [SearchResult]) { searchResults = exitList self.tableView.reloadData() } func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { self.searchResults.removeAll() viewModel?.dispatchAction( action: Search.ActionQueryChangeAction( filterState: filterViewController!.generateFilterState(), query: searchText ) ) self.tableView.reloadData() } override var prefersStatusBarHidden: Bool { return true } }