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.

235 lines
7.2 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. //
  2. // RecipientsViewController.swift
  3. // GME Remit
  4. //
  5. // Created by InKwon James Kim on 08/08/2019.
  6. //Copyright © 2019 Gobal Money Express Co. Ltd. All rights reserved.
  7. //
  8. import UIKit
  9. import RxSwift
  10. import RxCocoa
  11. import Localize_Swift
  12. class RecipientsViewController: UIViewController {
  13. struct StringConstant {
  14. static let swipeText = ""
  15. static let sendMoneyText = "Send Money"
  16. static let newRecipeintText = "New Recipient"
  17. static let navBarTitle = "Select Recipient"
  18. }
  19. // MARK: Properties
  20. var viewModel: RecipientsViewModel!
  21. private let disposeBag = DisposeBag()
  22. private lazy var editTrigger = PublishSubject<Recipient>()
  23. private lazy var deleteTrigger = PublishSubject<Recipient>()
  24. private let impact = UISelectionFeedbackGenerator()
  25. // MARK: Computed Properties
  26. // MARK: IBOutlets
  27. @IBOutlet private weak var tableView: UITableView!
  28. @IBOutlet private weak var viewAddRecipient: UIView!
  29. @IBOutlet private weak var newRecipeintLabel: UILabel!
  30. @IBOutlet private weak var noRecipientLabel: UILabel!
  31. @IBOutlet private var addRecipientTapGestureRecognizer: UITapGestureRecognizer!
  32. @IBOutlet private weak var searchBar: UISearchBar!
  33. // MARK: VC's Life cycle
  34. override func viewDidLoad() {
  35. super.viewDidLoad()
  36. setup()
  37. }
  38. override func viewWillAppear(_ animated: Bool) {
  39. super.viewWillAppear(animated)
  40. self.navigationItem.title = "recipient_listing_title_text".localized()
  41. setupNormalNavigation()
  42. setupNavigationShadow(isUse: false)
  43. configureLanguage()
  44. }
  45. override func viewWillDisappear(_ animated: Bool) {
  46. super.viewWillDisappear(animated)
  47. self.navigationItem.title = ""
  48. setupNavigationShadow(isUse: true)
  49. view.endEditing(true)
  50. }
  51. // MARK: IBActions
  52. override func setupTabItem() {
  53. let image = UIImage.init(named: "ic-sendmoney")
  54. self.tabBarItem = UITabBarItem(
  55. title: "send_money_title_text".localized(),
  56. image: image, selectedImage: nil
  57. )
  58. self.tabBarItem.titlePositionAdjustment = UIOffset(
  59. horizontal: 0,
  60. vertical: UI_USER_INTERFACE_IDIOM() == .pad ? 2 : -6
  61. )
  62. }
  63. }
  64. // MARK: Other Functions
  65. extension RecipientsViewController {
  66. func configureLanguage() {
  67. self.newRecipeintLabel.text = "new_recipient".localized()
  68. self.searchBar.placeholder = "search_text".localized()
  69. }
  70. private func setup() {
  71. // all setup should be done here
  72. viewAddRecipient.hero.id = "setupRecipient"
  73. let colorOption = [NSAttributedString.Key.foregroundColor : UIColor.themeWhite]
  74. let title = NSAttributedString(string: "pull to refresh", attributes: colorOption)
  75. let refreshControl = UIRefreshControl()
  76. refreshControl.attributedTitle = title
  77. refreshControl.backgroundColor = .themeBlue
  78. refreshControl.tintColor = .themeWhite
  79. refreshControl.layer.cornerRadius = 5
  80. tableView.refreshControl = refreshControl
  81. tableView.separatorColor = .themeBorderColor
  82. setBinding()
  83. NotificationCenter.default.addObserver(
  84. self,
  85. selector: #selector(setupTabItem),
  86. name: NSNotification.Name(LCLLanguageChangeNotification),
  87. object: nil
  88. )
  89. }
  90. private func setBinding() {
  91. let viewWillAppear = rx.sentMessage(#selector(UIViewController.viewWillAppear(_:)))
  92. .mapToVoid()
  93. .asDriverOnErrorJustComplete()
  94. let needEditTrigger = PublishSubject<Void>()
  95. let input = RecipientsViewModel.Input(
  96. fetchTrigger: viewWillAppear,
  97. refreshTrigger: tableView.refreshControl!.rx.controlEvent(.valueChanged).asDriver(),
  98. addTrigger: addRecipientTapGestureRecognizer.rx.event.mapToVoid().asDriverOnErrorJustComplete(),
  99. selectTrigger: tableView.rx.itemSelected.asDriver(),
  100. editTrigger: editTrigger.asDriverOnErrorJustComplete(),
  101. deleteTrigger: deleteTrigger.asDriverOnErrorJustComplete(),
  102. needEditTrigger: needEditTrigger.asDriverOnErrorJustComplete(),
  103. filterText: searchBar.rx.text.asDriverOnErrorJustComplete()
  104. )
  105. addRecipientTapGestureRecognizer.rx.event.mapToVoid().asDriverOnErrorJustComplete()
  106. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  107. self.impact.selectionChanged()
  108. })
  109. .disposed(by: disposeBag)
  110. let output = viewModel.transform(input: input)
  111. output
  112. .recipients
  113. .map { $0.count != 0 }
  114. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  115. self.noRecipientLabel.isHidden = $0
  116. })
  117. .disposed(by: disposeBag)
  118. output
  119. .recipients.drive(
  120. tableView.rx.items(cellIdentifier: "RecipientCell")
  121. ) { [weak self] (_, element: Recipient, cell: RecipientCell) in
  122. guard let `self` = self else { return }
  123. cell.setModel(with: element)
  124. cell.hero.modifiers = [.fade, .scale(0.7)]
  125. cell.delegate = self
  126. }
  127. .disposed(by: disposeBag)
  128. output
  129. .isError.drive(
  130. onNext: { [weak self] in guard let `self` = self else { return }
  131. self.alert(type: .error, message: $0.localizedDescription)
  132. }
  133. ).disposed(by: disposeBag)
  134. output
  135. .isProgress.drive(
  136. onNext: { [weak self] in guard let `self` = self else { return }
  137. $0 ? self.showProgressHud() : self.hideProgressHud()
  138. if !$0 && self.tableView.refreshControl!.isRefreshing {
  139. self.tableView.refreshControl?.endRefreshing()
  140. }
  141. }
  142. ).disposed(by: disposeBag)
  143. output
  144. .isNeedEdit
  145. .drive(
  146. onNext: {
  147. DispatchQueue.main.async { [weak self] in guard let `self` = self else { return }
  148. self.alertWithOkCancel(
  149. type: .normal,
  150. message: "recipient_profile_update_prompt_text".localized(),
  151. okTitle: "yes_text".localized(),
  152. cancelTitle: "no_text".localized(),
  153. okAction: { needEditTrigger.onNext(()) },
  154. cancelAction: nil
  155. )
  156. }
  157. })
  158. .disposed(by: disposeBag)
  159. output
  160. .isPartnerChanged.drive(
  161. onNext: {
  162. DispatchQueue.main.async { [weak self] in guard let `self` = self else { return }
  163. self.alertWithOkCancel(
  164. type: .normal,
  165. message: "recipient_bank_update_prompt_text".localized(),
  166. okTitle: "ok_text".localized(),
  167. cancelTitle: "cancel_text".localized(),
  168. okAction: { needEditTrigger.onNext(()) },
  169. cancelAction: nil
  170. )
  171. }
  172. })
  173. .disposed(by: disposeBag)
  174. tableView.rx.setDelegate(self).disposed(by: disposeBag)
  175. }
  176. }
  177. // MARK: - UITableViewDelegate
  178. extension RecipientsViewController: UITableViewDelegate {
  179. func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
  180. view.endEditing(true)
  181. }
  182. }
  183. // MARK: - RecipientCellDelegate
  184. extension RecipientsViewController: RecipientCellDelegate {
  185. func edit(didSelect model: Recipient?) {
  186. guard let model = model else { return }
  187. self.editTrigger.onNext(model)
  188. }
  189. func delete(didSelect model: Recipient?) {
  190. self.alertWithOkCancel(
  191. message: "delete_recipient_confirmation_text".localized(),
  192. title: "alert_text".localized(),
  193. okAction: {
  194. guard let model = model else { return }
  195. self.deleteTrigger.onNext(model)
  196. })
  197. }
  198. }