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.

635 lines
18 KiB

6 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
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
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
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
5 years ago
5 years ago
5 years ago
  1. //
  2. // UIExtension.swift
  3. // GMERemittance
  4. //
  5. // Created by Sujal on 12/11/17.
  6. // Copyright © 2017 Gobal Money Express Co. Ltd. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10. import MBProgressHUD
  11. import NVActivityIndicatorView
  12. import ChannelIO
  13. #if DEBUG
  14. import FLEX
  15. #endif
  16. // MARK: - Navigation
  17. extension UIViewController {
  18. func setupPicturedNavBar(sideMenuAction: Selector? = nil) {
  19. self.navigationController?.isNavigationBarHidden = false
  20. self.navigationController?.navigationBar.isTranslucent = false
  21. if let selector = sideMenuAction {
  22. let leftButton = UIBarButtonItem(
  23. image: UIImage(named: "ic_hamburger"),
  24. style: .plain,
  25. target: self,
  26. action: selector
  27. )
  28. self.navigationItem.leftBarButtonItem = leftButton
  29. } else {
  30. self.navigationItem.leftBarButtonItem = nil
  31. }
  32. self.navigationController?.navigationBar.barTintColor = .themeRedDark
  33. self.navigationController?.navigationBar.tintColor = .themeBlack
  34. self.navigationItem.leftBarButtonItem?.tintColor = .white
  35. let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 125, height: 30))
  36. imageView.contentMode = .scaleAspectFit
  37. let image = UIImage(named: "ic_gme_new")?.withRenderingMode(.alwaysTemplate)
  38. imageView.image = image
  39. imageView.tintColor = .themeWhiteRed
  40. self.navigationItem.titleView = imageView
  41. }
  42. func setupNormalNavigation(color: UIColor = .themeWhite) {
  43. self.navigationController?.isNavigationBarHidden = false
  44. self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "backIconBlack")
  45. self.navigationController?.navigationBar
  46. .backIndicatorTransitionMaskImage = UIImage(named: "backIconBlack")
  47. self.navigationController?.navigationBar.titleTextAttributes = [
  48. NSAttributedString.Key.font: UIFont.sanfrancisco(.medium, size: 17)
  49. ]
  50. self.navigationController?.navigationBar.tintColor = .themeBlack
  51. self.navigationController?.navigationBar.barTintColor = color
  52. }
  53. func setupNavigationShadow(isUse: Bool = true) {
  54. navigationController?.navigationBar.setValue(!isUse, forKey: "hidesShadow")
  55. }
  56. }
  57. // MARK: - Alert
  58. extension UIViewController {
  59. enum AlertType {
  60. case success
  61. case error
  62. case normal
  63. }
  64. func alert(
  65. type: AlertType = .normal,
  66. message: String?,
  67. title: String? = nil,
  68. rightButtomTitle: String = "ok_text".localized(),
  69. okAction: (() -> Void)? = nil
  70. ) {
  71. let settedTitle: String
  72. switch type {
  73. case .normal:
  74. settedTitle = title == nil ? "alert_text".localized() : title!
  75. case .error:
  76. settedTitle = title == nil ? "error_text".localized() : title!
  77. case .success:
  78. settedTitle = title == nil ? "success_text".localized() : title!
  79. }
  80. gmeAlert(
  81. type: type,
  82. title: settedTitle,
  83. message: message,
  84. rightButtonTitle: rightButtomTitle,
  85. leftButtonTitle: nil,
  86. rightButtonAction: okAction,
  87. leftButtonAction: nil
  88. )
  89. }
  90. func alertWithOkCancel(
  91. type: AlertType = .normal,
  92. message: String?,
  93. title: String? = nil,
  94. okTitle: String = "ok_text".localized(),
  95. cancelTitle: String = "cancel_text".localized(),
  96. okAction: (() -> Void)? = nil,
  97. cancelAction: (() -> Void)? = nil
  98. ) {
  99. let settedTitle: String
  100. switch type {
  101. case .normal:
  102. settedTitle = title == nil ? "alert_text".localized() : title!
  103. case .error:
  104. settedTitle = title == nil ? "error_text".localized() : title!
  105. case .success:
  106. settedTitle = title == nil ? "success_text".localized() : title!
  107. }
  108. gmeAlert(
  109. type: type,
  110. title: settedTitle,
  111. message: message,
  112. rightButtonTitle: okTitle,
  113. leftButtonTitle: cancelTitle,
  114. rightButtonAction: okAction,
  115. leftButtonAction: cancelAction
  116. )
  117. }
  118. func alertWithOk(
  119. type: AlertType = .normal,
  120. message: String?,
  121. title: String? = nil,
  122. okTitle: String = "ok_text".localized(),
  123. okAction: (() -> Void)? = nil
  124. ) {
  125. let settedTitle: String
  126. switch type {
  127. case .normal:
  128. settedTitle = title == nil ? "alert_text".localized() : title!
  129. case .error:
  130. settedTitle = title == nil ? "error_text".localized() : title!
  131. case .success:
  132. settedTitle = title == nil ? "success_text".localized() : title!
  133. }
  134. gmeAlert(
  135. type: type,
  136. title: settedTitle,
  137. message: message,
  138. rightButtonTitle: okTitle,
  139. leftButtonTitle: nil,
  140. rightButtonAction: okAction,
  141. leftButtonAction: nil
  142. )
  143. }
  144. private func getAlert(
  145. type: AlertType,
  146. message: String?,
  147. title: String?,
  148. style: UIAlertController.Style? = .alert
  149. ) -> UIAlertController {
  150. let customerWalletNumber = GMEDB.shared.user.string(.walletNumber) ?? ""
  151. let customerTitle: String
  152. switch type {
  153. case .error:
  154. customerTitle = "\(title ?? "Alert")(\(customerWalletNumber))"
  155. case .normal:
  156. customerTitle = title ?? ""
  157. case .success:
  158. customerTitle = title ?? ""
  159. }
  160. return UIAlertController(title: customerTitle, message: message, preferredStyle: style ?? .alert)
  161. }
  162. func present(_ alert: UIAlertController, asActionsheetInSourceView sourceView: Any) {
  163. if UI_USER_INTERFACE_IDIOM() == .pad {
  164. alert.modalPresentationStyle = .popover
  165. if let presenter = alert.popoverPresentationController {
  166. if sourceView is UIBarButtonItem {
  167. presenter.barButtonItem = sourceView as? UIBarButtonItem
  168. } else if sourceView is UIView {
  169. guard let view = sourceView as? UIView else {
  170. return
  171. }
  172. presenter.sourceView = view
  173. presenter.sourceRect = view.bounds
  174. }
  175. }
  176. }
  177. self.present(alert, animated: true, completion: nil)
  178. }
  179. func gmeAlert(
  180. type: AlertType = .normal,
  181. title: String = "Alert",
  182. message: String? = nil,
  183. rightButtonTitle: String = "Ok",
  184. leftButtonTitle: String? = nil,
  185. rightButtonAction: (() -> Void)? = nil,
  186. leftButtonAction: (() -> Void)? = nil
  187. ) {
  188. let titleText: String
  189. let customerWalletNumber = GMEDB.shared.user.string(.walletNumber) ?? ""
  190. switch type {
  191. case .error:
  192. if customerWalletNumber != "" {
  193. titleText = "\(title) (\(customerWalletNumber))"
  194. } else {
  195. titleText = title
  196. }
  197. case .normal:
  198. titleText = title
  199. case .success:
  200. titleText = title
  201. }
  202. let gmeAlertVC = GMEAlertViewController(
  203. type: type,
  204. title: titleText,
  205. message: message,
  206. rightButtonTitle: rightButtonTitle,
  207. leftButtonTitle: leftButtonTitle,
  208. rightButtonAction: rightButtonAction,
  209. leftButtonAction: leftButtonAction
  210. )
  211. present(gmeAlertVC, animated: false, completion: nil)
  212. }
  213. }
  214. extension UIAlertController {
  215. func addAction(title: String?, style: UIAlertAction.Style = .default, handler: (() -> Void)? = nil) {
  216. let action = UIAlertAction(title: title, style: style, handler: {_ in
  217. handler?()
  218. })
  219. self.addAction(action)
  220. }
  221. }
  222. struct Associate {
  223. static var hud: UInt8 = 0
  224. static var messageCount: UInt8 = 1
  225. static var csButton: UInt8 = 2
  226. static var channelIO: UInt8 = 3
  227. }
  228. // MARK: HUD
  229. extension UIViewController {
  230. private func setProgressHud() -> MBProgressHUD {
  231. let progressHud: MBProgressHUD = MBProgressHUD.showAdded(to: self.view, animated: true)
  232. progressHud.tintColor = UIColor.darkGray
  233. progressHud.removeFromSuperViewOnHide = true
  234. objc_setAssociatedObject(
  235. self, &Associate.hud,
  236. progressHud,
  237. objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
  238. )
  239. return progressHud
  240. }
  241. var progressHud: MBProgressHUD {
  242. if let progressHud = objc_getAssociatedObject(self, &Associate.hud) as? MBProgressHUD {
  243. progressHud.isUserInteractionEnabled = true
  244. return progressHud
  245. }
  246. return setProgressHud()
  247. }
  248. var progressHudIsShowing: Bool {
  249. return self.progressHud.isHidden
  250. }
  251. func showProgressHud(
  252. backgroundColor: UIColor = .themeBackgroundGray,
  253. loadingColor: UIColor = .themeRed,
  254. textColor: UIColor = .white
  255. ) {
  256. let activityData = ActivityData(
  257. size: CGSize(width: 50, height: 50),
  258. message: "loading_text".localized(),
  259. messageFont: .sanfrancisco(.medium, size: 14),
  260. messageSpacing: 2,
  261. type: .lineScale,
  262. color: loadingColor,
  263. padding: 5,
  264. backgroundColor: backgroundColor,
  265. textColor: textColor
  266. )
  267. NVActivityIndicatorPresenter.sharedInstance.startAnimating(activityData, nil)
  268. }
  269. func hideProgressHud() {
  270. NVActivityIndicatorPresenter.sharedInstance.stopAnimating(nil)
  271. }
  272. }
  273. // MARK: - LargeTitle
  274. extension UIViewController {
  275. func setLargeTitle() {
  276. if #available(iOS 11.0, *) {
  277. self.navigationController?.navigationBar.prefersLargeTitles = true
  278. self.navigationController?.navigationBar.largeTitleTextAttributes =
  279. [NSAttributedString.Key.font: UIFont.sanfrancisco(.medium, size: 20)]
  280. }
  281. // UINavigationBar.appearance().titleTextAttributes =
  282. // [NSAttributedStringKey.font: font]
  283. }
  284. }
  285. // MARK: - Activity Indicator
  286. private var associatedObjectHandle: UInt8 = 0
  287. extension UIViewController {
  288. private var progressView: UIView? {
  289. get {
  290. guard let view = objc_getAssociatedObject(self, &associatedObjectHandle) as? UIView else {
  291. return nil
  292. }
  293. return view
  294. }
  295. set {
  296. objc_setAssociatedObject(
  297. self,
  298. &associatedObjectHandle,
  299. newValue,
  300. objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
  301. )
  302. }
  303. }
  304. func setPercent(with percent: CGFloat) {
  305. let progressSubView: UIView
  306. if let view = progressView {
  307. progressSubView = view
  308. } else {
  309. progressSubView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 2))
  310. progressView = progressSubView
  311. }
  312. progressSubView.removeFromSuperview()
  313. view.addSubview(progressSubView)
  314. print("progress: \(percent)")
  315. progressSubView.backgroundColor = .themeRed
  316. let width = view.frame.width * percent
  317. UIView.animate(
  318. withDuration: 0.5,
  319. animations: {
  320. progressSubView.frame = CGRect(x: 0, y: 0, width: width, height: 2)
  321. },
  322. completion: { _ in
  323. if width == self.view.frame.width {
  324. UIView.animate(
  325. withDuration: 0.2,
  326. animations: {
  327. progressSubView.alpha = 0.0
  328. },
  329. completion: { _ in
  330. progressSubView.frame = CGRect(x: 0, y: 0, width: 0, height: 2)
  331. progressSubView.alpha = 1.0
  332. })
  333. }
  334. }
  335. )
  336. }
  337. }
  338. // MARK: - Right Bar button item form ChannelIO
  339. extension UIViewController {
  340. @discardableResult
  341. func setMessageCount(with count: Int = 0) -> Int {
  342. objc_setAssociatedObject(
  343. self, &Associate.messageCount,
  344. count,
  345. objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
  346. )
  347. var appearance = BadgeAppearance()
  348. let message = count != 0 ? "\(count)" : nil
  349. appearance.backgroundColor = .themeWhiteRed
  350. appearance.textColor = .themeRedWhite
  351. csButton.badge(text: message, appearance: appearance)
  352. return count
  353. }
  354. private var messageCount: Int {
  355. guard let count = objc_getAssociatedObject(self, &Associate.messageCount) as? Int else {
  356. let count = setMessageCount()
  357. return count
  358. }
  359. return count
  360. }
  361. private func setCSButton() -> UIBarButtonItem {
  362. let supportImage = UIImage(named: "ic_support")?.withRenderingMode(.alwaysOriginal)
  363. let csButton = UIBarButtonItem(
  364. image: supportImage,
  365. style: .plain,
  366. target: self,
  367. action: #selector(UIViewController.touchCSButton)
  368. )
  369. objc_setAssociatedObject(
  370. self, &Associate.csButton,
  371. csButton,
  372. objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
  373. )
  374. return csButton
  375. }
  376. var csButton: UIBarButtonItem {
  377. if let csButton = objc_getAssociatedObject(self, &Associate.csButton) as? UIBarButtonItem {
  378. return csButton
  379. }
  380. return setCSButton()
  381. }
  382. @discardableResult
  383. private func setChannelIODelegate(_ delegate: ChannelPluginDelegate? = nil) -> ChannelPluginDelegate? {
  384. guard let delegate = delegate else { return nil }
  385. objc_setAssociatedObject(
  386. self, &Associate.channelIO,
  387. delegate,
  388. objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
  389. )
  390. return delegate
  391. }
  392. var channelIODelegate: ChannelPluginDelegate? {
  393. if let delegate = objc_getAssociatedObject(self, &Associate.channelIO) as? ChannelPluginDelegate {
  394. return delegate
  395. }
  396. return setChannelIODelegate()
  397. }
  398. func addRightCSButton(delegate: ChannelPluginDelegate) {
  399. setChannelIODelegate(delegate)
  400. self.navigationItem.rightBarButtonItem = csButton
  401. }
  402. @objc func touchCSButton() {
  403. let hotLines = HotLineService().staticHotLines
  404. let nativeCountry = GMEDB.shared.user.string(.countryCode)?.lowercased()
  405. let userHotLine = hotLines?.filter { $0.countryCode == nativeCountry }.first
  406. let alert = UIAlertController(
  407. title: nil,
  408. message: "help_you_text".localized(),
  409. preferredStyle: .actionSheet
  410. )
  411. let liveChat = UIAlertAction(
  412. title: "live_chat_text".localized(),
  413. style: .default
  414. ) { _ in
  415. self.alertWithOkCancel(
  416. message: "check_start_chat_text".localized(),
  417. title: "check_start_chat_title_text".localized(),
  418. okTitle: "yes_text".localized(),
  419. cancelTitle: "no_text".localized(),
  420. okAction: {
  421. self.setChannelIO(delegate: self.channelIODelegate)
  422. }
  423. )
  424. }
  425. #if DEBUG
  426. let debug = UIAlertAction(
  427. title: "Debug",
  428. style: .default
  429. ) { _ in
  430. FLEXManager.shared()?.showExplorer()
  431. }
  432. let changeServer = UIAlertAction(
  433. title: "Change Server (\(server.rawValue))",
  434. style: .destructive
  435. ) { _ in
  436. MainWireframe.shared?.window?.rootViewController = LauncherScreenWireframe().getMainView()
  437. }
  438. #endif
  439. let contactNumber = UIAlertAction(
  440. title: userHotLine?.remitPhoneNumber ?? "1588 6864",
  441. style: .default
  442. ) { _ in
  443. self.startCall(contactNumber: userHotLine?.remitPhoneNumber ?? "1588 6864")
  444. }
  445. liveChat.setValue(UIImage(named:"chat")?.withRenderingMode(.alwaysOriginal),forKey:"image")
  446. contactNumber.setValue(UIImage(named:"ic_call")?.withRenderingMode(.alwaysOriginal),forKey:"image")
  447. #if DEBUG
  448. alert.addAction(changeServer)
  449. alert.addAction(debug)
  450. #endif
  451. alert.addAction(liveChat)
  452. alert.addAction(contactNumber)
  453. alert.addAction(UIAlertAction(
  454. title: "cancel_text".localized(),
  455. style: UIAlertAction.Style.cancel,
  456. handler: nil
  457. )
  458. )
  459. alert.view.tintColor = .themeText
  460. if UIDevice.current.userInterfaceIdiom == .pad {
  461. if let popoverController = alert.popoverPresentationController {
  462. popoverController.sourceView = self.view
  463. popoverController.sourceRect = CGRect(
  464. x: self.view.bounds.midX,
  465. y: self.view.bounds.midY,
  466. width: 0,
  467. height: 0
  468. )
  469. popoverController.permittedArrowDirections = []
  470. self.present(alert, animated: true, completion: nil)
  471. }
  472. } else {
  473. self.present(alert, animated: true, completion: nil)
  474. }
  475. guard
  476. let label = (liveChat.value(forKey: "__representer")as? NSObject)?.value(forKey: "label") as? UILabel
  477. else { return }
  478. var appearance = BadgeAppearance()
  479. appearance.distanceFromCenterX = (label.intrinsicContentSize.width / 2) + 10
  480. appearance.distanceFromCenterY = -(label.intrinsicContentSize.height / 2)
  481. let message = messageCount != 0 ? "\(messageCount)" : nil
  482. label.badge(text: message, appearance: appearance)
  483. }
  484. func setChannelIO(delegate: ChannelPluginDelegate?) {
  485. let settings = ChannelPluginSettings()
  486. settings.pluginKey = "24dc2dfd-3ed1-4953-b395-a2255ed41dae"
  487. settings.userId = GMEDB.shared.user.string(.userId)
  488. let profile = Profile()
  489. let username = GMEDB.shared.user.string(.fullName)
  490. let email = GMEDB.shared.user.string(.email)
  491. profile
  492. .set(name: username ?? "")
  493. .set(email: email ?? "")
  494. ChannelIO.delegate = delegate
  495. ChannelIO.boot(with:settings, profile: profile) {(completion, _) in
  496. var message = "channelIO_error_message_text".localized()
  497. switch completion {
  498. case .success:
  499. ChannelIO.open(animated: true)
  500. return
  501. case .notInitialized: message += "(1)"
  502. case .networkTimeout: message += "(2)"
  503. case .notAvailableVersion: message += "(3)"
  504. case .serviceUnderConstruction: message += "(4)"
  505. case .requirePayment: message += "(5)"
  506. case .accessDenied: message += "(6)"
  507. case .unknown: message += "(7)"
  508. @unknown default: message += "(8)"
  509. }
  510. self.alert(type: .error, message: message)
  511. }
  512. }
  513. private func startCall(contactNumber: String) {
  514. if let url = URL(string: "tel://\(contactNumber.removeWhitespacesInBetween())"),
  515. UIApplication.shared.canOpenURL(url) {
  516. UIApplication.shared.open(url)
  517. }
  518. }
  519. }
  520. extension UIViewController {
  521. func presentDatePicker(completion: ((_ from: String?, _ to: String?) -> Void)?) {
  522. guard let datePickerViewController = UIStoryboard
  523. .init(name: "TransactionHistoryDatePicker", bundle: nil)
  524. .instantiateViewController(
  525. withIdentifier: "DatePickerViewController"
  526. ) as? DatePickerViewController else { return }
  527. datePickerViewController.completion = completion
  528. present(datePickerViewController, animated: true, completion: nil)
  529. }
  530. }