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.

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