You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

321 lines
9.6 KiB

//
// TablePresenterViewController.swift
// GME Remit
//
// Created by InKwon Devik Kim on 26/06/2019.
//Copyright © 2019 Gobal Money Express Co. Ltd. All rights reserved.
//
import UIKit
import IQKeyboardManagerSwift
struct TablePresenterConfiguration {
var presenterTitle: String
var closeButtonTitle: String
var notFoundTitle: String
var searchBarPlaceHolder: String
init(presenterTitle: String) {
self.presenterTitle = presenterTitle
closeButtonTitle = "penny_test_close_text".localized()
notFoundTitle = "no_result_found_text".localized()
searchBarPlaceHolder = "search_text".localized()
}
init(
presenterTitle: String,
closeButtonTitle: String,
notFoundTitle: String,
searchBarPlaceHolder: String
) {
self.presenterTitle = presenterTitle
self.closeButtonTitle = closeButtonTitle
self.notFoundTitle = notFoundTitle
self.searchBarPlaceHolder = searchBarPlaceHolder
}
}
protocol TablePresenterDelegate: class {
func tablePresenterView(
_ viewController: TablePresenterViewController
) -> TablePresenterConfiguration
func tablePresenterView(
_ viewController: TablePresenterViewController,
didSelectModel model: TablePresenterProtocol?
)
}
class TablePresenterViewController: UIViewController {
// MARK: Properties
var presenter: TablePresenterModuleInterface?
weak var delegate: TablePresenterDelegate?
var type: TablePresenterType = .default
private var dynamicHeight: CGFloat = 0
private var cellHeight: CGFloat = 60
private let impact = UISelectionFeedbackGenerator()
private var isFirst = true
private lazy var originPoint = CGPoint(x: 0, y: 0)
private lazy var isDismissAnimation = false
// MARK: Computed Properties
var model: [TablePresenterProtocol]? {
didSet {
if model?.count == 0 {
notFoundLabel.isHidden = false
notFoundLabel.alpha = 1.0
} else {
notFoundLabel.isHidden = true
notFoundLabel.alpha = 0.0
}
tableView.reloadData()
if isFirst {
switch type {
case .branches:
searchBarContainerView.isHidden = false
dynamicHeight = view.frame.height * 0.8
default :
searchBarContainerView.isHidden = (model?.count ?? 0) < 1 ? true : false
dynamicHeight = calculateHeight(count: model?.count ?? 0)
}
isFirst = false
}
}
}
// MARK: IBOutlets
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var searchBarContainerView: UIView!
@IBOutlet private weak var searchBar: UISearchBar!
@IBOutlet private weak var tableView: UITableView!
@IBOutlet private weak var closeButton: UIButton!
@IBOutlet private weak var mainView: UIView!
@IBOutlet private weak var notFoundLabel: UILabel!
@IBOutlet private weak var transparentView: UIView!
@IBOutlet private weak var heightConstraint: NSLayoutConstraint!
// MARK: VC's Life cycle
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
searchBar.keyboardType = .asciiCapable
setConfiguration()
mainView.bottomToOrigin(duration: 0.1) {[weak self] in
guard let `self` = self else { return }
if !self.searchBarContainerView.isHidden {
if self.searchBar.canBecomeFirstResponder {
self.searchBar.becomeFirstResponder()
}
}
}
IQKeyboardManager.shared.enable = false
heightConstraint.constant = (dynamicHeight == 0) ? view.frame.height * 0.8 : dynamicHeight
impact.selectionChanged()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
originPoint = mainView.frame.origin
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
IQKeyboardManager.shared.enable = true
view.endEditing(true)
}
// MARK: IBActions
@IBAction func touchCloseButton(_ sender: UIButton) {
presentingViewController?.view.endEditing(true)
mainView.originToBottom {
// self.delegate?.tablePresenterView(self, didSelectModel: nil)
self.dismiss(animated: true)
}
}
private func calculateHeight(count: Int) -> CGFloat {
let calculatedHeight = CGFloat(count) * cellHeight + (view.frame.height - 200)
return min(calculatedHeight, view.frame.height * 0.8)
}
}
// MARK: TablePresenterViewInterface
extension TablePresenterViewController: TablePresenterViewInterface {
func setModel(with model: [TablePresenterProtocol]?) {
self.model = model
}
func setError(with error: Error) {
// alert(message: error.localizedDescription)
notFoundLabel.text = error.localizedDescription
self.model?.removeAll()
}
}
// MARK: Other Functions
extension TablePresenterViewController {
private func setup() {
mainView.layer.cornerRadius = 5
searchBar.delegate = self
tableView.delegate = self
tableView.dataSource = self
let tapGestureRecognizer = UITapGestureRecognizer()
tapGestureRecognizer.addTarget(self, action: #selector(tapGesture(_:)))
tapGestureRecognizer.delegate = self
transparentView.addGestureRecognizer(tapGestureRecognizer)
presenter?.fetchModel(type: type)
transparentView.backgroundColor = .themeBackgroundGray
// let panGesture = UIPanGestureRecognizer(target: self,action: #selector(onDrag(_:)))
// panGesture.delegate = self
//
// tableView.bounces = false
// tableView.addGestureRecognizer(panGesture)
}
private func setConfiguration() {
let configuration = delegate?.tablePresenterView(self)
titleLabel.text = configuration?.presenterTitle
notFoundLabel.text = configuration?.notFoundTitle
searchBar.placeholder = configuration?.presenterTitle
// searchBar.isHidden = !(configuration?.isUseSearchBar ?? true)
}
@objc func onDrag(_ sender: UIPanGestureRecognizer) {
if tableView.contentOffset.y == 0 && sender.velocity(in: tableView).y > 0 {
isDismissAnimation = true
let percentThreshold: CGFloat = 0.5
let translation = sender.translation(in: mainView)
let newY = ensureRange(
value: mainView.frame.minY + translation.y,
minimum: 0,
maximum: mainView.frame.maxY
)
let progress = progressAlongAxis(newY, mainView.bounds.height)
mainView.frame.origin.y = newY
if sender.state == .ended {
let velocity = sender.velocity(in: mainView)
if velocity.y >= 200 || progress > percentThreshold {
self.touchCloseButton(UIButton())
} else {
UIView.animate(withDuration: 0.2, animations: {
self.mainView.frame.origin.y = self.originPoint.y
})
}
}
sender.setTranslation(.zero, in: mainView)
} else if isDismissAnimation {
isDismissAnimation = false
UIView.animate(withDuration: 0.2, animations: {
self.mainView.frame.origin.y = self.originPoint.y
})
}
}
func progressAlongAxis(_ pointOnAxis: CGFloat, _ axisLength: CGFloat) -> CGFloat {
let movementOnAxis = pointOnAxis / axisLength
let positiveMovementOnAxis = fmaxf(Float(movementOnAxis), 0.0)
let positiveMovementOnAxisPercent = fminf(positiveMovementOnAxis, 1.0)
return CGFloat(positiveMovementOnAxisPercent)
}
func ensureRange<T>(value: T, minimum: T, maximum: T) -> T where T : Comparable {
return min(max(value, minimum), maximum)
}
@objc private func tapGesture(_ sender: UITapGestureRecognizer) {
touchCloseButton(UIButton())
}
}
// MARK: - UITableViewDataSource
extension TablePresenterViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeight
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return model?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell") as? TableCell else {
return UITableViewCell()
}
cell.setModel(model?[indexPath.row])
return cell
}
}
// MARK: - UITableViewDelegate
extension TablePresenterViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
mainView.originToBottom {[weak self] in guard let `self` = self else { return }
self.delegate?.tablePresenterView(self, didSelectModel: self.model?[indexPath.row])
self.dismiss(animated: true)
}
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
view.endEditing(true)
}
}
// MARK: - UIGestureRecognizerDelegate
extension TablePresenterViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
guard let tapRecognizer = gestureRecognizer as? UITapGestureRecognizer else {
return true
}
return touch.view == tapRecognizer.view
}
func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
return true
}
}
extension TablePresenterViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
print("\(searchText)")
guard let filteredSearchText = searchText.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return }
presenter?.filterModel(word: filteredSearchText, type: type)
}
}