// // ViewController.swift // TestQmeraLite // // Created by Qindi on 29/11/21. // import UIKit import NexilisLite import AVKit import AVFoundation import SwiftUI import Speech import Alamofire import WebKit class ViewController: UITabBarController, UITabBarControllerDelegate, SettingMABDelegate, WKNavigationDelegate { let playerController = AVPlayerViewController() static var sURL = "https://www.google.com" static var tab3 = "0" public var isShow: Bool = false public static var chatButton = UIButton() public static var callButton = UIButton() public static var ccButton = UIButton() public static var streamingButton = UIButton() public static var postButton = UIButton() public static var middleButton = UIButton() var buttonChatGR : UITapGestureRecognizer? var buttonCallGR : UITapGestureRecognizer? var buttonCCGR : UITapGestureRecognizer? var buttonStreamGR : UITapGestureRecognizer? var floating : FloatingButton? var firstTab : UINavigationController? var secondTab : UINavigationController? var thirdTab : UINavigationController? var fourthTab : UINavigationController? var callTab : UINavigationController? var chatWATab : UINavigationController? var communityTab : UINavigationController? var secureFolderTab : UINavigationController? var statusUpdateTab : UINavigationController? let emptyTab = EmptyTabViewController() public static var isTab1 = true public static var isTab2 = false public static var isTab3 = false public static var isTab4 = false public static var isTabCall = false public static var isExpandButton = false public static var alwaysHideButton = false static var listPullFB: [String] = [] static var datePullFB: Date? let welcomeVC = UIViewController() let privacyPolicyVC = UIViewController() var termVC: UIViewController? let welcomeDesc = UILabel() let termText = "Read our Terms of Service. Tap \"Agree and Continue\" to accept Terms of Service.".localized() let notifDisclaim = "Enabling notifications ensures you receive important updates, alerts, and reminders from our app. By turning on notifications, you agree to receive push notifications related to app features, promotions, and relevant updates.".localized() let term = "Terms of Service.".localized() var firstLoad = true let privacyWV = WKWebView() let indicatorCounterFB = UIView() let labelCounterFB = UILabel() var indicatorView : UIView! var indicatorImage : UIImageView! var imageIndicator: UIImage! var isDefaultIndicator = false public static var def: ViewController? override func viewDidLoad() { super.viewDidLoad() DispatchQueue.main.async { [self] in while !Utils.getFinishInitPrefsr() || HTTPCookieStorage.shared.cookies(for: URL(string: Utils.getDomainOpr())!)!.count == 0 { Thread.sleep(forTimeInterval: 1) } startView() } } override func viewDidDisappear(_ animated: Bool) { Nexilis.floatingButton.hideButton() Utils.randomizeBackground(view: self.navigationController?.view) } func startView() { navigationController?.view.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .black : .white Utils.addBackground(view: self.navigationController?.view) let topBorder = CALayer() topBorder.backgroundColor = UIColor.borderTabColor.cgColor topBorder.frame = CGRect(x: 0, y: 0, width: tabBar.frame.size.width, height: 1) tabBar.layer.addSublayer(topBorder) ViewController.def = self title = Bundle.main.displayName let customTab = PrefsUtil.getCustomTab().split(separator: ",") let cpaasMode = PrefsUtil.getCpaasMode() var tabs : [UIViewController] = [] firstTab = UINavigationController(rootViewController: FirstTabViewController()) secondTab = UINavigationController(rootViewController: SecondTabViewController()) thirdTab = UINavigationController(rootViewController: ThirdTabViewController()) fourthTab = UINavigationController(rootViewController: FourthTabViewController()) callTab = UINavigationController(rootViewController: CallLogVC()) chatWATab = UINavigationController(rootViewController: ChatWALikeVC()) communityTab = UINavigationController(rootViewController: CommunityList()) secureFolderTab = UINavigationController(rootViewController: SecureFolderViewController(isTab: true)) statusUpdateTab = UINavigationController(rootViewController: StatusUpdateVC()) self.delegate = self 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)) 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)) 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)) 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)) callTab?.tabBarItem = UITabBarItem(title: "", image: resizeImage(image: self.traitCollection.userInterfaceStyle == .dark ? UIImage(named: "tab_6_icon")!.withTintColor(.white) : UIImage(named: "tab_6_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal), selectedImage: resizeImage(image: UIImage(named: "tab_6_icon")!, targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysOriginal).withTintColor(self.traitCollection.userInterfaceStyle == .dark ? .lightGray : .mainColor)) chatWATab?.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)) communityTab?.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)) secureFolderTab?.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)) statusUpdateTab?.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)) var i = 0 var j = 0 while j < customTab.count { if(((i == 1 && customTab.count == 3) || i == 2) && (cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)){ tabs.append(emptyTab) } else { switch(customTab[j]){ case "1": tabs.append(firstTab!) case "2": tabs.append(secondTab!) case "3": tabs.append(thirdTab!) case "4": tabs.append(fourthTab!) case "5": tabs.append(secureFolderTab!) case "6": tabs.append(callTab!) case "16": tabs.append(communityTab!) case "17": tabs.append(statusUpdateTab!) case "18": tabs.append(chatWATab!) default: break } j += 1 } i += 1 } DispatchQueue.global().async { if !Utils.getTab1Icon().isEmpty { let urlString = "\(PrefsUtil.getURLBase())get_file_from_path?img=\(Utils.getTab1Icon())" if let cachedImage = ImageCache.shared.image(forKey: urlString) { DispatchQueue.main.async() { 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)) } } else { Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: urlString)!) { data, response, error in guard let data = data, error == nil else { return } // always update the UI from the main thread DispatchQueue.main.async() { [self] in if UIImage(data: data) != nil { 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)) ImageCache.shared.save(image: UIImage(data: data)!, forKey: urlString) } } } } } if !Utils.getTab2Icon().isEmpty && tabs.count > 1 { let urlString = "\(PrefsUtil.getURLBase())get_file_from_path?img=\(Utils.getTab2Icon())" if let cachedImage = ImageCache.shared.image(forKey: urlString) { DispatchQueue.main.async() { [self] in 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)) } } else { Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: urlString)!) { data, response, error in guard let data = data, error == nil else { return } // always update the UI from the main thread DispatchQueue.main.async() { [self] in if UIImage(data: data) != nil { 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)) ImageCache.shared.save(image: UIImage(data: data)!, forKey: urlString) } } } } } if !Utils.getTab3Icon().isEmpty && tabs.count > 2 { let urlString = "\(PrefsUtil.getURLBase())get_file_from_path?img=\(Utils.getTab3Icon())" if let cachedImage = ImageCache.shared.image(forKey: urlString) { DispatchQueue.main.async() { [self] in if cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX { 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)) } else { 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)) } } } else { Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: urlString)!) { data, response, error in guard let data = data, error == nil else { return } // always update the UI from the main thread DispatchQueue.main.async() { [self] in if UIImage(data: data) != nil { if cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX { 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)) } else { 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)) } ImageCache.shared.save(image: UIImage(data: data)!, forKey: urlString) } } } } } if !Utils.getTab4Icon().isEmpty && tabs.count > 3 { let urlString = "\(PrefsUtil.getURLBase())get_file_from_path?img=\(Utils.getTab4Icon())" if let cachedImage = ImageCache.shared.image(forKey: urlString) { DispatchQueue.main.async() { [self] in if cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX { 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)) } else { 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)) } } } else { Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: urlString)!) { data, response, error in guard let data = data, error == nil else { return } // always update the UI from the main thread DispatchQueue.main.async() { [self] in if UIImage(data: data) != nil { if cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX { 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)) } else { 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)) } ImageCache.shared.save(image: UIImage(data: data)!, forKey: urlString) } } } } } } if((cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)){ createMidFloatingButton() navigationController?.setNavigationBarHidden(true, animated: false) ViewController.pullActionButton() } // if((cpaasMode == PrefsUtil.CPAAS_MODE_FLOATING || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)) { // let rect = CGRect(x: self.view.bounds.width - 100, y: self.view.bounds.height / 2, width: 50, height: 250) // floating = FloatingButton() // floating?.frame = rect // floating?.isShow = true // // view.addSubview(floating!) // navigationController?.setNavigationBarHidden(true, animated: false) // } self.setViewControllers(tabs, animated: false) self.selectedIndex = Utils.getLastTabSelected() if(cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX){ if(customTab.count == 3){ self.tabBar.items?[1].isEnabled = false } self.tabBar.items?[2].isEnabled = false } let center: NotificationCenter = NotificationCenter.default center.addObserver(self, selector: #selector(checkCounter), name: NSNotification.Name(rawValue: Nexilis.listenerReceiveChat), object: nil) center.addObserver(self, selector: #selector(checkCounter), name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil) if #unavailable(iOS 26.0) { if !Utils.getIndicatorTabImage().isEmpty { let indicatorImage = Utils.getIndicatorTabImage() let fullUrl = "\(PrefsUtil.getURLBase())get_file_from_path?img=\(indicatorImage)" if let cachedImage = ImageCache.shared.image(forKey: fullUrl) { DispatchQueue.main.async() { [self] in imageIndicator = cachedImage addCustomViewAboveTabBarItem(at: Utils.getLastTabSelected(), image: imageIndicator) } } else { Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: fullUrl)!) { data, response, error in guard let data = data, error == nil else { return } // always update the UI from the main thread DispatchQueue.main.async() { [self] in if UIImage(data: data) != nil { imageIndicator = UIImage(data: data)! addCustomViewAboveTabBarItem(at: Utils.getLastTabSelected(), image: imageIndicator) ImageCache.shared.save(image: UIImage(data: data)!, forKey: fullUrl) } } } } } else { isDefaultIndicator = true imageIndicator = UIImage(named: "indicator_default_tab")! addCustomViewAboveTabBarItem(at: Utils.getLastTabSelected(), image: imageIndicator) } } DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: { [self] in checkCounter() }) willappear() let notificationName = "realtimeShareExtensionNexilis" as CFString CFNotificationCenterAddObserver( CFNotificationCenterGetDarwinNotifyCenter(), nil, { _, _, _, _, _ in APIS.checkDataForShareExtension() }, notificationName, nil, .deliverImmediately ) // Nexilis.debugBroadcast() } func addCustomViewAboveTabBarItem(at index: Int, image: UIImage?) { guard let tabBarItems = tabBar.items, index < tabBarItems.count else { return } let tabBarFrame = tabBar.frame let tabBarItemWidth = tabBarFrame.width / CGFloat(tabBarItems.count) let multiplierValue: CGFloat = CGFloat(index + index + 1) let xCenter = tabBarItemWidth * multiplierValue / 2 - 20 if image != nil { indicatorImage = UIImageView(image: image) indicatorImage.contentMode = .scaleAspectFit if isDefaultIndicator { indicatorImage.frame = CGRect(x: xCenter - 10, y: -5, width: 60, height: 60) } else { indicatorImage.frame = CGRect(x: xCenter, y: 5, width: 40, height: 40) } tabBar.addSubview(indicatorImage) tabBar.sendSubviewToBack(indicatorImage) } } static func getiPhoneModel() -> String { var systemInfo = utsname() uname(&systemInfo) let machineMirror = Mirror(reflecting: systemInfo.machine) let identifier = machineMirror.children.reduce("") { identifier, element in guard let value = element.value as? Int8, value != 0 else { return identifier } return identifier + String(UnicodeScalar(UInt8(value))) } var model = "" if let modelName = mapToDevice(identifier: identifier) { model = modelName } else { model = "Unknown" } return model } static func mapToDevice(identifier: String) -> String? { // Add mappings for iPhone models as needed switch identifier { 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" default: return "iPhone X or newer" } } @objc func checkCounter() { DispatchQueue.global().async { DispatchQueue.main.async { [self] in if self.viewControllers?.firstIndex(of: secondTab!) != nil { let counter = APIS.getTotalCounter() let indexSecondTab = self.viewControllers?.firstIndex(of: secondTab!) if counter > 0 { if !indicatorCounterFB.isDescendant(of: tabBar) { guard let tabBarItems = tabBar.items, let index = indexSecondTab else { return } let tabBarFrame = tabBar.frame let tabBarItemWidth = tabBarFrame.width / CGFloat(tabBarItems.count) let multiplierValue: CGFloat = CGFloat(index + index + 1) let xCenter = tabBarItemWidth * multiplierValue / 2 + 10 indicatorCounterFB.backgroundColor = .red indicatorCounterFB.layer.cornerRadius = 8 indicatorCounterFB.clipsToBounds = true indicatorCounterFB.frame = CGRect(x: xCenter, y: 5, width: counter > 99 ? 30 : counter > 9 ? 23 : 16, height: 16) tabBar.addSubview(indicatorCounterFB) indicatorCounterFB.addSubview(labelCounterFB) labelCounterFB.anchor(centerX: indicatorCounterFB.centerXAnchor, centerY: indicatorCounterFB.centerYAnchor) labelCounterFB.font = .systemFont(ofSize: 10) labelCounterFB.textColor = .white } if counter > 99 { labelCounterFB.text = "99+" } else { labelCounterFB.text = "\(counter)" } } else { if indicatorCounterFB.isDescendant(of: tabBar) { indicatorCounterFB.removeFromSuperview() } } } } } } // override func viewDidLayoutSubviews() { // super.viewDidLayoutSubviews() // tabBar.frame.size.height = 65 // tabBar.frame.origin.y = view.frame.height - 65 // } override func viewDidAppear(_ animated: Bool) { Nexilis.floatingButton.isHidden = false } func settingDelegate() { if self.navigationController?.visibleViewController == fourthTab { return } if self.viewControllers?.firstIndex(of: fourthTab!) == nil { let vc = FourthTabViewController() vc.notInTab = true Nexilis.floatingButton.isHidden = true self.navigationController?.show(vc, sender: nil) } else { self.selectedIndex = (self.viewControllers?.firstIndex(of: fourthTab!))! if indicatorImage != nil { indicatorImage.removeFromSuperview() addCustomViewAboveTabBarItem(at: selectedIndex, image: imageIndicator) } } } static var alertChangeProfile = LibAlertController() public static func checkIsChangePerson() -> Bool { let isChangeProfile = Utils.getSetProfile() if !isChangeProfile { alertChangeProfile.dismiss(animated: false) alertChangeProfile = LibAlertController(title: "Set Profile".localized(), message: "You must set your profile to use this feature".localized(), preferredStyle: .alert) alertChangeProfile.addAction(UIAlertAction(title: "Cancel".localized(), style: .destructive, handler: {_ in if ViewController.def?.viewControllers?.firstIndex(of: (ViewController.def?.firstTab)!) == ViewController.def?.selectedIndex { if let wv = ViewController.def?.firstTab?.viewControllers.first as? FirstTabViewController { wv.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } } if ViewController.def?.viewControllers?.firstIndex(of: (ViewController.def?.thirdTab)!) == ViewController.def?.selectedIndex { if let wv = ViewController.def?.thirdTab?.viewControllers.first as? ThirdTabViewController { wv.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } } })) alertChangeProfile.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in ViewController.resetTabSelected() guard let controller = APIS.getControllerSign() else { return } if let controller = controller as? SignUpSignIn { controller.forceLogin = true } else if let controller = controller as? SignInOption { controller.forceLogin = true } let navigationController = CustomNavigationController(rootViewController: controller) navigationController.modalPresentationStyle = .fullScreen navigationController.navigationBar.tintColor = .white navigationController.navigationBar.barTintColor = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor navigationController.navigationBar.isTranslucent = false navigationController.navigationBar.overrideUserInterfaceStyle = .dark navigationController.navigationBar.barStyle = .black let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)] UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal) let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white] navigationController.navigationBar.titleTextAttributes = textAttributes ViewController.def?.show(b: false) if let wv1 = ViewController.def?.firstTab?.viewControllers.first as? FirstTabViewController { wv1.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if let wv3 = ViewController.def?.thirdTab?.viewControllers.first as? ThirdTabViewController { wv3.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } let rootVC = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController if rootVC?.presentedViewController == nil { rootVC?.present(navigationController, animated: true, completion: nil) } else { rootVC?.presentedViewController?.present(navigationController, animated: true, completion: nil) } })) let rootVC = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController if rootVC?.presentedViewController == nil { rootVC?.present(alertChangeProfile, animated: true, completion: nil) } else { rootVC?.presentedViewController?.present(alertChangeProfile, animated: true, completion: nil) } return false } return true } public static func resetTabSelected(){ ViewController.isTab1 = true ViewController.isTab2 = false ViewController.isTab3 = false ViewController.isTab4 = false } override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { let cpaasMode = PrefsUtil.getCpaasMode() let customTab = PrefsUtil.getCustomTab().split(separator: ",") if(cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX){ if(customTab.count == 2){ ViewController.isTab1 = item == tabBar.items?[0] ViewController.isTab2 = item == tabBar.items?[2] } else if(customTab.count == 3){ ViewController.isTab1 = item == tabBar.items?[0] ViewController.isTab2 = item == tabBar.items?[2] ViewController.isTab3 = item == tabBar.items?[3] } else if(customTab.count == 4){ ViewController.isTab1 = item == tabBar.items?[0] ViewController.isTab2 = item == tabBar.items?[1] ViewController.isTab3 = item == tabBar.items?[3] ViewController.isTab4 = item == tabBar.items?[4] } } else{ ViewController.isTab1 = item == tabBar.items?[0] ViewController.isTab2 = item == tabBar.items?[1] if(customTab.count > 2){ ViewController.isTab3 = item == tabBar.items?[2] } if(customTab.count > 3){ ViewController.isTab4 = item == tabBar.items?[3] } } } func createMidFloatingButton(){ var minYIpX: CGFloat = 0 let iPhoneModel = ViewController.getiPhoneModel() if iPhoneModel == "iPhone X or newer" { minYIpX += 20 } var widthHeightButton: CGFloat = 45 if Utils.getIconDockSize() == "1" { widthHeightButton = 55 } ViewController.chatButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: widthHeightButton, height: widthHeightButton)) ViewController.chatButton.setBackgroundImage(UIImage(named: "pb_button_chat", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal) ViewController.chatButton.layer.shadowColor = UIColor.black.cgColor ViewController.chatButton.layer.shadowOpacity = 0.1 ViewController.chatButton.layer.shadowOffset = CGSize(width: 4, height: 4) ViewController.chatButton.addTarget(self, action: #selector(chatTap), for: .touchUpInside) ViewController.callButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: widthHeightButton, height: widthHeightButton)) ViewController.callButton.setBackgroundImage(UIImage(named: "pb_button_call", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal) ViewController.callButton.layer.shadowColor = UIColor.black.cgColor ViewController.callButton.layer.shadowOpacity = 0.1 ViewController.callButton.layer.shadowOffset = CGSize(width: 4, height: 4) ViewController.callButton.addTarget(self, action: #selector(callTap), for: .touchUpInside) ViewController.ccButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: widthHeightButton, height: widthHeightButton)) ViewController.ccButton.setBackgroundImage(UIImage(named: "pb_button_cc", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal) ViewController.ccButton.layer.shadowColor = UIColor.black.cgColor ViewController.ccButton.layer.shadowOpacity = 0.1 ViewController.ccButton.layer.shadowOffset = CGSize(width: 4, height: 4) ViewController.ccButton.addTarget(self, action: #selector(ccTap), for: .touchUpInside) ViewController.streamingButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: widthHeightButton, height: widthHeightButton)) ViewController.streamingButton.setBackgroundImage(UIImage(named: "pb_button_stream", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal) ViewController.streamingButton.layer.shadowColor = UIColor.black.cgColor ViewController.streamingButton.layer.shadowOpacity = 0.1 ViewController.streamingButton.layer.shadowOffset = CGSize(width: 4, height: 4) ViewController.streamingButton.addTarget(self, action: #selector(streamTap), for: .touchUpInside) ViewController.postButton = UIButton(frame: CGRect(x: self.view.bounds.width / 2 - 22.5 , y: self.view.bounds.height - 80 - minYIpX, width: widthHeightButton, height: widthHeightButton)) ViewController.postButton.setBackgroundImage(UIImage(named: "pb_button_post", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal), for: .normal) ViewController.postButton.layer.shadowColor = UIColor.black.cgColor ViewController.postButton.layer.shadowOpacity = 0.1 ViewController.postButton.layer.shadowOffset = CGSize(width: 4, height: 4) ViewController.postButton.addTarget(self, action: #selector(postTap), for: .touchUpInside) let buttonCenterX = self.view.bounds.width / 2 let buttonCenterY = self.view.bounds.height - self.tabBar.bounds.height //print("buttonCenterX \(buttonCenterX)") //print("buttonCenterY \(buttonCenterY)") ViewController.middleButton = UIButton(frame: CGRect(x: buttonCenterX - 40 , y: buttonCenterY - 40, width: 80, height: 80)) if !PrefsUtil.getIconDock().isEmpty { if PrefsUtil.getIconDock().contains(".gif") { ViewController.middleButton.sd_setBackgroundImage(with: URL(string: PrefsUtil.getIconCenterAnim()!), for: .normal, completed: nil) } else { DispatchQueue.global().async { let urlString = PrefsUtil.getUrlDock()! if let cachedImage = ImageCache.shared.image(forKey: urlString) { DispatchQueue.main.async() { ViewController.middleButton.setBackgroundImage(cachedImage, for: .normal) } return } Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: urlString)!) { data, response, error in guard let data = data, error == nil else { return } // always update the UI from the main thread DispatchQueue.main.async() { if UIImage(data: data) != nil { ViewController.middleButton.setBackgroundImage(UIImage(data: data), for: .normal) ImageCache.shared.save(image: UIImage(data: data)!, forKey: urlString) } } } } } } else { ViewController.middleButton.setBackgroundImage(UIImage(named: "pb_button", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), for: .normal) } ViewController.middleButton.layer.shadowColor = UIColor.black.cgColor ViewController.middleButton.layer.shadowOffset = CGSize(width: 0.0, height: 2.0) ViewController.middleButton.layer.shadowOpacity = 1.0 ViewController.middleButton.layer.shadowRadius = 5.0 ViewController.middleButton.layer.masksToBounds = false ViewController.middleButton.layer.cornerRadius = 4.0 ViewController.middleButton.addTarget(self, action: #selector(middleBtnTapped), for: .touchUpInside) let longPressMidButton = UILongPressGestureRecognizer(target: self, action: #selector(longPressMidBtn(gestureRecognizer:))) ViewController.middleButton.addGestureRecognizer(longPressMidButton) self.view.addSubview(ViewController.chatButton) self.view.addSubview(ViewController.callButton) self.view.addSubview(ViewController.ccButton) self.view.addSubview(ViewController.postButton) self.view.addSubview(ViewController.streamingButton) self.view.addSubview(ViewController.middleButton) ViewController.hideDockedButton() } @objc func longPressMidBtn(gestureRecognizer: UILongPressGestureRecognizer) { if gestureRecognizer.state == .began { APIS.openSetting() // if self.viewControllers?.firstIndex(of: fourthTab!) == nil { // let vc = fourthTab! // vc.notInTab = true // self.navigationController?.show(vc, sender: nil) // } else { // self.selectedIndex = (self.viewControllers?.firstIndex(of: fourthTab!))! // } } } func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { if(viewController == secondTab){ if(!ViewController.checkIsChangePerson()){ return false } } return true } func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { if let selectedIndex = viewControllers?.firstIndex(of: viewController) { if indicatorImage != nil { indicatorImage.removeFromSuperview() addCustomViewAboveTabBarItem(at: selectedIndex, image: imageIndicator) } Utils.setLastTabSelected(value: selectedIndex) } if viewController != secondTab { let idxTabChat = self.viewControllers?.firstIndex(where: {$0 == secondTab}) if idxTabChat != nil { let navTabs = self.viewControllers![idxTabChat!] as! UINavigationController let vcTabChats = navTabs.viewControllers.first as! SecondTabViewController if vcTabChats.searchController.isActive { vcTabChats.searchController.isActive = false } } } } override func viewWillAppear(_ animated: Bool) { navigationController?.setNavigationBarHidden(true, animated: false) if !firstLoad { willappear() } else { firstLoad = false } } func willappear() { let acceptTerm = PrefsUtil.getTerms() let enable_privacy_policy = PrefsUtil.getEnablePrivacyPolicy() if !acceptTerm { if !Utils.getForceAnonymous() && !Utils.getSetProfile() { Nexilis.showForceSignIn() { self.showWelocomeView() } } else { showWelocomeView() } return } else if enable_privacy_policy && !PrefsUtil.getAgreePrivacyPolicy() { showPrivacyPolicyView() return } else if acceptTerm { if !Utils.getForceAnonymous() && !Utils.getSetProfile() { Nexilis.showForceSignIn() return } } self.selectedViewController?.viewWillAppear(false) self.selectedViewController?.viewDidAppear(false) } func showPrivacyPolicyView() { if let privacyView = privacyPolicyVC.view { let bgImage = UIImageView() privacyView.addSubview(bgImage) bgImage.anchor(top: privacyView.topAnchor, left: privacyView.leftAnchor, bottom: privacyView.bottomAnchor, right: privacyView.rightAnchor) bgImage.backgroundColor = .white DispatchQueue.global().async { DispatchQueue.main.async { let listBg = PrefsUtil.getBackgroundLight().isEmpty && PrefsUtil.getBackgroundDark().isEmpty ? PrefsUtil.getBackground() : self.traitCollection.userInterfaceStyle == .dark ? PrefsUtil.getBackgroundDark() : PrefsUtil.getBackgroundLight() if listBg.isEmpty { return } var bgChoosen = "" let arrayBg = listBg.split(separator: ",") bgChoosen = String(arrayBg[Int.random(in: 0.. String? { guard let infoPlist = Bundle.main.infoDictionary else { return nil } guard let bundleIcons = infoPlist["CFBundleIcons"] as? NSDictionary else { return nil } guard let bundlePrimaryIcon = bundleIcons["CFBundlePrimaryIcon"] as? NSDictionary else { return nil } guard let bundleIconFiles = bundlePrimaryIcon["CFBundleIconFiles"] as? NSArray else { return nil } guard let appIcon = bundleIconFiles.lastObject as? String else { return nil } return appIcon } func showWebviewTerm() { termVC = UIViewController() if let viewTerm = termVC!.view { let webView = WKWebView() let lang: String = SecureUserDefaults.shared.value(forKey: "i18n_language") ?? "en" var urlTerm = "https://nexilis.io/newuniverse-tos" if lang == "id" { urlTerm = "https://nexilis.io/newuniverse-tos-id" } let url = URL (string: urlTerm) let requestObj = URLRequest(url: url!) webView.load(requestObj) viewTerm.addSubview(webView) webView.anchor(top: viewTerm.safeAreaLayoutGuide.topAnchor, left: viewTerm.safeAreaLayoutGuide.leftAnchor, bottom: viewTerm.safeAreaLayoutGuide.bottomAnchor, right: viewTerm.safeAreaLayoutGuide.rightAnchor) } let navigationController = CustomNavigationController(rootViewController: termVC!) navigationController.navigationBar.tintColor = .mainColor navigationController.navigationBar.barTintColor = .white navigationController.navigationBar.isTranslucent = false let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.mainColor] navigationController.navigationBar.titleTextAttributes = textAttributes termVC!.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Close".localized(), style: .plain, target: self, action: #selector(closeTerm)) welcomeVC.present(navigationController, animated: true) } @objc func closeTerm() { termVC!.dismiss(animated: true) } @objc func tappedOnLabelTerms(_ gesture: UITapGestureRecognizer) { let termString = termText as NSString let termRange = termString.range(of: term) let tapLocation = gesture.location(in: welcomeDesc) let index = welcomeDesc.indexOfAttributedTextCharacterAtPoint(point: tapLocation) if checkRange(termRange, contain: index) == true { showWebviewTerm() return } } @objc func tappedOnAgree(_ gesture: UITapGestureRecognizer) { PrefsUtil.setTerms(value: true) welcomeVC.dismiss(animated: true) } @objc func tappedOnAgreePrivacy(_ gesture: UITapGestureRecognizer) { PrefsUtil.setAgreePrivacyPolicy(value: true) privacyPolicyVC.dismiss(animated: true) } func checkRange(_ range: NSRange, contain index: Int) -> Bool { return index > range.location && index < range.location + range.length } @objc func middleBtnTapped() { ViewController.expandButton() } public func show(b: Bool) { if(!b){ if(ViewController.isExpandButton){ ViewController.expandButton() } } } @objc func ccTap() { //print("ccTap") if(ViewController.checkIsChangePerson()){ show(b: false) if let wv1 = ViewController.def?.firstTab?.viewControllers.first as? FirstTabViewController { wv1.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if let wv3 = ViewController.def?.thirdTab?.viewControllers.first as? ThirdTabViewController { wv3.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 2 { let package_id = ViewController.listPullFB[2].split(separator: "|")[0] var app_id = "" if package_id.contains("_fb") { let listSplit = package_id.split(separator: "_", maxSplits: 1) let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0] let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))! if listSplit.count == 2 { app_id = String(listSplit[1]) } if indexTap == 99 { openTabPost() } else { Nexilis.buttonClicked(index: indexTap, id: app_id) } } else { if !app_id.isEmpty { Nexilis.buttonClicked(index: 0, id: app_id) } } } else { Nexilis.buttonClicked(index: 9) } } } @objc func streamTap() { //print("streamTap") if(ViewController.checkIsChangePerson()){ show(b: false) if let wv1 = ViewController.def?.firstTab?.viewControllers.first as? FirstTabViewController { wv1.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if let wv3 = ViewController.def?.thirdTab?.viewControllers.first as? ThirdTabViewController { wv3.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 4 { let package_id = ViewController.listPullFB[4].split(separator: "|")[0] var app_id = "" if package_id.contains("_fb") { let listSplit = package_id.split(separator: "_", maxSplits: 1) let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0] let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))! if listSplit.count == 2 { app_id = String(listSplit[1]) } if indexTap == 99 { openTabPost() } else { Nexilis.buttonClicked(index: indexTap, id: app_id) } } else { if !app_id.isEmpty { Nexilis.buttonClicked(index: 0, id: app_id) } } } else { Nexilis.buttonClicked(index: 8) } } } @objc func callTap() { //print("callTap") if(ViewController.checkIsChangePerson()){ show(b: false) if let wv1 = ViewController.def?.firstTab?.viewControllers.first as? FirstTabViewController { wv1.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if let wv3 = ViewController.def?.thirdTab?.viewControllers.first as? ThirdTabViewController { wv3.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 1 { let package_id = ViewController.listPullFB[1].split(separator: "|")[0] var app_id = "" if package_id.contains("_fb") { let listSplit = package_id.split(separator: "_", maxSplits: 1) let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0] let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))! if listSplit.count == 2 { app_id = String(listSplit[1]) } if indexTap == 99 { openTabPost() } else { Nexilis.buttonClicked(index: indexTap, id: app_id) } } else { if !app_id.isEmpty { Nexilis.buttonClicked(index: 0, id: app_id) } } } else { Nexilis.buttonClicked(index: 7) } } } @objc func chatTap() { //print("chatTap") // APIS.openWhiteboard() // return if(ViewController.checkIsChangePerson()){ show(b: false) if let wv1 = ViewController.def?.firstTab?.viewControllers.first as? FirstTabViewController { wv1.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if let wv3 = ViewController.def?.thirdTab?.viewControllers.first as? ThirdTabViewController { wv3.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 0 { let package_id = ViewController.listPullFB[0].split(separator: "|")[0] var app_id = "" if package_id.contains("_fb") { let listSplit = package_id.split(separator: "_", maxSplits: 1) let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0] let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))! if listSplit.count == 2 { app_id = String(listSplit[1]) } if indexTap == 99 { openTabPost() } else { Nexilis.buttonClicked(index: indexTap, id: app_id) } } else { if !app_id.isEmpty { Nexilis.buttonClicked(index: 0, id: app_id) } } } else { Nexilis.buttonClicked(index: 6) } } } @objc func postTap() { if(ViewController.checkIsChangePerson()){ show(b: false) if let wv1 = ViewController.def?.firstTab?.viewControllers.first as? FirstTabViewController { wv1.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if let wv3 = ViewController.def?.thirdTab?.viewControllers.first as? ThirdTabViewController { wv3.webView?.evaluateJavaScript("if(resumeAll){resumeAll();}") } if ViewController.listPullFB.count != 0 && ViewController.listPullFB.count > 3 { let package_id = ViewController.listPullFB[3].split(separator: "|")[0] var app_id = "" if package_id.contains("_fb") { let listSplit = package_id.split(separator: "_", maxSplits: 1) let numIdx = listSplit[listSplit.firstIndex(where: { $0.contains("fb") }) ?? 0] let indexTap = Int(String(numIdx).substring(from: 2, to: numIdx.count))! if listSplit.count == 2 { app_id = String(listSplit[1]) } if indexTap == 99 { openTabPost() } else { Nexilis.buttonClicked(index: indexTap, id: app_id) } } else { if !app_id.isEmpty { Nexilis.buttonClicked(index: 0, id: app_id) } } } else { openTabPost() } } } func openTabPost() { let customTab = PrefsUtil.getCustomTab().split(separator: ",") let cpaasMode = PrefsUtil.getCpaasMode() var i = 0 var j = 0 //print("custom tab post tap = \(customTab)") while j < customTab.count { if(((i == 1 && customTab.count == 3) || i == 2) && (cpaasMode == PrefsUtil.CPAAS_MODE_DOCKED || cpaasMode == PrefsUtil.CPAAS_MODE_MIX)){ } else { if customTab[j] == "3" { break } j += 1 } i += 1 } if(j < customTab.count){ self.selectedIndex = i DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(1), execute: { let me = User.getMyPin() let address = "\(PrefsUtil.getURLBase())nexilis/pages/tab5-new-post?f_pin=\(me ?? "")" if let wv3 = ViewController.def?.thirdTab?.viewControllers.first as? ThirdTabViewController { wv3.webView.evaluateJavaScript("{window.localStorage.setItem('currentTab','\(ViewController.tab3)')}") wv3.webView.evaluateJavaScript("window.location = '\(address)'") } }) } } static func pullActionButton() { if datePullFB == nil || Int(Date().timeIntervalSince(datePullFB!)) >= 60 { datePullFB = Date() DispatchQueue.global().async { if !PrefsUtil.getCustomButtons().isEmpty { DispatchQueue.main.async { [self] in let customButtons = PrefsUtil.getCustomButtons().components(separatedBy: ",") var customIcons = PrefsUtil.getCustomFBIcon().components(separatedBy: ",") if Utils.getIsLoadThemeFromOther() { customIcons = Utils.getButtonIcon().components(separatedBy: ",") } for i in 0.. UIImage { let rect: CGRect = CGRect(x: 0, y: 0, width: size.width, height: size.height) UIGraphicsBeginImageContextWithOptions(size, false, 0) color.setFill() UIRectFill(rect) let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return image } } extension String { static func format(strings: [String], italicFont: UIFont = UIFont.italicSystemFont(ofSize: 12), italicColor: UIColor = UIColor.systemGreen, inString string: String, font: UIFont = UIFont.systemFont(ofSize: 12), color: UIColor = UIColor.black) -> NSAttributedString { let attributedString = NSMutableAttributedString(string: string, attributes: [ NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: color]) let italicFontAttribute = [NSAttributedString.Key.font: italicFont, NSAttributedString.Key.foregroundColor: italicColor] for italic in strings { attributedString.addAttributes(italicFontAttribute, range: (string as NSString).range(of: italic)) } return attributedString } } extension UILabel { func indexOfAttributedTextCharacterAtPoint(point: CGPoint) -> Int { assert(self.attributedText != nil, "This method is developed for attributed string") let textStorage = NSTextStorage(attributedString: self.attributedText!) let layoutManager = NSLayoutManager() textStorage.addLayoutManager(layoutManager) let textContainer = NSTextContainer(size: self.frame.size) textContainer.lineFragmentPadding = 0 textContainer.maximumNumberOfLines = self.numberOfLines textContainer.lineBreakMode = self.lineBreakMode layoutManager.addTextContainer(textContainer) let index = layoutManager.characterIndex(for: point, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) return index } }