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.

246 lines
7.6 KiB

5 years ago
5 years ago
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<IndexPath>()
  23. private lazy var deleteTrigger = PublishSubject<IndexPath>()
  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 labelSwipeInfo: UILabel!
  30. @IBOutlet private weak var newRecipeintLabel: UILabel!
  31. @IBOutlet private weak var noRecipientLabel: UILabel!
  32. @IBOutlet private var addRecipientTapGestureRecognizer: UITapGestureRecognizer!
  33. @IBOutlet private weak var searchBar: UISearchBar!
  34. // MARK: VC's Life cycle
  35. override func viewDidLoad() {
  36. super.viewDidLoad()
  37. setup()
  38. }
  39. override func viewWillAppear(_ animated: Bool) {
  40. super.viewWillAppear(animated)
  41. self.navigationItem.title = "recipient_listing_title_text".localized()
  42. setupNormalNavigation()
  43. setupNavigationShadow(isUse: false)
  44. configureLanguage()
  45. }
  46. override func viewWillDisappear(_ animated: Bool) {
  47. super.viewWillDisappear(animated)
  48. self.navigationItem.title = ""
  49. setupNavigationShadow(isUse: true)
  50. view.endEditing(true)
  51. }
  52. // MARK: IBActions
  53. override func setupTabItem() {
  54. let image = UIImage.init(named: "ic-sendmoney")
  55. self.tabBarItem = UITabBarItem(
  56. title: "send_money_title_text".localized(),
  57. image: image, selectedImage: nil
  58. )
  59. self.tabBarItem.titlePositionAdjustment = UIOffset(
  60. horizontal: 0,
  61. vertical: UI_USER_INTERFACE_IDIOM() == .pad ? 2 : -6
  62. )
  63. }
  64. }
  65. // MARK: Other Functions
  66. extension RecipientsViewController {
  67. func configureLanguage() {
  68. self.labelSwipeInfo.text = "edit_delete_hint_ios_text".localized()
  69. self.newRecipeintLabel.text = "new_recipient".localized()
  70. self.searchBar.placeholder = "search_text".localized()
  71. }
  72. private func setup() {
  73. // all setup should be done here
  74. viewAddRecipient.hero.id = "setupRecipient"
  75. let colorOption = [NSAttributedString.Key.foregroundColor : UIColor.themeWhite]
  76. let title = NSAttributedString(string: "pull to refresh", attributes: colorOption)
  77. let refreshControl = UIRefreshControl()
  78. refreshControl.attributedTitle = title
  79. refreshControl.backgroundColor = .themeBlue
  80. refreshControl.tintColor = .themeWhite
  81. refreshControl.layer.cornerRadius = 5
  82. tableView.refreshControl = refreshControl
  83. tableView.separatorColor = .themeBorderColor
  84. setBinding()
  85. NotificationCenter.default.addObserver(
  86. self,
  87. selector: #selector(setupTabItem),
  88. name: NSNotification.Name(LCLLanguageChangeNotification),
  89. object: nil
  90. )
  91. }
  92. private func setBinding() {
  93. let viewWillAppear = rx.sentMessage(#selector(UIViewController.viewWillAppear(_:)))
  94. .mapToVoid()
  95. .asDriverOnErrorJustComplete()
  96. let needEditTrigger = PublishSubject<Void>()
  97. let input = RecipientsViewModel.Input(
  98. fetchTrigger: viewWillAppear,
  99. refreshTrigger: tableView.refreshControl!.rx.controlEvent(.valueChanged).asDriver(),
  100. addTrigger: addRecipientTapGestureRecognizer.rx.event.mapToVoid().asDriverOnErrorJustComplete(),
  101. selectTrigger: tableView.rx.itemSelected.asDriver(),
  102. editTrigger: editTrigger.asDriverOnErrorJustComplete(),
  103. deleteTrigger: deleteTrigger.asDriverOnErrorJustComplete(),
  104. needEditTrigger: needEditTrigger.asDriverOnErrorJustComplete(),
  105. filterText: searchBar.rx.text.asDriverOnErrorJustComplete()
  106. )
  107. addRecipientTapGestureRecognizer.rx.event.mapToVoid().asDriverOnErrorJustComplete()
  108. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  109. self.impact.selectionChanged()
  110. })
  111. .disposed(by: disposeBag)
  112. let output = viewModel.transform(input: input)
  113. output
  114. .recipients
  115. .map { $0.count != 0 }
  116. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  117. self.noRecipientLabel.isHidden = $0
  118. })
  119. .disposed(by: disposeBag)
  120. output
  121. .recipients.drive(
  122. tableView.rx.items(cellIdentifier: "RecipientCell")
  123. ) { (_, element: Recipient, cell: RecipientCell) in
  124. cell.setModel(with: element)
  125. cell.hero.modifiers = [.fade, .scale(0.7)]
  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 tableView(
  180. _ tableView: UITableView,
  181. editActionsForRowAt indexPath: IndexPath
  182. ) -> [UITableViewRowAction]? {
  183. let delete = UITableViewRowAction(
  184. style: .destructive,
  185. title: "delete_text".localized()
  186. ) { [weak self] (_, indexPath) in
  187. guard let `self` = self else { return }
  188. self.alertWithOkCancel(
  189. message: "delete_recipient_confirmation_text".localized(),
  190. title: "alert_text".localized(),
  191. okAction: {
  192. self.deleteTrigger.onNext(indexPath)
  193. })
  194. }
  195. let edit = UITableViewRowAction(
  196. style: .normal,
  197. title: "edit_text".localized()
  198. ) {[weak self] (_, indexPath) in
  199. guard let `self` = self else { return }
  200. self.editTrigger.onNext(indexPath)
  201. }
  202. edit.backgroundColor = .themeBlue
  203. delete.backgroundColor = .themeRed
  204. return [delete, edit]
  205. }
  206. func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
  207. view.endEditing(true)
  208. }
  209. }