ThirdTabViewController.swift 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. //
  2. // ThirdTabViewController.swift
  3. // AppBuilder
  4. //
  5. // Created by Kevin Maulana on 30/03/22.
  6. //
  7. import UIKit
  8. import WebKit
  9. import NexilisLite
  10. import Speech
  11. class ThirdTabViewController: UIViewController, UIScrollViewDelegate, UIGestureRecognizerDelegate, WKNavigationDelegate, WKScriptMessageHandler {
  12. @IBOutlet weak var webView: WKWebView!
  13. var address = ""
  14. private var lastContentOffset: CGFloat = 0
  15. var isAllowSpeech = false
  16. var speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en"))
  17. var recognitionRequest : SFSpeechAudioBufferRecognitionRequest?
  18. var recognitionTask : SFSpeechRecognitionTask?
  19. let audioEngine = AVAudioEngine()
  20. var alertController = LibAlertController()
  21. var dateRefresh: Date?
  22. public static var forceRefresh = false
  23. public static var inView = false
  24. public static var atFirstPage = true
  25. public static var showModal = false
  26. override func viewDidLoad() {
  27. super.viewDidLoad()
  28. let tapGesture = UITapGestureRecognizer(target: self, action: #selector(collapseDocked))
  29. tapGesture.cancelsTouchesInView = false
  30. tapGesture.delegate = self
  31. webView.scrollView.addGestureRecognizer(tapGesture)
  32. let refreshControl = UIRefreshControl()
  33. refreshControl.addTarget(self, action: #selector(reloadWebView(_:)), for: .valueChanged)
  34. webView.scrollView.addSubview(refreshControl)
  35. webView.scrollView.delegate = self
  36. webView.navigationDelegate = self
  37. webView.allowsBackForwardNavigationGestures = true
  38. let contentController = self.webView.configuration.userContentController
  39. contentController.add(self, name: "checkProfile")
  40. contentController.add(self, name: "setIsProductModalOpen")
  41. contentController.add(self, name: "toggleVoiceSearch")
  42. contentController.add(self, name: "blockUser")
  43. contentController.add(self, name: "showAlert")
  44. contentController.add(self, name: "closeProfile")
  45. contentController.add(self, name: "tabShowHide")
  46. let source: String = "var meta = document.createElement('meta');" +
  47. "meta.name = 'viewport';" +
  48. "meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';" +
  49. "var head = document.getElementsByTagName('head')[0];" +
  50. "head.appendChild(meta);" +
  51. "$('#header-layout').find('.col-8').removeClass('col-8').addClass('col');" +
  52. "$('#header-layout').find('.col-4').removeClass('col-4').addClass('col');"
  53. let script: WKUserScript = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
  54. contentController.addUserScript(script)
  55. NotificationCenter.default.addObserver(self, selector: #selector(onShowAC(notification:)), name: NSNotification.Name(rawValue: "onShowAC"), object: nil)
  56. NotificationCenter.default.addObserver(self, selector: #selector(onRefreshWebView(notification:)), name: NSNotification.Name(rawValue: "onRefreshWebView"), object: nil)
  57. }
  58. override func viewWillAppear(_ animated: Bool) {
  59. if ThirdTabViewController.inView {
  60. return
  61. }
  62. ThirdTabViewController.inView = true
  63. let me = UserDefaults.standard.string(forKey: "me")
  64. var myURL : URL?
  65. let lang = UserDefaults.standard.string(forKey: "i18n_language")
  66. var intLang = 0
  67. if lang == "id" {
  68. speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "id"))
  69. intLang = 1
  70. }
  71. switch(ViewController.tab3){
  72. case "0":
  73. address = "\(PrefsUtil.getURLBase())nexilis/pages/tab1-main-only?f_pin=\(me ?? "")&lang=\(intLang)"
  74. myURL = URL(string: address)
  75. case "1":
  76. address = "\(PrefsUtil.getURLBase())nexilis/pages/tab3-main-only?f_pin=\(me ?? "")&lang=\(intLang)"
  77. myURL = URL(string: address)
  78. case "2":
  79. address = "\(PrefsUtil.getURLBase())nexilis/pages/tab1-main?f_pin=\(me ?? "")&lang=\(intLang)"
  80. myURL = URL(string: address)
  81. case "3":
  82. address = "\(PrefsUtil.getURLBase())nexilis/pages/tab3-commerce?f_pin=\(me ?? "")&lang=\(intLang)"
  83. myURL = URL(string: address)
  84. case "4":
  85. address = "\(PrefsUtil.getURLBase())nexilis/pages/tab1-video?f_pin=\(me ?? "")&lang=\(intLang)"
  86. myURL = URL(string: address)
  87. default:
  88. if(!ViewController.tab3.isEmpty){
  89. if(ViewController.tab3.lowercased().contains("https://") || ViewController.sURL.lowercased().contains("http://")){
  90. address = ViewController.tab3
  91. myURL = URL(string: address)
  92. }
  93. else {
  94. address = "https://\(ViewController.tab3)"
  95. myURL = URL(string: address)
  96. }
  97. }
  98. }
  99. print(address)
  100. if let u = myURL{
  101. self.webView.evaluateJavaScript("{window.localStorage.setItem('currentTab','\(ViewController.tab3)')}")
  102. if ((dateRefresh == nil || Int(Date().timeIntervalSince(dateRefresh!)) >= 60) && ThirdTabViewController.atFirstPage) || ThirdTabViewController.forceRefresh {
  103. let myRequest = URLRequest(url: u)
  104. webView.load(myRequest)
  105. } else {
  106. self.webView.evaluateJavaScript("if(resumeAll){resumeAll();}")
  107. }
  108. dateRefresh = Date()
  109. ThirdTabViewController.forceRefresh = false
  110. }
  111. let cpaasMode = PrefsUtil.getCpaasMode()
  112. let isBurger = cpaasMode == PrefsUtil.CPAAS_MODE_BURGER
  113. navigationController?.setNavigationBarHidden(!isBurger, animated: false)
  114. if isBurger {
  115. self.navigationController?.navigationBar.topItem?.title = Bundle.main.displayName
  116. self.navigationController?.navigationBar.setNeedsLayout()
  117. }
  118. }
  119. override func viewDidAppear(_ animated: Bool) {
  120. DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: {
  121. // if (self.isUsingMyWebview() && self.webView.url != nil && !self.webView.url!.absoluteString.contains("nexilis/pages/tab1-main-only") && !self.webView.url!.absoluteString.contains("nexilis/pages/tab3-main-only") && !self.webView.url!.absoluteString.contains("nexilis/pages/tab1-main") && !self.webView.url!.absoluteString.contains("nexilis/pages/tab3-commerce") && !self.webView.url!.absoluteString.contains("nexilis/pages/tab1-video") && !self.webView.url!.absoluteString.contains("nexilis/pages/tab3-main")) || ThirdTabViewController.showModal {
  122. // ViewController.alwaysHideButton = true
  123. // self.hideTabBar()
  124. // ThirdTabViewController.atFirstPage = false
  125. // } else {
  126. var viewController = UIApplication.shared.windows.first!.rootViewController
  127. if !(viewController is ViewController) {
  128. viewController = self.parent
  129. }
  130. if ViewController.middleButton.isHidden {
  131. ViewController.isExpandButton = false
  132. if let viewController = viewController as? ViewController {
  133. if viewController.tabBar.isHidden {
  134. viewController.tabBar.isHidden = false
  135. ViewController.middleButton.isHidden = false
  136. ViewController.alwaysHideButton = false
  137. }
  138. }
  139. } else if PrefsUtil.getCpaasMode() != PrefsUtil.CPAAS_MODE_DOCKED {
  140. DispatchQueue.main.async {
  141. if let viewController = viewController as? ViewController {
  142. if viewController.tabBar.isHidden {
  143. viewController.tabBar.isHidden = false
  144. ViewController.alwaysHideButton = false
  145. }
  146. }
  147. }
  148. }
  149. // }
  150. })
  151. }
  152. @objc func onShowAC(notification: NSNotification) {
  153. self.webView.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  154. view.endEditing(true)
  155. resignFirstResponder()
  156. }
  157. @objc func onRefreshWebView(notification: NSNotification) {
  158. ThirdTabViewController.forceRefresh = true
  159. }
  160. override func viewWillDisappear(_ animated: Bool) {
  161. if self.webView.scrollView.contentOffset.y < 0 { // Move tableView to top
  162. self.webView.scrollView.setContentOffset(CGPoint.zero, animated: true)
  163. }
  164. self.webView.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  165. view.endEditing(true)
  166. resignFirstResponder()
  167. ThirdTabViewController.inView = false
  168. self.webView.evaluateJavaScript("hideAddToCart();")
  169. }
  170. func scrollViewDidScroll(_ scrollView: UIScrollView) {
  171. if (self.lastContentOffset > scrollView.contentOffset.y && scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)) {
  172. showTabBar();
  173. }
  174. else if (self.lastContentOffset != 0 && self.lastContentOffset < scrollView.contentOffset.y && self.lastContentOffset >= 0) {
  175. hideTabBar();
  176. }
  177. self.lastContentOffset = scrollView.contentOffset.y
  178. self.collapseDocked()
  179. }
  180. @objc func collapseDocked() {
  181. if ViewController.isExpandButton {
  182. ViewController.expandButton()
  183. }
  184. }
  185. @objc func reloadWebView(_ sender: UIRefreshControl) {
  186. webView.reload()
  187. sender.endRefreshing()
  188. }
  189. func hideTabBar() {
  190. var viewController = UIApplication.shared.windows.first!.rootViewController
  191. if !(viewController is ViewController) {
  192. viewController = self.parent
  193. }
  194. if ViewController.middleButton.isDescendant(of: viewController!.view) {
  195. DispatchQueue.main.async {
  196. if ViewController.isExpandButton {
  197. ViewController.expandButton()
  198. }
  199. ViewController.hideDockedButton()
  200. if let viewController = viewController as? ViewController {
  201. viewController.tabBar.isHidden = true
  202. }
  203. ViewController.removeMiddleButton()
  204. }
  205. } else if PrefsUtil.getCpaasMode() != PrefsUtil.CPAAS_MODE_DOCKED {
  206. DispatchQueue.main.async {
  207. if let viewController = viewController as? ViewController {
  208. if !viewController.tabBar.isHidden {
  209. viewController.tabBar.isHidden = true
  210. }
  211. }
  212. }
  213. }
  214. }
  215. func showTabBar() {
  216. if(ViewController.alwaysHideButton){
  217. return
  218. }
  219. var viewController = UIApplication.shared.windows.first!.rootViewController
  220. if !(viewController is ViewController) {
  221. viewController = self.parent
  222. }
  223. if ViewController.middleButton.isHidden {
  224. if let viewController = viewController as? ViewController {
  225. viewController.tabBar.isHidden = false
  226. ViewController.middleButton.isHidden = false
  227. }
  228. } else if PrefsUtil.getCpaasMode() != PrefsUtil.CPAAS_MODE_DOCKED {
  229. DispatchQueue.main.async {
  230. if let viewController = viewController as? ViewController {
  231. if viewController.tabBar.isHidden {
  232. viewController.tabBar.isHidden = false
  233. }
  234. }
  235. }
  236. }
  237. }
  238. func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
  239. scrollView.pinchGestureRecognizer?.isEnabled = false
  240. }
  241. func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
  242. if message.name == "checkProfile" {
  243. guard let dict = message.body as? [String: AnyObject],
  244. let param1 = dict["param1"] as? String,
  245. let param2 = dict["param2"] as? String else {
  246. return
  247. }
  248. if ViewController.checkIsChangePerson() {
  249. if param2 == "like" {
  250. self.webView.evaluateJavaScript("likeProduct('\(param1)',1,true);")
  251. } else if param2 == "comment" {
  252. self.webView.evaluateJavaScript("openComment('\(param1.split(separator: "|")[0])',\(param1.split(separator: "|")[1]),true);")
  253. } else if param2 == "report_user" {
  254. self.webView.evaluateJavaScript("reportUser('\(param1)',true);")
  255. } else if param2 == "report_content" {
  256. self.webView.evaluateJavaScript("reportContent('\(param1.split(separator: "|")[0])','\(param1.split(separator: "|")[1])',true);")
  257. } else if param2 == "block_user" {
  258. self.webView.evaluateJavaScript("blockUser('\(param1)',true);")
  259. } else if param2 == "follow_user" {
  260. self.webView.evaluateJavaScript("followUser('\(param1.split(separator: "|")[0])',\(param1.split(separator: "|")[1]),true);")
  261. } else if param2 == "homepage" || param2 == "gif" {
  262. self.webView.evaluateJavaScript("window.location.href = '\(param1)';")
  263. } else if param2 == "block_content" {
  264. self.webView.evaluateJavaScript("blockContent('\(param1)',true);")
  265. } else {
  266. self.webView.evaluateJavaScript("openNewPost(true);")
  267. }
  268. } else {
  269. self.webView.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  270. }
  271. } else if message.name == "setIsProductModalOpen" {
  272. guard let dict = message.body as? [String: AnyObject],
  273. let param1 = dict["param1"] as? Bool else {
  274. return
  275. }
  276. if param1 {
  277. if self.webView.scrollView.contentOffset.y < 0 { // Move tableView to top
  278. self.webView.scrollView.setContentOffset(CGPoint.zero, animated: true)
  279. }
  280. }
  281. ThirdTabViewController.showModal = param1
  282. } else if message.name == "toggleVoiceSearch" {
  283. if !isAllowSpeech {
  284. setupSpeech()
  285. } else {
  286. runVoice()
  287. }
  288. } else if message.name == "blockUser" {
  289. guard let dict = message.body as? [String: AnyObject],
  290. let param1 = dict["param1"] as? String,
  291. let param2 = dict["param2"] as? Bool else {
  292. return
  293. }
  294. if param2 {
  295. DispatchQueue.global().async {
  296. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getBlock(l_pin: param1)) {
  297. if response.isOk() {
  298. DispatchQueue.main.async {
  299. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  300. _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
  301. "ex_block" : "1"
  302. ], _where: "f_pin = '\(param1)'")
  303. })
  304. }
  305. }
  306. }
  307. }
  308. } else {
  309. DispatchQueue.global().async {
  310. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getUnBlock(l_pin: param1)) {
  311. if response.isOk() {
  312. DispatchQueue.main.async {
  313. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  314. _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
  315. "ex_block" : "0"
  316. ], _where: "f_pin = '\(param1)'")
  317. })
  318. }
  319. }
  320. }
  321. }
  322. }
  323. } else if message.name == "showAlert" {
  324. guard let dict = message.body as? [String: AnyObject],
  325. let param1 = dict["param1"] as? String else {
  326. return
  327. }
  328. showToast(message: param1, controller: self.tabBarController!)
  329. } else if message.name == "blockUser" {
  330. guard let dict = message.body as? [String: AnyObject],
  331. let param1 = dict["param1"] as? String,
  332. let param2 = dict["param2"] as? Bool else {
  333. return
  334. }
  335. if param2 {
  336. DispatchQueue.global().async {
  337. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getBlock(l_pin: param1)) {
  338. if response.isOk() {
  339. DispatchQueue.main.async {
  340. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  341. _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
  342. "ex_block" : "1"
  343. ], _where: "f_pin = '\(param1)'")
  344. })
  345. }
  346. }
  347. }
  348. }
  349. } else {
  350. DispatchQueue.global().async {
  351. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getUnBlock(l_pin: param1)) {
  352. if response.isOk() {
  353. DispatchQueue.main.async {
  354. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  355. _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
  356. "ex_block" : "0"
  357. ], _where: "f_pin = '\(param1)'")
  358. })
  359. }
  360. }
  361. }
  362. }
  363. }
  364. } else if message.name == "tabShowHide" {
  365. guard let dict = message.body as? [String: AnyObject],
  366. let param1 = dict["param1"] as? Bool else {
  367. return
  368. }
  369. if param1 {
  370. ViewController.alwaysHideButton = false
  371. showTabBar()
  372. } else {
  373. if self.viewIfLoaded?.window != nil {
  374. ViewController.alwaysHideButton = true
  375. hideTabBar()
  376. }
  377. }
  378. }
  379. }
  380. func setupSpeech() {
  381. self.speechRecognizer?.delegate = self
  382. SFSpeechRecognizer.requestAuthorization { (authStatus) in
  383. var isButtonEnabled = false
  384. switch authStatus {
  385. case .authorized:
  386. isButtonEnabled = true
  387. case .denied:
  388. isButtonEnabled = false
  389. //print("User denied access to speech recognition")
  390. case .restricted:
  391. isButtonEnabled = false
  392. //print("Speech recognition restricted on this device")
  393. case .notDetermined:
  394. isButtonEnabled = false
  395. //print("Speech recognition not yet authorized")
  396. @unknown default:
  397. isButtonEnabled = false
  398. }
  399. OperationQueue.main.addOperation() {
  400. self.isAllowSpeech = isButtonEnabled
  401. if isButtonEnabled {
  402. UserDefaults.standard.set(isButtonEnabled, forKey: "allowSpeech")
  403. self.runVoice()
  404. }
  405. }
  406. }
  407. }
  408. func runVoice() {
  409. if !audioEngine.isRunning {
  410. alertController = LibAlertController(title: "Start Recording".localized(), message: "Say something, I'm listening!".localized(), preferredStyle: .alert)
  411. self.present(alertController, animated: true)
  412. self.webView.evaluateJavaScript("toggleVoiceButton(true)")
  413. self.startRecording()
  414. }
  415. }
  416. func startRecording() {
  417. // Clear all previous session data and cancel task
  418. if recognitionTask != nil {
  419. recognitionTask?.cancel()
  420. recognitionTask = nil
  421. }
  422. // Create instance of audio session to record voice
  423. let audioSession = AVAudioSession.sharedInstance()
  424. do {
  425. try audioSession.setCategory(AVAudioSession.Category.record, mode: .default, options: [])
  426. try audioSession.setMode(AVAudioSession.Mode.measurement)
  427. try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
  428. } catch {
  429. //print("audioSession properties weren't set because of an error.")
  430. }
  431. self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
  432. let inputNode = audioEngine.inputNode
  433. guard let recognitionRequest = recognitionRequest else {
  434. fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")
  435. }
  436. recognitionRequest.shouldReportPartialResults = true
  437. self.recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in
  438. var isFinal = false
  439. var text = ""
  440. if result != nil {
  441. text = result?.bestTranscription.formattedString ?? ""
  442. isFinal = (result?.isFinal)!
  443. self.alertController.dismiss(animated: true)
  444. self.audioEngine.stop()
  445. self.recognitionRequest?.endAudio()
  446. } else {
  447. self.alertController.dismiss(animated: true)
  448. }
  449. if error != nil || isFinal {
  450. if error == nil {
  451. self.webView.evaluateJavaScript("toggleVoiceButton(false)")
  452. self.webView.evaluateJavaScript("submitVoiceSearch('\(text)')")
  453. } else {
  454. self.audioEngine.stop()
  455. self.recognitionRequest?.endAudio()
  456. }
  457. inputNode.removeTap(onBus: 0)
  458. self.recognitionRequest = nil
  459. self.recognitionTask = nil
  460. self.isAllowSpeech = true
  461. }
  462. })
  463. let recordingFormat = inputNode.outputFormat(forBus: 0)
  464. inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
  465. self.recognitionRequest?.append(buffer)
  466. }
  467. self.audioEngine.prepare()
  468. do {
  469. try self.audioEngine.start()
  470. } catch {
  471. //print("audioEngine couldn't start because of an error.")
  472. }
  473. }
  474. func isUsingMyWebview() -> Bool{
  475. return PrefsUtil.getURLThirdTab() == "0" || PrefsUtil.getURLThirdTab() == "1" || PrefsUtil.getURLThirdTab() == "2" || PrefsUtil.getURLThirdTab() == "3" || PrefsUtil.getURLThirdTab() == "4"
  476. }
  477. }
  478. extension ThirdTabViewController: SFSpeechRecognizerDelegate {
  479. func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
  480. if available {
  481. self.isAllowSpeech = true
  482. } else {
  483. self.isAllowSpeech = false
  484. }
  485. }
  486. }
  487. extension ThirdTabViewController: WKUIDelegate {
  488. func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
  489. if self.viewIfLoaded?.window != nil {
  490. if let urlStr = navigationAction.request.url?.absoluteString {
  491. collapseDocked()
  492. if urlStr.contains("nexilis/pages/tab1-main-only") || urlStr.contains("nexilis/pages/tab3-main-only") || urlStr.contains("nexilis/pages/tab1-main") || urlStr.contains("nexilis/pages/tab3-commerce") || urlStr.contains("nexilis/pages/tab1-video") || urlStr.contains("nexilis/pages/tab3-main") {
  493. ViewController.alwaysHideButton = false
  494. showTabBar()
  495. ThirdTabViewController.atFirstPage = true
  496. }
  497. // else if isUsingMyWebview() {
  498. // ViewController.alwaysHideButton = true
  499. // hideTabBar()
  500. // ThirdTabViewController.atFirstPage = false
  501. // }
  502. }
  503. }
  504. decisionHandler(.allow)
  505. }
  506. }