// // UIExtension.swift // GMERemittance // // Created by Sujal on 12/11/17. // Copyright © 2017 Gobal Money Express Co. Ltd. All rights reserved. // import Foundation import UIKit import MBProgressHUD import NVActivityIndicatorView import ChannelIO #if DEBUG import FLEX #endif // MARK: - Navigation extension UIViewController { func setupPicturedNavBar(sideMenuAction: Selector? = nil) { self.navigationController?.isNavigationBarHidden = false self.navigationController?.navigationBar.isTranslucent = false if let selector = sideMenuAction { let leftButton = UIBarButtonItem( image: UIImage(named: "ic_hamburger"), style: .plain, target: self, action: selector ) self.navigationItem.leftBarButtonItem = leftButton } else { self.navigationItem.leftBarButtonItem = nil } self.navigationController?.navigationBar.barTintColor = .themeRedDark self.navigationController?.navigationBar.tintColor = .themeBlack self.navigationItem.leftBarButtonItem?.tintColor = .white let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 125, height: 30)) imageView.contentMode = .scaleAspectFit let image = UIImage(named: "ic_gme_new")?.withRenderingMode(.alwaysTemplate) imageView.image = image imageView.tintColor = .themeWhiteRed self.navigationItem.titleView = imageView } func setupNormalNavigation(color: UIColor = .themeWhite) { self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "backIconBlack") self.navigationController?.navigationBar .backIndicatorTransitionMaskImage = UIImage(named: "backIconBlack") self.navigationController?.navigationBar.titleTextAttributes = [ NSAttributedString.Key.font: UIFont.sanfrancisco(.medium, size: 17) ] self.navigationController?.navigationBar.tintColor = .themeBlack self.navigationController?.navigationBar.barTintColor = color } func setupNavigationShadow(isUse: Bool = true) { navigationController?.navigationBar.setValue(!isUse, forKey: "hidesShadow") } } // MARK: - Alert extension UIViewController { enum AlertType { case error case normal } func alert( type: AlertType = .normal, message: String?, title: String? = nil, rightButtomTitle: String = "ok_text".localized(), okAction: (() -> Void)? = nil ) { let settedTitle: String switch type { case .normal: settedTitle = title == nil ? "alert_text".localized() : title! case .error: settedTitle = title == nil ? "error_text".localized() : title! } gmeAlert( type: type, title: settedTitle, message: message, rightButtonTitle: rightButtomTitle, leftButtonTitle: nil, rightButtonAction: okAction, leftButtonAction: nil ) } func alertWithOkCancel( type: AlertType = .normal, message: String?, title: String? = nil, okTitle: String = "ok_text".localized(), cancelTitle: String = "cancel_text".localized(), okAction: (() -> Void)? = nil, cancelAction: (() -> Void)? = nil ) { let settedTitle: String switch type { case .normal: settedTitle = title == nil ? "alert_text".localized() : title! case .error: settedTitle = title == nil ? "error_text".localized() : title! } gmeAlert( type: type, title: settedTitle, message: message, rightButtonTitle: okTitle, leftButtonTitle: cancelTitle, rightButtonAction: okAction, leftButtonAction: cancelAction ) } func alertWithOk( type: AlertType = .normal, message: String?, title: String? = nil, okTitle: String = "ok_text".localized(), okAction: (() -> Void)? = nil ) { let settedTitle: String switch type { case .normal: settedTitle = title == nil ? "alert_text".localized() : title! case .error: settedTitle = title == nil ? "error_text".localized() : title! } gmeAlert( type: type, title: settedTitle, message: message, rightButtonTitle: okTitle, leftButtonTitle: nil, rightButtonAction: okAction, leftButtonAction: nil ) } private func getAlert( type: AlertType, message: String?, title: String?, style: UIAlertController.Style? = .alert ) -> UIAlertController { let customerWalletNumber = GMEDB.shared.user.string(.walletNumber) ?? "" let customerTitle: String switch type { case .error: customerTitle = "\(title ?? "Alert")(\(customerWalletNumber))" case .normal: customerTitle = title ?? "" } return UIAlertController(title: customerTitle, message: message, preferredStyle: style ?? .alert) } func present(_ alert: UIAlertController, asActionsheetInSourceView sourceView: Any) { if UI_USER_INTERFACE_IDIOM() == .pad { alert.modalPresentationStyle = .popover if let presenter = alert.popoverPresentationController { if sourceView is UIBarButtonItem { presenter.barButtonItem = sourceView as? UIBarButtonItem } else if sourceView is UIView { guard let view = sourceView as? UIView else { return } presenter.sourceView = view presenter.sourceRect = view.bounds } } } self.present(alert, animated: true, completion: nil) } func gmeAlert( type: AlertType = .normal, title: String = "Alert", message: String? = nil, rightButtonTitle: String = "Ok", leftButtonTitle: String? = nil, rightButtonAction: (() -> Void)? = nil, leftButtonAction: (() -> Void)? = nil ) { let titleText: String let customerWalletNumber = GMEDB.shared.user.string(.walletNumber) ?? "" switch type { case .error: if customerWalletNumber != "" { titleText = "\(title) (\(customerWalletNumber))" } else { titleText = title } case .normal: titleText = title } let gmeAlertVC = GMEAlertViewController( type: type, title: titleText, message: message, rightButtonTitle: rightButtonTitle, leftButtonTitle: leftButtonTitle, rightButtonAction: rightButtonAction, leftButtonAction: leftButtonAction ) present(gmeAlertVC, animated: false, completion: nil) } } extension UIAlertController { func addAction(title: String?, style: UIAlertAction.Style = .default, handler: (() -> Void)? = nil) { let action = UIAlertAction(title: title, style: style, handler: {_ in handler?() }) self.addAction(action) } } struct Associate { static var hud: UInt8 = 0 static var messageCount: UInt8 = 1 static var csButton: UInt8 = 2 static var channelIO: UInt8 = 3 } // MARK: HUD extension UIViewController { private func setProgressHud() -> MBProgressHUD { let progressHud: MBProgressHUD = MBProgressHUD.showAdded(to: self.view, animated: true) progressHud.tintColor = UIColor.darkGray progressHud.removeFromSuperViewOnHide = true objc_setAssociatedObject( self, &Associate.hud, progressHud, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC ) return progressHud } var progressHud: MBProgressHUD { if let progressHud = objc_getAssociatedObject(self, &Associate.hud) as? MBProgressHUD { progressHud.isUserInteractionEnabled = true return progressHud } return setProgressHud() } var progressHudIsShowing: Bool { return self.progressHud.isHidden } func showProgressHud( backgroundColor: UIColor = .themeBackgroundGray, loadingColor: UIColor = .themeRed, textColor: UIColor = .white ) { let activityData = ActivityData( size: CGSize(width: 50, height: 50), message: "loading_text".localized(), messageFont: .sanfrancisco(.medium, size: 14), messageSpacing: 2, type: .lineScale, color: loadingColor, padding: 5, backgroundColor: backgroundColor, textColor: textColor ) NVActivityIndicatorPresenter.sharedInstance.startAnimating(activityData, nil) } func hideProgressHud() { NVActivityIndicatorPresenter.sharedInstance.stopAnimating(nil) } } // MARK: - LargeTitle extension UIViewController { func setLargeTitle() { if #available(iOS 11.0, *) { self.navigationController?.navigationBar.prefersLargeTitles = true self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.font: UIFont.sanfrancisco(.medium, size: 20)] } // UINavigationBar.appearance().titleTextAttributes = // [NSAttributedStringKey.font: font] } } // MARK: - Activity Indicator private var associatedObjectHandle: UInt8 = 0 extension UIViewController { private var progressView: UIView? { get { guard let view = objc_getAssociatedObject(self, &associatedObjectHandle) as? UIView else { return nil } return view } set { objc_setAssociatedObject( self, &associatedObjectHandle, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC ) } } func setPercent(with percent: CGFloat) { let progressSubView: UIView if let view = progressView { progressSubView = view } else { progressSubView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 2)) progressView = progressSubView } progressSubView.removeFromSuperview() view.addSubview(progressSubView) print("progress: \(percent)") progressSubView.backgroundColor = .themeRed let width = view.frame.width * percent UIView.animate( withDuration: 0.5, animations: { progressSubView.frame = CGRect(x: 0, y: 0, width: width, height: 2) }, completion: { _ in if width == self.view.frame.width { UIView.animate( withDuration: 0.2, animations: { progressSubView.alpha = 0.0 }, completion: { _ in progressSubView.frame = CGRect(x: 0, y: 0, width: 0, height: 2) progressSubView.alpha = 1.0 }) } } ) } } // MARK: - Right Bar button item form ChannelIO extension UIViewController { @discardableResult func setMessageCount(with count: Int = 0) -> Int { objc_setAssociatedObject( self, &Associate.messageCount, count, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC ) var appearance = BadgeAppearance() let message = count != 0 ? "\(count)" : nil appearance.backgroundColor = .themeWhiteRed appearance.textColor = .themeRedWhite csButton.badge(text: message, appearance: appearance) return count } private var messageCount: Int { guard let count = objc_getAssociatedObject(self, &Associate.messageCount) as? Int else { let count = setMessageCount() return count } return count } private func setCSButton() -> UIBarButtonItem { let supportImage = UIImage(named: "ic_support")?.withRenderingMode(.alwaysOriginal) let csButton = UIBarButtonItem( image: supportImage, style: .plain, target: self, action: #selector(UIViewController.touchCSButton) ) objc_setAssociatedObject( self, &Associate.csButton, csButton, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC ) return csButton } var csButton: UIBarButtonItem { if let csButton = objc_getAssociatedObject(self, &Associate.csButton) as? UIBarButtonItem { return csButton } return setCSButton() } @discardableResult private func setChannelIODelegate(_ delegate: ChannelPluginDelegate? = nil) -> ChannelPluginDelegate? { guard let delegate = delegate else { return nil } objc_setAssociatedObject( self, &Associate.channelIO, delegate, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC ) return delegate } var channelIODelegate: ChannelPluginDelegate? { if let delegate = objc_getAssociatedObject(self, &Associate.channelIO) as? ChannelPluginDelegate { return delegate } return setChannelIODelegate() } func addRightCSButton(delegate: ChannelPluginDelegate) { setChannelIODelegate(delegate) self.navigationItem.rightBarButtonItem = csButton } @objc func touchCSButton() { let hotLines = HotLineService().staticHotLines let nativeCountry = GMEDB.shared.user.string(.countryCode)?.lowercased() let userHotLine = hotLines?.filter { $0.countryCode == nativeCountry }.first let alert = UIAlertController( title: nil, message: "help_you_text".localized(), preferredStyle: .actionSheet ) let liveChat = UIAlertAction( title: "live_chat_text".localized(), style: .default ) { _ in self.alertWithOkCancel( message: "check_start_chat_text".localized(), title: "check_start_chat_title_text".localized(), okTitle: "yes_text".localized(), cancelTitle: "no_text".localized(), okAction: { self.setChannelIO(delegate: self.channelIODelegate) } ) } #if DEBUG let debug = UIAlertAction( title: "Debug", style: .default ) { _ in FLEXManager.shared()?.showExplorer() } let changeServer = UIAlertAction( title: "Change Server (\(server.rawValue))", style: .destructive ) { _ in MainWireframe.shared?.window?.rootViewController = LauncherScreenWireframe().getMainView() } #endif let contactNumber = UIAlertAction( title: userHotLine?.remitPhoneNumber ?? "1588 6864", style: .default ) { _ in self.startCall(contactNumber: userHotLine?.remitPhoneNumber ?? "1588 6864") } liveChat.setValue(UIImage(named:"chat")?.withRenderingMode(.alwaysOriginal),forKey:"image") contactNumber.setValue(UIImage(named:"ic_call")?.withRenderingMode(.alwaysOriginal),forKey:"image") #if DEBUG alert.addAction(changeServer) alert.addAction(debug) #endif alert.addAction(liveChat) alert.addAction(contactNumber) alert.addAction(UIAlertAction( title: "cancel_text".localized(), style: UIAlertAction.Style.cancel, handler: nil ) ) alert.view.tintColor = .themeText if UIDevice.current.userInterfaceIdiom == .pad { if let popoverController = alert.popoverPresentationController { popoverController.sourceView = self.view popoverController.sourceRect = CGRect( x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0 ) popoverController.permittedArrowDirections = [] self.present(alert, animated: true, completion: nil) } } else { self.present(alert, animated: true, completion: nil) } guard let label = (liveChat.value(forKey: "__representer")as? NSObject)?.value(forKey: "label") as? UILabel else { return } var appearance = BadgeAppearance() appearance.distanceFromCenterX = (label.intrinsicContentSize.width / 2) + 10 appearance.distanceFromCenterY = -(label.intrinsicContentSize.height / 2) let message = messageCount != 0 ? "\(messageCount)" : nil label.badge(text: message, appearance: appearance) } func setChannelIO(delegate: ChannelPluginDelegate?) { let settings = ChannelPluginSettings() settings.pluginKey = "24dc2dfd-3ed1-4953-b395-a2255ed41dae" settings.userId = GMEDB.shared.user.string(.userId) let profile = Profile() let username = GMEDB.shared.user.string(.fullName) let email = GMEDB.shared.user.string(.email) profile .set(name: username ?? "") .set(email: email ?? "") ChannelIO.delegate = delegate ChannelIO.boot(with:settings, profile: profile) {(completion, _) in var message = "channelIO_error_message_text".localized() switch completion { case .success: ChannelIO.open(animated: true) return case .notInitialized: message += "(1)" case .networkTimeout: message += "(2)" case .notAvailableVersion: message += "(3)" case .serviceUnderConstruction: message += "(4)" case .requirePayment: message += "(5)" case .accessDenied: message += "(6)" case .unknown: message += "(7)" @unknown default: message += "(8)" } self.alert(type: .error, message: message) } } private func startCall(contactNumber: String) { if let url = URL(string: "tel://\(contactNumber.removeWhitespacesInBetween())"), UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url) } } }