ViewController.swift 84 KB

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