ViewController.swift 74 KB

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