blob: 8c173de788120f7ba35da961f9ae3a626ea9363a [file] [log] [blame]
/*
* Copyright (C) 2020 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
* Author: Raphaël Brulé <raphael.brule@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import UIKit
import RxSwift
import RxDataSources
import RxCocoa
import Reusable
class JamiSearchView: NSObject {
@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var searchingLabel: UILabel!
@IBOutlet weak var searchResultsTableView: UITableView!
private var viewModel: JamiSearchViewModel!
private let disposeBag = DisposeBag()
var editSearch = PublishSubject<Bool>()
var isIncognito = false
let incognitoCellHeight: CGFloat = 150
let incognitoHeaderHeight: CGFloat = 0
var showSearchResult: Bool = true
func configure(with injectionBag: InjectionBag, source: FilterConversationDataSource, isIncognito: Bool, delegate: FilterConversationDelegate?) {
self.viewModel = JamiSearchViewModel(with: injectionBag, source: source, searchOnlyExistingConversations: true)
self.viewModel.setDelegate(delegate: delegate)
self.isIncognito = isIncognito
self.setUpView()
}
private func setUpView() {
configureSearchResult()
configureSearchBar()
}
private func cancelSearch() {
self.searchBar.text = ""
self.searchBar.resignFirstResponder()
self.searchResultsTableView.isHidden = true
}
private func configureSearchResult() {
if self.isIncognito {
self.searchResultsTableView.register(cellType: IncognitoSmartListCell.self)
self.searchResultsTableView.rowHeight = self.incognitoCellHeight
} else {
self.searchResultsTableView.register(cellType: SmartListCell.self)
self.searchResultsTableView.rowHeight = SmartlistConstants.smartlistRowHeight
}
self.searchResultsTableView.backgroundColor = UIColor.jamiBackgroundColor
self.searchResultsTableView.rx.setDelegate(self).disposed(by: disposeBag)
let configureCell: (TableViewSectionedDataSource, UITableView, IndexPath, ConversationSection.Item) -> UITableViewCell = {
(_: TableViewSectionedDataSource<ConversationSection>,
tableView: UITableView,
indexPath: IndexPath,
conversationItem: ConversationSection.Item) in
let cellType = self.isIncognito ? IncognitoSmartListCell.self : SmartListCell.self
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: cellType)
cell.configureFromItem(conversationItem)
return cell
}
let searchResultsDatasource = RxTableViewSectionedReloadDataSource<ConversationSection>(configureCell: configureCell)
self.viewModel
.searchResults
.bind(to: self.searchResultsTableView.rx.items(dataSource: searchResultsDatasource))
.disposed(by: disposeBag)
self.viewModel
.searchResults
.map({ (conversations) -> Bool in return conversations.isEmpty })
.subscribe(onNext: { [weak self] (hideFooterView) in
self?.searchResultsTableView.tableFooterView?.isHidden = hideFooterView })
.disposed(by: disposeBag)
self.searchResultsTableView.rx.itemSelected
.subscribe(onNext: { [weak self] indexPath in
self?.searchResultsTableView.deselectRow(at: indexPath, animated: true) })
.disposed(by: disposeBag)
searchResultsDatasource.titleForHeaderInSection = { dataSource, index in
return dataSource.sectionModels[index].header
}
// search status label
self.viewModel.searchStatus
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] status in
guard let self = self else { return }
self.searchingLabel.text = status.toString()
self.searchingLabel.isHidden = status.toString().isEmpty
})
.disposed(by: disposeBag)
searchingLabel.textColor = UIColor.jamiLabelColor
self.viewModel.isSearching
.subscribe(onNext: { [weak self] (isSearching) in
guard let self = self else { return }
self.searchResultsTableView.isHidden = !isSearching
let resultvisible = isSearching && self.showSearchResult
self.searchingLabel.isHidden = !resultvisible
})
.disposed(by: disposeBag)
}
private func configureSearchBar() {
self.searchBar.rx.text.orEmpty
.debounce(Durations.textFieldThrottlingDuration.toTimeInterval(), scheduler: MainScheduler.instance)
.bind(to: self.viewModel.searchBarText)
.disposed(by: disposeBag)
searchBar.placeholder = L10n.Smartlist.searchBar
}
}
// MARK: UITableViewDelegate
extension JamiSearchView: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return isIncognito ? incognitoHeaderHeight : SmartlistConstants.tableHeaderViewHeight
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let convToShow: ConversationViewModel = try? tableView.rx.model(at: indexPath) {
self.viewModel.showConversation(conversation: convToShow)
}
}
}