ThirdTabViewController.swift 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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. let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "id"))
  17. var recognitionRequest : SFSpeechAudioBufferRecognitionRequest?
  18. var recognitionTask : SFSpeechRecognitionTask?
  19. let audioEngine = AVAudioEngine()
  20. var alertController = UIAlertController()
  21. override func viewDidLoad() {
  22. super.viewDidLoad()
  23. let tapGesture = UITapGestureRecognizer(target: self, action: #selector(collapseDocked))
  24. tapGesture.cancelsTouchesInView = false
  25. tapGesture.delegate = self
  26. webView.scrollView.addGestureRecognizer(tapGesture)
  27. let refreshControl = UIRefreshControl()
  28. refreshControl.addTarget(self, action: #selector(reloadWebView(_:)), for: .valueChanged)
  29. webView.scrollView.addSubview(refreshControl)
  30. webView.scrollView.delegate = self
  31. webView.navigationDelegate = self
  32. webView.allowsBackForwardNavigationGestures = true
  33. let contentController = self.webView.configuration.userContentController
  34. contentController.add(self, name: "checkProfile")
  35. contentController.add(self, name: "setIsProductModalOpen")
  36. contentController.add(self, name: "toggleVoiceSearch")
  37. contentController.add(self, name: "blockUser")
  38. contentController.add(self, name: "showAlert")
  39. contentController.add(self, name: "closeProfile")
  40. let source: String = "var meta = document.createElement('meta');" +
  41. "meta.name = 'viewport';" +
  42. "meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';" +
  43. "var head = document.getElementsByTagName('head')[0];" +
  44. "head.appendChild(meta);" +
  45. "$('#header-layout').find('.col-8').removeClass('col-8').addClass('col');" +
  46. "$('#header-layout').find('.col-4').removeClass('col-4').addClass('col');"
  47. let script: WKUserScript = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
  48. contentController.addUserScript(script)
  49. }
  50. override func viewWillAppear(_ animated: Bool) {
  51. let me = UserDefaults.standard.string(forKey: "me")
  52. var myURL : URL?
  53. switch(ViewController.tab3){
  54. case "0":
  55. address = "\(PrefsUtil.getURLBase() ?? "https://qmera.io/")nexilis/pages/tab1-main-only?f_pin=\(me ?? "")"
  56. myURL = URL(string: address)
  57. case "1":
  58. address = "\(PrefsUtil.getURLBase() ?? "https://qmera.io/")nexilis/pages/tab3-main-only?f_pin=\(me ?? "")"
  59. myURL = URL(string: address)
  60. case "2":
  61. address = "\(PrefsUtil.getURLBase() ?? "https://qmera.io/")nexilis/pages/tab1-main?f_pin=\(me ?? "")"
  62. myURL = URL(string: address)
  63. case "3":
  64. address = "\(PrefsUtil.getURLBase() ?? "https://qmera.io/")nexilis/pages/tab3-commerce?f_pin=\(me ?? "")"
  65. myURL = URL(string: address)
  66. default:
  67. if(!ViewController.tab3.isEmpty){
  68. if(ViewController.tab3.lowercased().contains("https://") || ViewController.sURL.lowercased().contains("http://")){
  69. address = ViewController.tab3
  70. myURL = URL(string: address)
  71. }
  72. else {
  73. address = "https://\(ViewController.tab3)"
  74. myURL = URL(string: address)
  75. }
  76. }
  77. }
  78. print(address)
  79. if let u = myURL{
  80. let lang = UserDefaults.standard.string(forKey: "i18n_language")
  81. var intLang = 0
  82. if lang == "id" {
  83. intLang = 1
  84. }
  85. self.webView.evaluateJavaScript("{window.localStorage.lang = \(intLang)}")
  86. let myRequest = URLRequest(url: u)
  87. webView.load(myRequest)
  88. }
  89. self.navigationController?.navigationBar.topItem?.title = Bundle.main.displayName
  90. let cpaasMode = PrefsUtil.getCpaasMode()
  91. let isBurger = cpaasMode == PrefsUtil.CPAAS_MODE_BURGER
  92. // navigationController?.navigationBar.backgroundColor = .white
  93. navigationController?.setNavigationBarHidden(!isBurger, animated: false)
  94. }
  95. func scrollViewDidScroll(_ scrollView: UIScrollView) {
  96. if (self.lastContentOffset > scrollView.contentOffset.y && scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)) {
  97. showTabBar();
  98. }
  99. else if (self.lastContentOffset != 0 && self.lastContentOffset < scrollView.contentOffset.y && self.lastContentOffset >= 0) {
  100. hideTabBar();
  101. }
  102. self.lastContentOffset = scrollView.contentOffset.y
  103. self.collapseDocked()
  104. }
  105. @objc func collapseDocked() {
  106. if ViewController.isExpandButton {
  107. ViewController.expandButton()
  108. }
  109. }
  110. @objc func reloadWebView(_ sender: UIRefreshControl) {
  111. webView.reload()
  112. sender.endRefreshing()
  113. }
  114. func hideTabBar() {
  115. var viewController = UIApplication.shared.windows.first!.rootViewController
  116. if !(viewController is ViewController) {
  117. viewController = self.parent
  118. }
  119. if ViewController.middleButton.isDescendant(of: viewController!.view) {
  120. DispatchQueue.main.async {
  121. if let viewController = viewController as? ViewController {
  122. viewController.tabBar.isHidden = true
  123. }
  124. ViewController.removeMiddleButton()
  125. }
  126. }
  127. }
  128. func showTabBar() {
  129. if(ViewController.alwaysHideButton){
  130. return
  131. }
  132. var viewController = UIApplication.shared.windows.first!.rootViewController
  133. if !(viewController is ViewController) {
  134. viewController = self.parent
  135. }
  136. if !ViewController.middleButton.isDescendant(of: viewController!.view) {
  137. ViewController.isExpandButton = false
  138. if let viewController = viewController as? ViewController {
  139. viewController.tabBar.isHidden = false
  140. viewController.createMidFloatingButton()
  141. }
  142. }
  143. }
  144. func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
  145. scrollView.pinchGestureRecognizer?.isEnabled = false
  146. }
  147. func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
  148. print("KACAU \(message.name)")
  149. if message.name == "checkProfile" {
  150. guard let dict = message.body as? [String: AnyObject],
  151. let param1 = dict["param1"] as? String,
  152. let param2 = dict["param2"] as? String else {
  153. return
  154. }
  155. if ViewController.checkIsChangePerson() {
  156. if param2 == "like" {
  157. self.webView.evaluateJavaScript("likeProduct('\(param1)',true);")
  158. } else if param2 == "comment" {
  159. self.webView.evaluateJavaScript("openComment('\(param1)',true);")
  160. } else if param2 == "report_user" {
  161. self.webView.evaluateJavaScript("reportUser('\(param1)',true);")
  162. } else if param2 == "report_content" {
  163. self.webView.evaluateJavaScript("reportContent('\(param1.split(separator: "|")[0])','\(param1.split(separator: "|")[1])',true);")
  164. } else if param2 == "block_user" {
  165. self.webView.evaluateJavaScript("blockUser('\(param1)',true);")
  166. } else if param2 == "follow_store" {
  167. self.webView.evaluateJavaScript("follow(true);")
  168. } else if param2 == "homepage" {
  169. self.webView.evaluateJavaScript("window.location.href = '\(param1)';")
  170. } else {
  171. self.webView.evaluateJavaScript("openNewPost(true);")
  172. }
  173. } else {
  174. self.webView.evaluateJavaScript("{if(pauseAll){pauseAll();}}")
  175. }
  176. } else if message.name == "setIsProductModalOpen" {
  177. guard let dict = message.body as? [String: AnyObject],
  178. let param1 = dict["param1"] as? Bool else {
  179. return
  180. }
  181. if param1 {
  182. } else {
  183. }
  184. } else if message.name == "toggleVoiceSearch" {
  185. if !isAllowSpeech {
  186. setupSpeech()
  187. } else {
  188. runVoice()
  189. }
  190. } else if message.name == "blockUser" {
  191. guard let dict = message.body as? [String: AnyObject],
  192. let param1 = dict["param1"] as? String,
  193. let param2 = dict["param2"] as? Bool else {
  194. return
  195. }
  196. if param2 {
  197. DispatchQueue.global().async {
  198. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getBlock(l_pin: param1)) {
  199. if response.isOk() {
  200. DispatchQueue.main.async {
  201. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  202. _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
  203. "ex_block" : "1"
  204. ], _where: "f_pin = '\(param1)'")
  205. })
  206. }
  207. }
  208. }
  209. }
  210. } else {
  211. DispatchQueue.global().async {
  212. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getUnBlock(l_pin: param1)) {
  213. if response.isOk() {
  214. DispatchQueue.main.async {
  215. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  216. _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
  217. "ex_block" : "0"
  218. ], _where: "f_pin = '\(param1)'")
  219. })
  220. }
  221. }
  222. }
  223. }
  224. }
  225. } else if message.name == "showAlert" {
  226. guard let dict = message.body as? [String: AnyObject],
  227. let param1 = dict["param1"] as? String else {
  228. return
  229. }
  230. showToast(message: param1, controller: self.tabBarController!)
  231. } else if message.name == "blockUser" {
  232. guard let dict = message.body as? [String: AnyObject],
  233. let param1 = dict["param1"] as? String,
  234. let param2 = dict["param2"] as? Bool else {
  235. return
  236. }
  237. if param2 {
  238. DispatchQueue.global().async {
  239. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getBlock(l_pin: param1)) {
  240. if response.isOk() {
  241. DispatchQueue.main.async {
  242. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  243. _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
  244. "ex_block" : "1"
  245. ], _where: "f_pin = '\(param1)'")
  246. })
  247. }
  248. }
  249. }
  250. }
  251. } else {
  252. DispatchQueue.global().async {
  253. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getUnBlock(l_pin: param1)) {
  254. if response.isOk() {
  255. DispatchQueue.main.async {
  256. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  257. _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: [
  258. "ex_block" : "0"
  259. ], _where: "f_pin = '\(param1)'")
  260. })
  261. }
  262. }
  263. }
  264. }
  265. }
  266. }
  267. }
  268. func setupSpeech() {
  269. self.speechRecognizer?.delegate = self
  270. SFSpeechRecognizer.requestAuthorization { (authStatus) in
  271. var isButtonEnabled = false
  272. switch authStatus {
  273. case .authorized:
  274. isButtonEnabled = true
  275. case .denied:
  276. isButtonEnabled = false
  277. print("User denied access to speech recognition")
  278. case .restricted:
  279. isButtonEnabled = false
  280. print("Speech recognition restricted on this device")
  281. case .notDetermined:
  282. isButtonEnabled = false
  283. print("Speech recognition not yet authorized")
  284. @unknown default:
  285. isButtonEnabled = false
  286. }
  287. OperationQueue.main.addOperation() {
  288. self.isAllowSpeech = isButtonEnabled
  289. if isButtonEnabled {
  290. UserDefaults.standard.set(isButtonEnabled, forKey: "allowSpeech")
  291. self.runVoice()
  292. }
  293. }
  294. }
  295. }
  296. func runVoice() {
  297. if !audioEngine.isRunning {
  298. alertController = UIAlertController(title: "Start Recording".localized(), message: "Say something, I'm listening!".localized(), preferredStyle: .alert)
  299. self.present(alertController, animated: true)
  300. self.webView.evaluateJavaScript("toggleVoiceButton(true)")
  301. self.startRecording()
  302. }
  303. }
  304. func startRecording() {
  305. // Clear all previous session data and cancel task
  306. if recognitionTask != nil {
  307. recognitionTask?.cancel()
  308. recognitionTask = nil
  309. }
  310. // Create instance of audio session to record voice
  311. let audioSession = AVAudioSession.sharedInstance()
  312. do {
  313. try audioSession.setCategory(AVAudioSession.Category.record, mode: .default, options: [])
  314. try audioSession.setMode(AVAudioSession.Mode.measurement)
  315. try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
  316. } catch {
  317. print("audioSession properties weren't set because of an error.")
  318. }
  319. self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
  320. let inputNode = audioEngine.inputNode
  321. guard let recognitionRequest = recognitionRequest else {
  322. fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")
  323. }
  324. recognitionRequest.shouldReportPartialResults = true
  325. self.recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in
  326. var isFinal = false
  327. if result != nil {
  328. let text = result?.bestTranscription.formattedString
  329. isFinal = (result?.isFinal)!
  330. self.alertController.dismiss(animated: true)
  331. self.audioEngine.stop()
  332. self.recognitionRequest?.endAudio()
  333. self.webView.evaluateJavaScript("toggleVoiceButton(false)")
  334. self.webView.evaluateJavaScript("submitVoiceSearch('\(text ?? "")')")
  335. } else {
  336. self.alertController.dismiss(animated: true)
  337. }
  338. if error != nil || isFinal {
  339. self.audioEngine.stop()
  340. inputNode.removeTap(onBus: 0)
  341. self.recognitionRequest = nil
  342. self.recognitionTask = nil
  343. self.isAllowSpeech = true
  344. }
  345. })
  346. let recordingFormat = inputNode.outputFormat(forBus: 0)
  347. inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
  348. self.recognitionRequest?.append(buffer)
  349. }
  350. self.audioEngine.prepare()
  351. do {
  352. try self.audioEngine.start()
  353. } catch {
  354. print("audioEngine couldn't start because of an error.")
  355. }
  356. }
  357. }
  358. extension ThirdTabViewController: SFSpeechRecognizerDelegate {
  359. func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
  360. if available {
  361. self.isAllowSpeech = true
  362. } else {
  363. self.isAllowSpeech = false
  364. }
  365. }
  366. }