ViewController.swift 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339
  1. //
  2. // ViewController.swift
  3. // TestQmeraLite
  4. //
  5. // Created by Qindi on 29/11/21.
  6. //
  7. import UIKit
  8. import NexilisLite
  9. import AVKit
  10. import AVFoundation
  11. import SwiftUI
  12. import Speech
  13. import Alamofire
  14. import WebKit
  15. class ViewController: UITabBarController, UITabBarControllerDelegate, SettingMABDelegate, WKNavigationDelegate {
  16. let playerController = AVPlayerViewController()
  17. static var sURL = "https://www.google.com"
  18. static var tab3 = "0"
  19. public var isShow: Bool = false
  20. public static var chatButton = UIButton()
  21. public static var callButton = UIButton()
  22. public static var ccButton = UIButton()
  23. public static var streamingButton = UIButton()
  24. public static var postButton = UIButton()
  25. public static var middleButton = UIButton()
  26. var buttonChatGR : UITapGestureRecognizer?
  27. var buttonCallGR : UITapGestureRecognizer?
  28. var buttonCCGR : UITapGestureRecognizer?
  29. var buttonStreamGR : UITapGestureRecognizer?
  30. var floating : FloatingButton?
  31. var firstTab : FirstTabViewController?
  32. var secondTab : SecondTabViewController?
  33. var thirdTab : ThirdTabViewController?
  34. var fourthTab : FourthTabViewController?
  35. let emptyTab = EmptyTabViewController()
  36. public static var isTab1 = true
  37. public static var isTab2 = false
  38. public static var isTab3 = false
  39. public static var isTab4 = false
  40. public static var isExpandButton = false
  41. public static var alwaysHideButton = false
  42. static var listPullFB: [String] = []
  43. static var datePullFB: Date?
  44. let welcomeVC = UIViewController()
  45. let privacyPolicyVC = UIViewController()
  46. var termVC: UIViewController?
  47. let welcomeDesc = UILabel()
  48. let termText = "Read our Terms of Service. Tap \"Agree and Continue\" to accept Terms of Service.".localized()
  49. let term = "Terms of Service.".localized()
  50. var firstLoad = true
  51. let privacyWV = WKWebView()
  52. let indicatorCounterFB = UIView()
  53. let labelCounterFB = UILabel()
  54. public static var def: ViewController?
  55. override func viewDidLoad() {
  56. super.viewDidLoad()
  57. DispatchQueue.main.async { [self] in
  58. while !Utils.getFinishInitPrefsr() || HTTPCookieStorage.shared.cookies?.count == 0 {
  59. //print("WAITING PREFS DONE")
  60. }
  61. startView()
  62. }
  63. }
  64. func startView() {
  65. self.navigationController?.view.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .black : .white
  66. let topBorder = CALayer()
  67. topBorder.backgroundColor = UIColor.gray.withAlphaComponent(0.5).cgColor
  68. topBorder.frame = CGRect(x: 0, y: 0, width: tabBar.frame.size.width, height: 1)
  69. tabBar.layer.addSublayer(topBorder)
  70. ViewController.def = self
  71. title = Bundle.main.displayName
  72. let customTab = PrefsUtil.getCustomTab().split(separator: ",")
  73. let cpaasMode = PrefsUtil.getCpaasMode()
  74. var tabs : [UIViewController] = []
  75. firstTab = storyboard?.instantiateViewController(withIdentifier: "firstTabVC") as? FirstTabViewController
  76. secondTab = storyboard?.instantiateViewController(withIdentifier: "secondTabVC") as? SecondTabViewController
  77. thirdTab = storyboard?.instantiateViewController(withIdentifier: "thirdTabVC") as? ThirdTabViewController
  78. fourthTab = storyboard?.instantiateViewController(withIdentifier: "fourthTabVC") as? FourthTabViewController
  79. self.delegate = self
  80. firstTab?.tabBarItem = UITabBarItem(title: "", image: resizeImage(image: self.traitCollection.userInterfaceStyle == .dark ? UIImage(named: "tab_1_icon")!.withTintColor(.white) : UIImage(named: "tab_1_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), selectedImage: resizeImage(image: UIImage(named: "tab_1_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal).withTintColor(.mainColor))
  81. secondTab?.tabBarItem = UITabBarItem(title: "", image: resizeImage(image: self.traitCollection.userInterfaceStyle == .dark ? UIImage(named: "tab_2_icon")!.withTintColor(.white) : UIImage(named: "tab_2_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), selectedImage: resizeImage(image: UIImage(named: "tab_2_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal).withTintColor(.mainColor))
  82. thirdTab?.tabBarItem = UITabBarItem(title: "", image: resizeImage(image: self.traitCollection.userInterfaceStyle == .dark ? UIImage(named: "tab_3_icon")!.withTintColor(.white) : UIImage(named: "tab_3_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), selectedImage: resizeImage(image: UIImage(named: "tab_3_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal).withTintColor(.mainColor))
  83. fourthTab?.tabBarItem = UITabBarItem(title: "", image: resizeImage(image: self.traitCollection.userInterfaceStyle == .dark ? UIImage(named: "tab_4_icon")!.withTintColor(.white) : UIImage(named: "tab_4_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), selectedImage: resizeImage(image: UIImage(named: "tab_4_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal).withTintColor(.mainColor))
  84. var i = 0
  85. var j = 0
  86. while j < customTab.count {
  87. if(((i == 1 && customTab.count == 3) || i == 2) &&
  88. (cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)){
  89. tabs.append(emptyTab)
  90. }
  91. else {
  92. switch(customTab[j]){
  93. case "1":
  94. tabs.append(firstTab!)
  95. case "2":
  96. tabs.append(secondTab!)
  97. case "3":
  98. tabs.append(thirdTab!)
  99. case "4":
  100. tabs.append(fourthTab!)
  101. default:
  102. break
  103. }
  104. j += 1
  105. }
  106. i += 1
  107. }
  108. if(cpaasMode == PrefsUtil.CPAAS_MODE_BURGER){
  109. navigationController?.setNavigationBarHidden(false, animated: false)
  110. //print("cpaas mode burger")
  111. let childrenMenu : [UIAction] = [
  112. UIAction(title: "Contact Center", handler: {[weak self](_) in
  113. self?.ccTap()
  114. }),
  115. UIAction(title: "Chat", handler: {[weak self](_) in
  116. self?.chatTap()
  117. }),
  118. UIAction(title: "Call", handler: {[weak self](_) in
  119. self?.callTap()
  120. }),
  121. UIAction(title: "New Post", handler: {[weak self](_) in
  122. self?.postTap()
  123. }),
  124. UIAction(title: "Live Streaming", handler: {[weak self](_) in
  125. self?.streamTap()
  126. }),
  127. // UIAction(title: "Settings", handler: {[weak self](_) in
  128. // self?.settingTap()
  129. // }),
  130. ]
  131. let menu = UIMenu(title: "", children: childrenMenu)
  132. if !PrefsUtil.getIconDock().isEmpty {
  133. DispatchQueue.global().async {
  134. ViewController.getDataImageFromUrl(from: URL(string: PrefsUtil.getUrlDock()!)!) { data, response, error in
  135. guard let data = data, error == nil else { return }
  136. // always update the UI from the main thread
  137. DispatchQueue.main.async() { [self] in
  138. navigationItem.rightBarButtonItem = UIBarButtonItem(image: resizeImage(image: UIImage(data: data)!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), primaryAction: .none, menu: menu)
  139. }
  140. }
  141. }
  142. } else {
  143. navigationItem.rightBarButtonItem = UIBarButtonItem(image: resizeImage(image: UIImage(named: "pb_button", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), primaryAction: .none, menu: menu)
  144. }
  145. }
  146. if((cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)){
  147. createMidFloatingButton()
  148. navigationController?.setNavigationBarHidden(true, animated: false)
  149. ViewController.pullActionButton()
  150. }
  151. // if((cpaasMode == PrefsUtil.CPAAS_MODE_FLOATING || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)) {
  152. // let rect = CGRect(x: self.view.bounds.width - 100, y: self.view.bounds.height / 2, width: 50, height: 250)
  153. // floating = FloatingButton()
  154. // floating?.frame = rect
  155. // floating?.isShow = true
  156. //
  157. // view.addSubview(floating!)
  158. // navigationController?.setNavigationBarHidden(true, animated: false)
  159. // }
  160. self.setViewControllers(tabs, animated: false)
  161. if(cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX){
  162. if(customTab.count == 3){
  163. self.tabBar.items?[1].isEnabled = false
  164. }
  165. self.tabBar.items?[2].isEnabled = false
  166. }
  167. let center: NotificationCenter = NotificationCenter.default
  168. center.addObserver(self, selector: #selector(checkCounter), name: NSNotification.Name(rawValue: Nexilis.listenerReceiveChat), object: nil)
  169. center.addObserver(self, selector: #selector(checkCounter), name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil)
  170. checkCounter()
  171. willappear()
  172. }
  173. static func getiPhoneModel() -> String {
  174. var systemInfo = utsname()
  175. uname(&systemInfo)
  176. let machineMirror = Mirror(reflecting: systemInfo.machine)
  177. let identifier = machineMirror.children.reduce("") { identifier, element in
  178. guard let value = element.value as? Int8, value != 0 else { return identifier }
  179. return identifier + String(UnicodeScalar(UInt8(value)))
  180. }
  181. var model = ""
  182. if let modelName = mapToDevice(identifier: identifier) {
  183. model = modelName
  184. } else {
  185. model = "Unknown"
  186. }
  187. return model
  188. }
  189. static func mapToDevice(identifier: String) -> String? {
  190. // Add mappings for iPhone models as needed
  191. switch identifier {
  192. case "iPhone1,1", "iPhone1,2", "iPhone2,1", "iPhone3,1", "iPhone3,2", "iPhone3,3", "iPhone4,1", "iPhone5,1", "iPhone5,2", "iPhone5,3", "iPhone5,4", "iPhone6,1", "iPhone6,2", "iPhone7,1", "iPhone7,2", "iPhone8,1", "iPhone8,2", "iPhone8,4", "iPhone9,1", "iPhone9,2", "iPhone9,3", "iPhone9,4", "iPhone10,1", "iPhone10,2", "iPhone10,4", "iPhone10,5": return "iPhone under X"
  193. default: return "iPhone X or newer"
  194. }
  195. }
  196. func getPrefs(key: String) -> TMessage {
  197. let tMessage = NexilisLite.TMessage()
  198. let me = UserDefaults.standard.string(forKey: "me")
  199. tMessage.mCode = "PPR"
  200. tMessage.mStatus = CoreMessage_TMessageUtil.getTID()
  201. tMessage.mBodies[CoreMessage_TMessageKey.F_PIN] = me
  202. tMessage.mBodies[CoreMessage_TMessageKey.KEY] = key
  203. return tMessage
  204. }
  205. @objc func checkCounter() {
  206. DispatchQueue.main.async { [self] in
  207. if self.viewControllers?.firstIndex(of: secondTab!) != nil {
  208. let counter = queryCountCounter()
  209. let indexSecondTab = self.viewControllers?.firstIndex(of: secondTab!)
  210. let viewSecondTab = self.tabBar.items?[indexSecondTab!].value(forKey: "view") as! UIView
  211. if counter > 0 {
  212. if !indicatorCounterFB.isDescendant(of: viewSecondTab) {
  213. let viewSecondTab = self.tabBar.items?[indexSecondTab!].value(forKey: "view") as! UIView
  214. indicatorCounterFB.backgroundColor = .red
  215. indicatorCounterFB.layer.cornerRadius = 7.5
  216. indicatorCounterFB.clipsToBounds = true
  217. viewSecondTab.addSubview(indicatorCounterFB)
  218. indicatorCounterFB.anchor(top: viewSecondTab.topAnchor, right: viewSecondTab.rightAnchor, paddingRight: 20, height: 15, minWidth: 15, maxWidth: 20)
  219. indicatorCounterFB.addSubview(labelCounterFB)
  220. labelCounterFB.anchor(left: indicatorCounterFB.leftAnchor, right: indicatorCounterFB.rightAnchor, paddingLeft: 5, paddingRight: 5, centerX: indicatorCounterFB.centerXAnchor, centerY: indicatorCounterFB.centerYAnchor)
  221. labelCounterFB.font = .systemFont(ofSize: 10)
  222. labelCounterFB.textColor = .white
  223. }
  224. if counter > 99 {
  225. labelCounterFB.text = "99+"
  226. } else {
  227. labelCounterFB.text = "\(counter)"
  228. }
  229. } else {
  230. if indicatorCounterFB.isDescendant(of: viewSecondTab) {
  231. indicatorCounterFB.removeFromSuperview()
  232. }
  233. }
  234. }
  235. }
  236. }
  237. private func queryCountCounter() -> Int32 {
  238. var counter: Int32?
  239. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  240. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT SUM(counter) FROM MESSAGE_SUMMARY"), cursor.next() {
  241. counter = cursor.int(forColumnIndex: 0)
  242. cursor.close()
  243. }
  244. })
  245. return counter ?? 0
  246. }
  247. // override func viewDidLayoutSubviews() {
  248. // super.viewDidLayoutSubviews()
  249. // tabBar.frame.size.height = 65
  250. // tabBar.frame.origin.y = view.frame.height - 65
  251. // }
  252. func settingDelegate() {
  253. if self.viewControllers?.firstIndex(of: fourthTab!) == nil {
  254. let vc = fourthTab!
  255. vc.notInTab = true
  256. self.navigationController?.show(vc, sender: nil)
  257. } else {
  258. self.selectedIndex = (self.viewControllers?.firstIndex(of: fourthTab!))!
  259. }
  260. }
  261. static var alertChangeProfile = LibAlertController()
  262. public static func checkIsChangePerson() -> Bool {
  263. let isChangeProfile = Utils.getSetProfile()
  264. if !isChangeProfile {
  265. alertChangeProfile.dismiss(animated: false)
  266. alertChangeProfile = LibAlertController(title: "Change Profile".localized(), message: "You must change your name to use this feature".localized().localized(), preferredStyle: .alert)
  267. alertChangeProfile.addAction(UIAlertAction(title: "Cancel".localized(), style: .destructive, handler: {_ in
  268. if ViewController.def?.viewControllers?.firstIndex(of: (ViewController.def?.firstTab)!) == ViewController.def?.selectedIndex {
  269. ViewController.def?.firstTab?.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}")
  270. }
  271. if ViewController.def?.viewControllers?.firstIndex(of: (ViewController.def?.thirdTab)!) == ViewController.def?.selectedIndex {
  272. ViewController.def?.thirdTab?.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}")
  273. }
  274. }))
  275. alertChangeProfile.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  276. ViewController.resetTabSelected()
  277. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  278. controller.forceLogin = true
  279. controller.isDismiss = { newThumb in
  280. FirstTabViewController.forceRefresh = true
  281. ThirdTabViewController.forceRefresh = true
  282. FirstTabViewController.showModal = false
  283. ThirdTabViewController.showModal = false
  284. }
  285. let navigationController = UINavigationController(rootViewController: controller)
  286. navigationController.modalPresentationStyle = .fullScreen
  287. navigationController.navigationBar.tintColor = .white
  288. navigationController.navigationBar.barTintColor = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  289. navigationController.navigationBar.isTranslucent = false
  290. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  291. navigationController.navigationBar.barStyle = .black
  292. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  293. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  294. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  295. navigationController.navigationBar.titleTextAttributes = textAttributes
  296. navigationController.view.backgroundColor = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.traitCollection.userInterfaceStyle == .dark ? .black : .white
  297. ViewController.def?.show(b: false)
  298. ViewController.def?.thirdTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  299. ViewController.def?.firstTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  300. let rootVC = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController
  301. if rootVC?.presentedViewController == nil {
  302. rootVC?.present(navigationController, animated: true, completion: nil)
  303. } else {
  304. rootVC?.presentedViewController?.present(navigationController, animated: true, completion: nil)
  305. }
  306. }))
  307. let rootVC = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController
  308. if rootVC?.presentedViewController == nil {
  309. rootVC?.present(alertChangeProfile, animated: true, completion: nil)
  310. } else {
  311. rootVC?.presentedViewController?.present(alertChangeProfile, animated: true, completion: nil)
  312. }
  313. return false
  314. }
  315. return true
  316. }
  317. public static func resetTabSelected(){
  318. ViewController.isTab1 = true
  319. ViewController.isTab2 = false
  320. ViewController.isTab3 = false
  321. ViewController.isTab4 = false
  322. // if ViewController.isTab1 {
  323. // ViewController.imageTab1.image = UIImage(named: "tab_1_nexilis")!
  324. // }
  325. // else {
  326. // ViewController.imageTab1.image = UIImage(named: "tab_1_nexilis_off")!
  327. // }
  328. // if ViewController.isTab2 {
  329. // ViewController.imageTab2.image = UIImage(named: "tab_2_nexilis")!
  330. // }
  331. // else {
  332. // ViewController.imageTab2.image = UIImage(named: "tab_2_nexilis_off")!
  333. // }
  334. // if ViewController.isTab3 {
  335. // ViewController.imageTab3.image = UIImage(named: "tab_3_nexilis")!
  336. // }
  337. // else {
  338. // ViewController.imageTab3.image = UIImage(named: "tab_3_nexilis_off")!
  339. // }
  340. // if ViewController.isTab4 {
  341. // ViewController.imageTab4.image = UIImage(named: "tab_4_nexilis")!
  342. // }
  343. // else {
  344. // ViewController.imageTab4.image = UIImage(named: "tab_4_nexilis_off")!
  345. // }
  346. }
  347. override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
  348. let cpaasMode = PrefsUtil.getCpaasMode()
  349. let customTab = PrefsUtil.getCustomTab().split(separator: ",")
  350. if(cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX){
  351. if(customTab.count == 2){
  352. ViewController.isTab1 = item == tabBar.items?[0]
  353. ViewController.isTab2 = item == tabBar.items?[2]
  354. }
  355. else if(customTab.count == 3){
  356. ViewController.isTab1 = item == tabBar.items?[0]
  357. ViewController.isTab2 = item == tabBar.items?[2]
  358. ViewController.isTab3 = item == tabBar.items?[3]
  359. }
  360. else if(customTab.count == 4){
  361. ViewController.isTab1 = item == tabBar.items?[0]
  362. ViewController.isTab2 = item == tabBar.items?[1]
  363. ViewController.isTab3 = item == tabBar.items?[3]
  364. ViewController.isTab4 = item == tabBar.items?[4]
  365. }
  366. }
  367. else{
  368. ViewController.isTab1 = item == tabBar.items?[0]
  369. ViewController.isTab2 = item == tabBar.items?[1]
  370. if(customTab.count > 2){
  371. ViewController.isTab3 = item == tabBar.items?[2]
  372. }
  373. if(customTab.count > 3){
  374. ViewController.isTab4 = item == tabBar.items?[3]
  375. }
  376. }
  377. }
  378. func createMidFloatingButton(){
  379. var minYIpX: CGFloat = 0
  380. let iPhoneModel = ViewController.getiPhoneModel()
  381. if iPhoneModel == "iPhone X or newer" {
  382. minYIpX += 20
  383. }
  384. ViewController.chatButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: 45, height: 45))
  385. ViewController.chatButton.setBackgroundImage(UIImage(named: "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  386. ViewController.chatButton.layer.shadowColor = UIColor.black.cgColor
  387. ViewController.chatButton.layer.shadowOpacity = 0.1
  388. ViewController.chatButton.layer.shadowOffset = CGSize(width: 4, height: 4)
  389. ViewController.chatButton.addTarget(self, action: #selector(chatTap), for: .touchUpInside)
  390. ViewController.callButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: 45, height: 45))
  391. ViewController.callButton.setBackgroundImage(UIImage(named: "pb_button_call", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  392. ViewController.callButton.layer.shadowColor = UIColor.black.cgColor
  393. ViewController.callButton.layer.shadowOpacity = 0.1
  394. ViewController.callButton.layer.shadowOffset = CGSize(width: 4, height: 4)
  395. ViewController.callButton.addTarget(self, action: #selector(callTap), for: .touchUpInside)
  396. ViewController.ccButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: 45, height: 45))
  397. ViewController.ccButton.setBackgroundImage(UIImage(named: "pb_button_cc", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  398. ViewController.ccButton.layer.shadowColor = UIColor.black.cgColor
  399. ViewController.ccButton.layer.shadowOpacity = 0.1
  400. ViewController.ccButton.layer.shadowOffset = CGSize(width: 4, height: 4)
  401. ViewController.ccButton.addTarget(self, action: #selector(ccTap), for: .touchUpInside)
  402. ViewController.streamingButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: 45, height: 45))
  403. ViewController.streamingButton.setBackgroundImage(UIImage(named: "pb_button_stream", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  404. ViewController.streamingButton.layer.shadowColor = UIColor.black.cgColor
  405. ViewController.streamingButton.layer.shadowOpacity = 0.1
  406. ViewController.streamingButton.layer.shadowOffset = CGSize(width: 4, height: 4)
  407. ViewController.streamingButton.addTarget(self, action: #selector(streamTap), for: .touchUpInside)
  408. ViewController.postButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: 45, height: 45))
  409. ViewController.postButton.setBackgroundImage(UIImage(named: "pb_button_post", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  410. ViewController.postButton.layer.shadowColor = UIColor.black.cgColor
  411. ViewController.postButton.layer.shadowOpacity = 0.1
  412. ViewController.postButton.layer.shadowOffset = CGSize(width: 4, height: 4)
  413. ViewController.postButton.addTarget(self, action: #selector(postTap), for: .touchUpInside)
  414. let buttonCenterX = self.view.bounds.width / 2
  415. let buttonCenterY = self.view.bounds.height - self.tabBar.bounds.height
  416. //print("buttonCenterX \(buttonCenterX)")
  417. //print("buttonCenterY \(buttonCenterY)")
  418. ViewController.middleButton = UIButton(frame: CGRect(x: buttonCenterX - 40 , y: buttonCenterY - 40, width: 80, height: 80))
  419. if !PrefsUtil.getIconDock().isEmpty {
  420. if PrefsUtil.getIconDock().contains(".gif") {
  421. ViewController.middleButton.sd_setBackgroundImage(with: URL(string: PrefsUtil.getIconCenterAnim()!), for: .normal, completed: { (image, error, cacheType, imageURL) in
  422. if let error = error {
  423. print("Error loading image: \(error.localizedDescription)")
  424. } else {
  425. print("Image loaded successfully")
  426. }
  427. })
  428. } else {
  429. DispatchQueue.global().async {
  430. Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: PrefsUtil.getUrlDock()!)!) { data, response, error in
  431. guard let data = data, error == nil else { return }
  432. // always update the UI from the main thread
  433. DispatchQueue.main.async() {
  434. ViewController.middleButton.setBackgroundImage(UIImage(data: data), for: .normal)
  435. }
  436. }
  437. }
  438. }
  439. } else {
  440. ViewController.middleButton.setBackgroundImage(UIImage(named: "pb_button", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal)
  441. }
  442. ViewController.middleButton.layer.shadowColor = UIColor.black.cgColor
  443. ViewController.middleButton.layer.shadowOffset = CGSize(width: 0.0, height: 2.0)
  444. ViewController.middleButton.layer.shadowOpacity = 1.0
  445. ViewController.middleButton.layer.shadowRadius = 5.0
  446. ViewController.middleButton.layer.masksToBounds = false
  447. ViewController.middleButton.layer.cornerRadius = 4.0
  448. ViewController.middleButton.addTarget(self, action: #selector(middleBtnTapped), for: .touchUpInside)
  449. let longPressMidButton = UILongPressGestureRecognizer(target: self, action: #selector(longPressMidBtn(gestureRecognizer:)))
  450. ViewController.middleButton.addGestureRecognizer(longPressMidButton)
  451. self.view.addSubview(ViewController.chatButton)
  452. self.view.addSubview(ViewController.callButton)
  453. self.view.addSubview(ViewController.ccButton)
  454. self.view.addSubview(ViewController.postButton)
  455. self.view.addSubview(ViewController.streamingButton)
  456. self.view.addSubview(ViewController.middleButton)
  457. ViewController.hideDockedButton()
  458. }
  459. @objc func longPressMidBtn(gestureRecognizer: UILongPressGestureRecognizer) {
  460. if gestureRecognizer.state == .began {
  461. if self.viewControllers?.firstIndex(of: fourthTab!) == nil {
  462. let vc = fourthTab!
  463. vc.notInTab = true
  464. self.navigationController?.show(vc, sender: nil)
  465. } else {
  466. self.selectedIndex = (self.viewControllers?.firstIndex(of: fourthTab!))!
  467. }
  468. }
  469. }
  470. func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
  471. if(viewController == secondTab){
  472. if(!ViewController.checkIsChangePerson()){
  473. return false
  474. }
  475. }
  476. return true
  477. }
  478. func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
  479. if viewController != secondTab {
  480. let idxTabChat = self.viewControllers?.firstIndex(where: {$0 == secondTab})
  481. if idxTabChat != nil {
  482. let vcTabChats = self.viewControllers![idxTabChat!] as! SecondTabViewController
  483. if vcTabChats.searchController.isActive {
  484. vcTabChats.searchController.isActive = false
  485. }
  486. }
  487. }
  488. let cpaasMode = PrefsUtil.getCpaasMode()
  489. var childrenMenu = [UIAction]()
  490. if(cpaasMode == PrefsUtil.CPAAS_MODE_BURGER){
  491. //print("cpaas mode burger")
  492. childrenMenu.append(contentsOf: [
  493. UIAction(title: "Contact Center", handler: {[weak self](_) in
  494. self?.ccTap()
  495. }),
  496. UIAction(title: "Chat", handler: {[weak self](_) in
  497. self?.chatTap()
  498. }),
  499. UIAction(title: "Call", handler: {[weak self](_) in
  500. self?.callTap()
  501. }),
  502. UIAction(title: "New Post", handler: {[weak self](_) in
  503. self?.postTap()
  504. }),
  505. UIAction(title: "Live Streaming", handler: {[weak self](_) in
  506. self?.streamTap()
  507. }),
  508. // UIAction(title: "Settings", handler: {[weak self](_) in
  509. // self?.settingTap()
  510. // }),
  511. ])
  512. if let vc = viewController as? SecondTabViewController {
  513. childrenMenu.append(contentsOf: vc.childrenMenu)
  514. }
  515. let menu = UIMenu(title: "", children: childrenMenu)
  516. if !PrefsUtil.getIconDock().isEmpty {
  517. DispatchQueue.global().async {
  518. ViewController.getDataImageFromUrl(from: URL(string: PrefsUtil.getUrlDock()!)!) { data, response, error in
  519. guard let data = data, error == nil else { return }
  520. // always update the UI from the main thread
  521. DispatchQueue.main.async() { [self] in
  522. navigationItem.rightBarButtonItem = UIBarButtonItem(image: resizeImage(image: UIImage(data: data)!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), primaryAction: .none, menu: menu)
  523. }
  524. }
  525. }
  526. } else {
  527. navigationItem.rightBarButtonItem = UIBarButtonItem(image: resizeImage(image: UIImage(named: "pb_button", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), primaryAction: .none, menu: menu)
  528. }
  529. }
  530. }
  531. override func viewWillAppear(_ animated: Bool) {
  532. if !firstLoad {
  533. willappear()
  534. } else {
  535. firstLoad = false
  536. }
  537. }
  538. func willappear() {
  539. let acceptTerm = PrefsUtil.getTerms()
  540. let enable_privacy_policy = PrefsUtil.getEnablePrivacyPolicy()
  541. if !acceptTerm {
  542. showWelocomeView()
  543. return
  544. } else if enable_privacy_policy && !PrefsUtil.getAgreePrivacyPolicy() {
  545. showPrivacyPolicyView()
  546. return
  547. } else {
  548. if !Utils.getForceAnonymous() && !Utils.getSetProfile() {
  549. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "changeDevice") as! ChangeDeviceViewController
  550. controller.forceLogin = true
  551. let navigationController = UINavigationController(rootViewController: controller)
  552. navigationController.navigationBar.tintColor = .white
  553. navigationController.navigationBar.barTintColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  554. navigationController.navigationBar.isTranslucent = false
  555. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  556. navigationController.navigationBar.barStyle = .black
  557. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  558. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  559. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  560. navigationController.navigationBar.titleTextAttributes = textAttributes
  561. navigationController.view.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .black : .white
  562. navigationController.modalPresentationStyle = .fullScreen
  563. navigationController.modalTransitionStyle = .crossDissolve
  564. self.present(navigationController, animated: true)
  565. return
  566. }
  567. }
  568. self.selectedViewController?.viewWillAppear(false)
  569. }
  570. func showPrivacyPolicyView() {
  571. if let privacyView = privacyPolicyVC.view {
  572. let bgImage = UIImageView()
  573. privacyView.addSubview(bgImage)
  574. bgImage.anchor(top: privacyView.topAnchor, left: privacyView.leftAnchor, bottom: privacyView.bottomAnchor, right: privacyView.rightAnchor)
  575. bgImage.backgroundColor = .white
  576. DispatchQueue.global().async {
  577. DispatchQueue.main.async {
  578. let listBg = PrefsUtil.getBackgroundLight().isEmpty && PrefsUtil.getBackgroundDark().isEmpty ? PrefsUtil.getBackground() :
  579. self.traitCollection.userInterfaceStyle == .dark ? PrefsUtil.getBackgroundDark() : PrefsUtil.getBackgroundLight()
  580. if listBg.isEmpty {
  581. return
  582. }
  583. var bgChoosen = ""
  584. let arrayBg = listBg.split(separator: ",")
  585. bgChoosen = String(arrayBg[Int.random(in: 0..<arrayBg.count)])
  586. Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: PrefsUtil.getURLBase() + "get_file_from_path?img=" + bgChoosen)!) { data, response, error in
  587. guard let data = data, error == nil else { return }
  588. // always update the UI from the main thread
  589. DispatchQueue.main.async() {
  590. if UIImage(data: data) != nil {
  591. bgImage.image = UIImage(data: data)!
  592. }
  593. }
  594. }
  595. }
  596. }
  597. let containerButton = UIView()
  598. privacyView.addSubview(containerButton)
  599. containerButton.anchor(left: privacyView.safeAreaLayoutGuide.leftAnchor, bottom: privacyView.safeAreaLayoutGuide.bottomAnchor, paddingLeft: 10, paddingBottom: 10, minHeight: 40)
  600. containerButton.rightAnchor.constraint(lessThanOrEqualTo: privacyView.safeAreaLayoutGuide.rightAnchor, constant: -10).isActive = true
  601. containerButton.isUserInteractionEnabled = true
  602. let tapgestureAgree = UITapGestureRecognizer(target: self, action: #selector(tappedOnAgreePrivacy(_ :)))
  603. tapgestureAgree.numberOfTapsRequired = 1
  604. containerButton.addGestureRecognizer(tapgestureAgree)
  605. let imageAgree = UIImageView()
  606. imageAgree.image = UIImage(systemName: "arrow.forward.circle")
  607. imageAgree.tintColor = .black
  608. containerButton.addSubview(imageAgree)
  609. imageAgree.anchor(left: containerButton.leftAnchor, centerY: containerButton.centerYAnchor, width: 40, height: 40)
  610. let titleAgree = UILabel()
  611. titleAgree.text = "Agree and Continue".localized()
  612. titleAgree.textColor = .black
  613. containerButton.addSubview(titleAgree)
  614. titleAgree.anchor(left: imageAgree.rightAnchor, right: containerButton.rightAnchor, paddingLeft: 5, centerY: containerButton.centerYAnchor)
  615. privacyWV.isOpaque = false
  616. privacyWV.backgroundColor = UIColor.clear
  617. privacyWV.scrollView.backgroundColor = UIColor.clear
  618. //print("URL: \(PrefsUtil.getURLPrivacyPolicy())")
  619. let lang = UserDefaults.standard.string(forKey: "i18n_language")
  620. var urlPrivacyPolicy = PrefsUtil.getURLPrivacyPolicy()
  621. if lang == "id" {
  622. urlPrivacyPolicy = urlPrivacyPolicy.replacingOccurrences(of: "/en/", with: "/id/")
  623. }
  624. privacyWV.load(URLRequest(url: URL(string: urlPrivacyPolicy)!))
  625. privacyView.addSubview(privacyWV)
  626. privacyWV.navigationDelegate = self
  627. privacyWV.anchor(top: privacyView.safeAreaLayoutGuide.topAnchor, left: privacyView.leftAnchor, right: privacyView.rightAnchor, height: privacyView.bounds.height - 80)
  628. }
  629. privacyPolicyVC.modalPresentationStyle = .fullScreen
  630. privacyPolicyVC.modalTransitionStyle = .crossDissolve
  631. self.present(privacyPolicyVC, animated: true)
  632. }
  633. func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
  634. let js = "(function() { document.body.style.background='transparent'; })();"
  635. privacyWV.evaluateJavaScript(js) { (_, error) in
  636. //print(error as Any)
  637. }
  638. }
  639. func showWelocomeView() {
  640. if let viewWelcome = welcomeVC.view {
  641. let bgImage = UIImageView()
  642. viewWelcome.addSubview(bgImage)
  643. bgImage.anchor(top: viewWelcome.topAnchor, left: viewWelcome.leftAnchor, bottom: viewWelcome.bottomAnchor, right: viewWelcome.rightAnchor)
  644. bgImage.backgroundColor = .white
  645. DispatchQueue.global().async {
  646. DispatchQueue.main.async {
  647. let listBg = PrefsUtil.getBackgroundLight().isEmpty && PrefsUtil.getBackgroundDark().isEmpty ? PrefsUtil.getBackground() :
  648. self.traitCollection.userInterfaceStyle == .dark ? PrefsUtil.getBackgroundDark() : PrefsUtil.getBackgroundLight()
  649. if listBg.isEmpty {
  650. return
  651. }
  652. var bgChoosen = ""
  653. let arrayBg = listBg.split(separator: ",")
  654. bgChoosen = String(arrayBg[Int.random(in: 0..<arrayBg.count)])
  655. Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: PrefsUtil.getURLBase() + "get_file_from_path?img=" + bgChoosen)!) { data, response, error in
  656. guard let data = data, error == nil else { return }
  657. // always update the UI from the main thread
  658. DispatchQueue.main.async() {
  659. if UIImage(data: data) != nil {
  660. bgImage.image = UIImage(data: data)!
  661. }
  662. }
  663. }
  664. }
  665. }
  666. let welcomeTitle = UILabel()
  667. welcomeTitle.text = "Welcome to".localized() + " " + (Bundle.main.displayName ?? "")
  668. welcomeTitle.font = .systemFont(ofSize: 25, weight: .bold)
  669. welcomeTitle.numberOfLines = 0
  670. viewWelcome.addSubview(welcomeTitle)
  671. welcomeTitle.anchor(top: viewWelcome.safeAreaLayoutGuide.topAnchor, left: viewWelcome.safeAreaLayoutGuide.leftAnchor, right: viewWelcome.safeAreaLayoutGuide.rightAnchor, paddingTop: 10, paddingLeft: 10, paddingRight: 10)
  672. let logoImage = UIImageView()
  673. logoImage.image = UIImage(named: getHighResolutionAppIconName() ?? "")
  674. viewWelcome.addSubview(logoImage)
  675. logoImage.anchor(centerX: viewWelcome.centerXAnchor, centerY: viewWelcome.centerYAnchor, width: 200, height: 200)
  676. let containerButton = UIView()
  677. viewWelcome.addSubview(containerButton)
  678. containerButton.anchor(left: viewWelcome.safeAreaLayoutGuide.leftAnchor, bottom: viewWelcome.safeAreaLayoutGuide.bottomAnchor, paddingLeft: 10, paddingBottom: 10, minHeight: 40)
  679. containerButton.rightAnchor.constraint(lessThanOrEqualTo: viewWelcome.safeAreaLayoutGuide.rightAnchor, constant: -10).isActive = true
  680. containerButton.isUserInteractionEnabled = true
  681. let tapgestureAgree = UITapGestureRecognizer(target: self, action: #selector(tappedOnAgree(_ :)))
  682. tapgestureAgree.numberOfTapsRequired = 1
  683. containerButton.addGestureRecognizer(tapgestureAgree)
  684. let imageAgree = UIImageView()
  685. imageAgree.image = UIImage(systemName: "arrow.forward.circle")
  686. imageAgree.tintColor = self.traitCollection.userInterfaceStyle == .dark ? UIColor.white: UIColor.black
  687. containerButton.addSubview(imageAgree)
  688. imageAgree.anchor(left: containerButton.leftAnchor, centerY: containerButton.centerYAnchor, width: 40, height: 40)
  689. let titleAgree = UILabel()
  690. titleAgree.text = "Agree and Continue".localized()
  691. titleAgree.textColor = self.traitCollection.userInterfaceStyle == .dark ? UIColor.white: UIColor.black
  692. containerButton.addSubview(titleAgree)
  693. titleAgree.anchor(left: imageAgree.rightAnchor, right: containerButton.rightAnchor, paddingLeft: 5, centerY: containerButton.centerYAnchor)
  694. let formattedText = String.format(strings: [term], inString: termText, color: self.traitCollection.userInterfaceStyle == .dark ? UIColor.white: UIColor.black)
  695. welcomeDesc.isUserInteractionEnabled = true
  696. welcomeDesc.attributedText = formattedText
  697. welcomeDesc.numberOfLines = 0
  698. viewWelcome.addSubview(welcomeDesc)
  699. welcomeDesc.anchor(left: viewWelcome.safeAreaLayoutGuide.leftAnchor, bottom: containerButton.topAnchor, right: viewWelcome.rightAnchor, paddingLeft: 10, paddingBottom: 10, paddingRight: 10)
  700. let tapgesture = UITapGestureRecognizer(target: self, action: #selector(tappedOnLabelTerms(_ :)))
  701. tapgesture.numberOfTapsRequired = 1
  702. welcomeDesc.addGestureRecognizer(tapgesture)
  703. }
  704. welcomeVC.modalPresentationStyle = .fullScreen
  705. welcomeVC.modalTransitionStyle = .crossDissolve
  706. self.present(welcomeVC, animated: true)
  707. }
  708. func getHighResolutionAppIconName() -> String? {
  709. guard let infoPlist = Bundle.main.infoDictionary else { return nil }
  710. guard let bundleIcons = infoPlist["CFBundleIcons"] as? NSDictionary else { return nil }
  711. guard let bundlePrimaryIcon = bundleIcons["CFBundlePrimaryIcon"] as? NSDictionary else { return nil }
  712. guard let bundleIconFiles = bundlePrimaryIcon["CFBundleIconFiles"] as? NSArray else { return nil }
  713. guard let appIcon = bundleIconFiles.lastObject as? String else { return nil }
  714. return appIcon
  715. }
  716. func showWebviewTerm() {
  717. termVC = UIViewController()
  718. if let viewTerm = termVC!.view {
  719. let webView = WKWebView()
  720. let lang = UserDefaults.standard.string(forKey: "i18n_language")
  721. var urlTerm = "https://nexilis.io/newuniverse-tos"
  722. if lang == "id" {
  723. urlTerm = "https://nexilis.io/newuniverse-tos-id"
  724. }
  725. let url = URL (string: urlTerm)
  726. let requestObj = URLRequest(url: url!)
  727. webView.load(requestObj)
  728. viewTerm.addSubview(webView)
  729. webView.anchor(top: viewTerm.safeAreaLayoutGuide.topAnchor, left: viewTerm.safeAreaLayoutGuide.leftAnchor, bottom: viewTerm.safeAreaLayoutGuide.bottomAnchor, right: viewTerm.safeAreaLayoutGuide.rightAnchor)
  730. }
  731. let navigationController = UINavigationController(rootViewController: termVC!)
  732. navigationController.navigationBar.tintColor = .mainColor
  733. navigationController.navigationBar.barTintColor = .white
  734. navigationController.navigationBar.isTranslucent = false
  735. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.mainColor]
  736. navigationController.navigationBar.titleTextAttributes = textAttributes
  737. navigationController.view.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .black : .white
  738. termVC!.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Close".localized(), style: .plain, target: self, action: #selector(closeTerm))
  739. welcomeVC.present(navigationController, animated: true)
  740. }
  741. @objc func closeTerm() {
  742. termVC!.dismiss(animated: true)
  743. }
  744. @objc func tappedOnLabelTerms(_ gesture: UITapGestureRecognizer) {
  745. let termString = termText as NSString
  746. let termRange = termString.range(of: term)
  747. let tapLocation = gesture.location(in: welcomeDesc)
  748. let index = welcomeDesc.indexOfAttributedTextCharacterAtPoint(point: tapLocation)
  749. if checkRange(termRange, contain: index) == true {
  750. showWebviewTerm()
  751. return
  752. }
  753. }
  754. @objc func tappedOnAgree(_ gesture: UITapGestureRecognizer) {
  755. PrefsUtil.setTerms(value: true)
  756. welcomeVC.dismiss(animated: true)
  757. }
  758. @objc func tappedOnAgreePrivacy(_ gesture: UITapGestureRecognizer) {
  759. PrefsUtil.setAgreePrivacyPolicy(value: true)
  760. privacyPolicyVC.dismiss(animated: true)
  761. }
  762. func checkRange(_ range: NSRange, contain index: Int) -> Bool {
  763. return index > range.location && index < range.location + range.length
  764. }
  765. @objc func middleBtnTapped() {
  766. ViewController.expandButton()
  767. }
  768. public func show(b: Bool) {
  769. if(!b){
  770. if(ViewController.isExpandButton){
  771. ViewController.expandButton()
  772. }
  773. }
  774. }
  775. @objc func ccTap() {
  776. //print("ccTap")
  777. if(ViewController.checkIsChangePerson()){
  778. show(b: false)
  779. ViewController.def?.thirdTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  780. ViewController.def?.firstTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  781. if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 2 {
  782. let package_id = ViewController.listPullFB[2].split(separator: "|")[0]
  783. var app_id = ""
  784. if package_id.contains("_fb") {
  785. let listSplit = package_id.split(separator: "_", maxSplits: 1)
  786. let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0]
  787. let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
  788. if listSplit.count == 2 {
  789. app_id = String(listSplit[1])
  790. }
  791. if indexTap == 99 {
  792. openTabPost()
  793. } else {
  794. Nexilis.buttonClicked(index: indexTap, id: app_id)
  795. }
  796. } else {
  797. if !app_id.isEmpty {
  798. Nexilis.buttonClicked(index: 0, id: app_id)
  799. }
  800. }
  801. } else {
  802. Nexilis.buttonClicked(index: 9)
  803. }
  804. }
  805. }
  806. @objc func streamTap() {
  807. //print("streamTap")
  808. if(ViewController.checkIsChangePerson()){
  809. show(b: false)
  810. ViewController.def?.thirdTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  811. ViewController.def?.firstTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  812. if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 4 {
  813. let package_id = ViewController.listPullFB[4].split(separator: "|")[0]
  814. var app_id = ""
  815. if package_id.contains("_fb") {
  816. let listSplit = package_id.split(separator: "_", maxSplits: 1)
  817. let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0]
  818. let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
  819. if listSplit.count == 2 {
  820. app_id = String(listSplit[1])
  821. }
  822. if indexTap == 99 {
  823. openTabPost()
  824. } else {
  825. Nexilis.buttonClicked(index: indexTap, id: app_id)
  826. }
  827. } else {
  828. if !app_id.isEmpty {
  829. Nexilis.buttonClicked(index: 0, id: app_id)
  830. }
  831. }
  832. } else {
  833. Nexilis.buttonClicked(index: 8)
  834. }
  835. }
  836. }
  837. @objc func callTap() {
  838. //print("callTap")
  839. if(ViewController.checkIsChangePerson()){
  840. show(b: false)
  841. ViewController.def?.thirdTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  842. ViewController.def?.firstTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  843. if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 1 {
  844. let package_id = ViewController.listPullFB[1].split(separator: "|")[0]
  845. var app_id = ""
  846. if package_id.contains("_fb") {
  847. let listSplit = package_id.split(separator: "_", maxSplits: 1)
  848. let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0]
  849. let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
  850. if listSplit.count == 2 {
  851. app_id = String(listSplit[1])
  852. }
  853. if indexTap == 99 {
  854. openTabPost()
  855. } else {
  856. Nexilis.buttonClicked(index: indexTap, id: app_id)
  857. }
  858. } else {
  859. if !app_id.isEmpty {
  860. Nexilis.buttonClicked(index: 0, id: app_id)
  861. }
  862. }
  863. } else {
  864. Nexilis.buttonClicked(index: 7)
  865. }
  866. }
  867. }
  868. @objc func chatTap() {
  869. //print("chatTap")
  870. // APIS.openWhiteboard()
  871. // return
  872. if(ViewController.checkIsChangePerson()){
  873. show(b: false)
  874. ViewController.def?.thirdTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  875. ViewController.def?.firstTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  876. if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 0 {
  877. let package_id = ViewController.listPullFB[0].split(separator: "|")[0]
  878. var app_id = ""
  879. if package_id.contains("_fb") {
  880. let listSplit = package_id.split(separator: "_", maxSplits: 1)
  881. let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0]
  882. let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
  883. if listSplit.count == 2 {
  884. app_id = String(listSplit[1])
  885. }
  886. if indexTap == 99 {
  887. openTabPost()
  888. } else {
  889. Nexilis.buttonClicked(index: indexTap, id: app_id)
  890. }
  891. } else {
  892. if !app_id.isEmpty {
  893. Nexilis.buttonClicked(index: 0, id: app_id)
  894. }
  895. }
  896. } else {
  897. Nexilis.buttonClicked(index: 6)
  898. }
  899. }
  900. }
  901. @objc func postTap() {
  902. if(ViewController.checkIsChangePerson()){
  903. show(b: false)
  904. ViewController.def?.thirdTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  905. ViewController.def?.firstTab?.webView?.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  906. if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 3 {
  907. let package_id = ViewController.listPullFB[3].split(separator: "|")[0]
  908. var app_id = ""
  909. if package_id.contains("_fb") {
  910. let listSplit = package_id.split(separator: "_", maxSplits: 1)
  911. let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0]
  912. let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))!
  913. if listSplit.count == 2 {
  914. app_id = String(listSplit[1])
  915. }
  916. if indexTap == 99 {
  917. openTabPost()
  918. } else {
  919. Nexilis.buttonClicked(index: indexTap, id: app_id)
  920. }
  921. } else {
  922. if !app_id.isEmpty {
  923. Nexilis.buttonClicked(index: 0, id: app_id)
  924. }
  925. }
  926. } else {
  927. openTabPost()
  928. }
  929. }
  930. }
  931. func openTabPost() {
  932. let customTab = PrefsUtil.getCustomTab().split(separator: ",")
  933. let cpaasMode = PrefsUtil.getCpaasMode()
  934. var i = 0
  935. var j = 0
  936. //print("custom tab post tap = \(customTab)")
  937. while j < customTab.count {
  938. if(((i == 1 && customTab.count == 3) || i == 2) &&
  939. (cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)){
  940. }
  941. else {
  942. if customTab[j] == "3" {
  943. break
  944. }
  945. j += 1
  946. }
  947. i += 1
  948. }
  949. if(j < customTab.count){
  950. self.selectedIndex = i
  951. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(1), execute: {
  952. let me = UserDefaults.standard.string(forKey: "me")
  953. let address = "\(PrefsUtil.getURLBase())nexilis/pages/tab5-new-post?f_pin=\(me ?? "")"
  954. self.thirdTab?.webView.evaluateJavaScript("{window.localStorage.setItem('currentTab','\(ViewController.tab3)')}")
  955. self.thirdTab?.webView.evaluateJavaScript("window.location = '\(address)'")
  956. })
  957. }
  958. }
  959. static func pullActionButton() {
  960. if datePullFB == nil || Int(Date().timeIntervalSince(datePullFB!)) >= 60 {
  961. datePullFB = Date()
  962. DispatchQueue.global().async {
  963. if !PrefsUtil.getCustomButtons().isEmpty {
  964. DispatchQueue.main.async { [self] in
  965. let customButtons = PrefsUtil.getCustomButtons().components(separatedBy: ",")
  966. let customIcons = PrefsUtil.getCustomFBIcon().components(separatedBy: ",")
  967. for i in 0..<customButtons.count {
  968. let package_id = customButtons[i]
  969. let app_id = ""
  970. let icon = customIcons[i]
  971. listPullFB.append("\(package_id)|\(app_id)")
  972. DispatchQueue.global().async {
  973. ViewController.getDataImageFromUrl(from: URL(string: PrefsUtil.getURLBase() + "get_file_from_path?img=\(icon)")!) { data, response, error in
  974. guard let data = data, error == nil else { return }
  975. // always update the UI from the main thread
  976. DispatchQueue.main.async() {
  977. if i == 0 {
  978. ViewController.chatButton.setBackgroundImage(UIImage(data: data), for: .normal)
  979. } else if i == 1 {
  980. ViewController.callButton.setBackgroundImage(UIImage(data: data), for: .normal)
  981. } else if i == 2 {
  982. ViewController.ccButton.setBackgroundImage(UIImage(data: data), for: .normal)
  983. } else if i == 3 {
  984. ViewController.postButton.setBackgroundImage(UIImage(data: data), for: .normal)
  985. } else if i == 4 {
  986. ViewController.streamingButton.setBackgroundImage(UIImage(data: data), for: .normal)
  987. }
  988. }
  989. }
  990. }
  991. }
  992. }
  993. return
  994. }
  995. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.pullFloatingButton(), timeout: 30 * 1000) {
  996. if response.isOk() {
  997. let data = response.getBody(key: CoreMessage_TMessageKey.DATA, default_value: "")
  998. if !data.isEmpty {
  999. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  1000. DispatchQueue.main.async { [self] in
  1001. listPullFB.removeAll()
  1002. if jsonArray.count != 0 {
  1003. var count = 0
  1004. for json in jsonArray {
  1005. let package_id = json["package_act"] as! String
  1006. let app_id = (json["app_id"] as? String) ?? ""
  1007. let icon = (json["icon"] as? String) ?? ""
  1008. listPullFB.append("\(package_id)|\(app_id)")
  1009. if count == 0 {
  1010. if !icon.isEmpty {
  1011. DispatchQueue.global().async {
  1012. ViewController.getDataImageFromUrl(from: URL(string: "https://nexilis.io/get_file?account=\(Nexilis.sAPIKey)&image=\(icon)")!) { data, response, error in
  1013. guard let data = data, error == nil else { return }
  1014. // always update the UI from the main thread
  1015. DispatchQueue.main.async() {
  1016. ViewController.chatButton.setBackgroundImage(UIImage(data: data), for: .normal)
  1017. }
  1018. }
  1019. }
  1020. } else {
  1021. ViewController.chatButton.setBackgroundImage(UIImage(named: "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  1022. }
  1023. } else if count == 1 {
  1024. if !icon.isEmpty {
  1025. DispatchQueue.global().async {
  1026. ViewController.getDataImageFromUrl(from: URL(string: "https://nexilis.io/get_file?account=\(Nexilis.sAPIKey)&image=\(icon)")!) { data, response, error in
  1027. guard let data = data, error == nil else { return }
  1028. // always update the UI from the main thread
  1029. DispatchQueue.main.async() {
  1030. ViewController.callButton.setBackgroundImage(UIImage(data: data), for: .normal)
  1031. }
  1032. }
  1033. }
  1034. } else {
  1035. ViewController.callButton.setBackgroundImage(UIImage(named: "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  1036. }
  1037. } else if count == 2 {
  1038. if !icon.isEmpty {
  1039. DispatchQueue.global().async {
  1040. ViewController.getDataImageFromUrl(from: URL(string: "https://nexilis.io/get_file?account=\(Nexilis.sAPIKey)&image=\(icon)")!) { data, response, error in
  1041. guard let data = data, error == nil else { return }
  1042. // always update the UI from the main thread
  1043. DispatchQueue.main.async() {
  1044. ViewController.ccButton.setBackgroundImage(UIImage(data: data), for: .normal)
  1045. }
  1046. }
  1047. }
  1048. } else {
  1049. ViewController.ccButton.setBackgroundImage(UIImage(named: "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  1050. }
  1051. } else if count == 3 {
  1052. if !icon.isEmpty {
  1053. DispatchQueue.global().async {
  1054. ViewController.getDataImageFromUrl(from: URL(string: "https://nexilis.io/get_file?account=\(Nexilis.sAPIKey)&image=\(icon)")!) { data, response, error in
  1055. guard let data = data, error == nil else { return }
  1056. // always update the UI from the main thread
  1057. DispatchQueue.main.async() {
  1058. ViewController.postButton.setBackgroundImage(UIImage(data: data), for: .normal)
  1059. }
  1060. }
  1061. }
  1062. } else {
  1063. ViewController.postButton.setBackgroundImage(UIImage(named: "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  1064. }
  1065. } else if count == 4 {
  1066. if !icon.isEmpty {
  1067. DispatchQueue.global().async {
  1068. ViewController.getDataImageFromUrl(from: URL(string: "https://nexilis.io/get_file?account=\(Nexilis.sAPIKey)&image=\(icon)")!) { data, response, error in
  1069. guard let data = data, error == nil else { return }
  1070. // always update the UI from the main thread
  1071. DispatchQueue.main.async() {
  1072. ViewController.streamingButton.setBackgroundImage(UIImage(data: data), for: .normal)
  1073. }
  1074. }
  1075. }
  1076. } else {
  1077. ViewController.streamingButton.setBackgroundImage(UIImage(named: "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal)
  1078. }
  1079. }
  1080. count += 1
  1081. }
  1082. }
  1083. }
  1084. }
  1085. }
  1086. }
  1087. }
  1088. }
  1089. }
  1090. }
  1091. public static func showDockedButton() {
  1092. ViewController.chatButton.isHidden = false
  1093. ViewController.callButton.isHidden = false
  1094. ViewController.ccButton.isHidden = false
  1095. ViewController.streamingButton.isHidden = false
  1096. ViewController.postButton.isHidden = false
  1097. }
  1098. public static func hideDockedButton() {
  1099. ViewController.chatButton.isHidden = true
  1100. ViewController.callButton.isHidden = true
  1101. ViewController.ccButton.isHidden = true
  1102. ViewController.streamingButton.isHidden = true
  1103. ViewController.postButton.isHidden = true
  1104. }
  1105. public static func expandButton() {
  1106. let cpaasMode = PrefsUtil.getCpaasMode()
  1107. if cpaasMode != PrefsUtil.CPAAS_MODE_DOCKED && cpaasMode != PrefsUtil.CPAAS_MODE_MIX {
  1108. return
  1109. }
  1110. if ViewController.alwaysHideButton && !ViewController.isExpandButton {
  1111. return
  1112. }
  1113. var minYIpX: CGFloat = 0
  1114. let iPhoneModel = getiPhoneModel()
  1115. if iPhoneModel == "iPhone X or newer" {
  1116. minYIpX += 20
  1117. }
  1118. if ViewController.isExpandButton {
  1119. ViewController.isExpandButton = false
  1120. let xChatPosition = ViewController.chatButton.frame.origin.x + 90
  1121. let yChatPosition = ViewController.chatButton.frame.origin.y + 20
  1122. let xCallPosition = ViewController.callButton.frame.origin.x + 55
  1123. let yCallPosition = ViewController.callButton.frame.origin.y + 70
  1124. let xCCPosition = ViewController.ccButton.frame.origin.x
  1125. let yCCPosition = ViewController.ccButton.frame.origin.y + 90
  1126. let xPostPosition = ViewController.postButton.frame.origin.x - 55
  1127. let yPostPosition = ViewController.postButton.frame.origin.y + 70
  1128. let xStreamingPosition = ViewController.streamingButton.frame.origin.x - 90
  1129. let yStreamingPosition = ViewController.streamingButton.frame.origin.y + 20
  1130. UIView.animate(withDuration: 0.5, animations: {
  1131. // if !ViewController.isBlue {
  1132. // ViewController.middleButton.transform = CGAffineTransform(rotationAngle: 0)
  1133. // }
  1134. ViewController.chatButton.frame.origin = CGPoint(x: xChatPosition, y: yChatPosition + minYIpX)
  1135. ViewController.callButton.frame.origin = CGPoint(x: xCallPosition, y: yCallPosition + minYIpX)
  1136. ViewController.ccButton.frame.origin = CGPoint(x: xCCPosition, y: yCCPosition + minYIpX)
  1137. ViewController.streamingButton.frame.origin = CGPoint(x: xStreamingPosition, y: yStreamingPosition + minYIpX)
  1138. ViewController.postButton.frame.origin = CGPoint(x: xPostPosition, y: yPostPosition + minYIpX)
  1139. })
  1140. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
  1141. if !ViewController.isExpandButton {
  1142. ViewController.hideDockedButton()
  1143. }
  1144. })
  1145. } else {
  1146. ViewController.isExpandButton = true
  1147. ViewController.showDockedButton()
  1148. let xChatPosition = ViewController.chatButton.frame.origin.x - 90
  1149. let yChatPosition = ViewController.chatButton.frame.origin.y - 20
  1150. let xCallPosition = ViewController.callButton.frame.origin.x - 55
  1151. let yCallPosition = ViewController.callButton.frame.origin.y - 70
  1152. let xCCPosition = ViewController.ccButton.frame.origin.x
  1153. let yCCPosition = ViewController.ccButton.frame.origin.y - 90
  1154. let xPostPosition = ViewController.postButton.frame.origin.x + 55
  1155. let yPostPosition = ViewController.postButton.frame.origin.y - 70
  1156. let xStreamingPosition = ViewController.streamingButton.frame.origin.x + 90
  1157. let yStreamingPosition = ViewController.streamingButton.frame.origin.y - 20
  1158. UIView.animate(withDuration: 0.5, animations: {
  1159. // if !ViewController.isBlue{
  1160. // ViewController.middleButton.transform = CGAffineTransform(rotationAngle: .pi / 2)
  1161. // }
  1162. ViewController.chatButton.frame.origin = CGPoint(x: xChatPosition, y: yChatPosition - minYIpX)
  1163. ViewController.callButton.frame.origin = CGPoint(x: xCallPosition, y: yCallPosition - minYIpX)
  1164. ViewController.ccButton.frame.origin = CGPoint(x: xCCPosition, y: yCCPosition - minYIpX)
  1165. ViewController.streamingButton.frame.origin = CGPoint(x: xStreamingPosition, y: yStreamingPosition - minYIpX)
  1166. ViewController.postButton.frame.origin = CGPoint(x: xPostPosition, y: yPostPosition - minYIpX)
  1167. })
  1168. }
  1169. }
  1170. public static func removeMiddleButton() {
  1171. // ViewController.chatButton.removeFromSuperview()
  1172. // ViewController.callButton.removeFromSuperview()
  1173. // ViewController.ccButton.removeFromSuperview()
  1174. // ViewController.streamingButton.removeFromSuperview()
  1175. // ViewController.postButton.removeFromSuperview()
  1176. ViewController.middleButton.isHidden = true
  1177. }
  1178. public static func getDataImageFromUrl(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
  1179. URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
  1180. }
  1181. }
  1182. class EmptyTabViewController: UIViewController {
  1183. override func viewDidLoad() {
  1184. }
  1185. }
  1186. extension Bundle {
  1187. // Name of the app - title under the icon.
  1188. var displayName: String? {
  1189. return object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ??
  1190. object(forInfoDictionaryKey: "CFBundleName") as? String
  1191. }
  1192. }
  1193. extension BinaryInteger {
  1194. var degreesToRadians: CGFloat { CGFloat(self) * .pi / 180 }
  1195. }
  1196. extension FloatingPoint {
  1197. var degreesToRadians: Self { self * .pi / 180 }
  1198. var radiansToDegrees: Self { self * 180 / .pi }
  1199. }
  1200. extension UIImage {
  1201. class func imageWithColor(color: UIColor, size: CGSize) -> UIImage {
  1202. let rect: CGRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
  1203. UIGraphicsBeginImageContextWithOptions(size, false, 0)
  1204. color.setFill()
  1205. UIRectFill(rect)
  1206. let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
  1207. UIGraphicsEndImageContext()
  1208. return image
  1209. }
  1210. }
  1211. extension String {
  1212. static func format(strings: [String],
  1213. italicFont: UIFont = UIFont.italicSystemFont(ofSize: 12),
  1214. italicColor: UIColor = UIColor.systemGreen,
  1215. inString string: String,
  1216. font: UIFont = UIFont.systemFont(ofSize: 12),
  1217. color: UIColor = UIColor.black) -> NSAttributedString {
  1218. let attributedString =
  1219. NSMutableAttributedString(string: string,
  1220. attributes: [
  1221. NSAttributedString.Key.font: font,
  1222. NSAttributedString.Key.foregroundColor: color])
  1223. let italicFontAttribute = [NSAttributedString.Key.font: italicFont, NSAttributedString.Key.foregroundColor: italicColor]
  1224. for italic in strings {
  1225. attributedString.addAttributes(italicFontAttribute, range: (string as NSString).range(of: italic))
  1226. }
  1227. return attributedString
  1228. }
  1229. }
  1230. extension UILabel {
  1231. func indexOfAttributedTextCharacterAtPoint(point: CGPoint) -> Int {
  1232. assert(self.attributedText != nil, "This method is developed for attributed string")
  1233. let textStorage = NSTextStorage(attributedString: self.attributedText!)
  1234. let layoutManager = NSLayoutManager()
  1235. textStorage.addLayoutManager(layoutManager)
  1236. let textContainer = NSTextContainer(size: self.frame.size)
  1237. textContainer.lineFragmentPadding = 0
  1238. textContainer.maximumNumberOfLines = self.numberOfLines
  1239. textContainer.lineBreakMode = self.lineBreakMode
  1240. layoutManager.addTextContainer(textContainer)
  1241. let index = layoutManager.characterIndex(for: point, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
  1242. return index
  1243. }
  1244. }