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.
329 lines
10 KiB
329 lines
10 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
|
|
titleLabel.font = .sanfrancisco(.bold, size: 16)
|
|
titleLabel.textColor = .themeBlack
|
|
notFoundLabel.text = configuration?.notFoundTitle
|
|
notFoundLabel.font = .sanfrancisco(.bold, size: 16)
|
|
notFoundLabel.textColor = .themeBlack
|
|
searchBar.placeholder = configuration?.presenterTitle
|
|
// searchBar.attributedPlaceholder = NSAttributedString(
|
|
// string: configuration?.presenterTitle,
|
|
// attributes: [NSAttributedStringKey.foregroundColor: .themeGray1, .font: .sanfrancisco(.medium, size: 14)]
|
|
// )
|
|
searchBar.searchTextField.font = .sanfrancisco(.medium, size: 16)
|
|
// 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)
|
|
}
|
|
}
|