Callback.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. //
  2. // Callback.swift
  3. // Runner
  4. //
  5. // Created by Yayan Dwi on 15/04/20.
  6. // Copyright © 2020 The Chromium Authors. All rights reserved.
  7. //
  8. import Foundation
  9. import nuSDKService
  10. import Network
  11. import NotificationBannerSwift
  12. class Callback : CallBack {
  13. var sID: String = "Callback"
  14. func connectionStateChanged(sUserID: String!, sDeviceID: String!, bConState: Bool!, nConType: Int!, nConSubType: Int!, nCLMConStat: UInt8!) {
  15. //print(sUserID, "/", sDeviceID, "/", bConState, "/", nConType, "/", nConSubType, "/", nCLMConStat)
  16. if let dispatch = Nexilis.dispatch, bConState {
  17. dispatch.leave()
  18. }
  19. if let delegate = Nexilis.shared.connectionDelegate {
  20. delegate.connectionStateChanged(userId: sUserID, deviceId: sDeviceID, state: bConState)
  21. }
  22. InquiryThread.default.set(wait: nCLMConStat == 0)
  23. OutgoingThread.default.set(wait: nCLMConStat == 0)
  24. }
  25. func gpsStateChanged(nState: Int!) {
  26. }
  27. func sleepStateChanged(bState: Bool!) {
  28. }
  29. func callStateChanged(nState: Int!, sMessage: String!) -> Int {
  30. // print(nState,"/",sMessage)
  31. if nState == Nexilis.AUDIO_CALL_INCOMING || nState == Nexilis.VIDEO_CALL_INCOMING {
  32. if let delegate = Nexilis.shared.callDelegate {
  33. if !Nexilis.showLibraryNotification || Nexilis.callAPNActivated {
  34. delegate.onStatusCall(state: nState, message: sMessage)
  35. } else {
  36. delegate.onIncomingCall(state: nState, message: sMessage)
  37. }
  38. }
  39. } else {
  40. if let delegate = Nexilis.shared.callDelegate {
  41. delegate.onStatusCall(state: nState, message: sMessage)
  42. }
  43. }
  44. return 1
  45. }
  46. func bcastStateChanged(nState: Int!, sMessage: String!) -> Int {
  47. //print("LS CALLBACK ",nState,"/",sMessage)
  48. if let delegate = Nexilis.shared.streamingDelagate {
  49. delegate.onStartLS(state: nState, message: sMessage)
  50. }
  51. if let delegate = Nexilis.shared.streamingDelagate {
  52. delegate.onJoinLS(state: nState, message: sMessage)
  53. }
  54. if let delegate = Nexilis.shared.seminarDelegate {
  55. delegate.onStartSeminar(state: nState, message: sMessage)
  56. }
  57. if let delegate = Nexilis.shared.seminarDelegate {
  58. delegate.onJoinSeminar(state: nState, message: sMessage)
  59. }
  60. return 1
  61. }
  62. func sshareStateChanged(nState: Int!, sMessage: String!) -> Int {
  63. //print("Screen sharing state: ",nState,"/",sMessage)
  64. switch nState {
  65. case 0:
  66. if (sMessage.starts(with: "Initiating")){
  67. if let delegate = Nexilis.shared.screenSharingDelegate {
  68. delegate.onStartScreenSharing(state: nState, message: sMessage)
  69. }
  70. }
  71. case 12:
  72. if let delegate = Nexilis.shared.screenSharingDelegate {
  73. delegate.onStartScreenSharing(state: nState, message: sMessage)
  74. }
  75. case 22:
  76. if let delegate = Nexilis.shared.screenSharingDelegate {
  77. delegate.onJoinScreenSharing(state: nState, message: sMessage)
  78. }
  79. case 88:
  80. if let delegate = Nexilis.shared.screenSharingDelegate {
  81. delegate.onStartScreenSharing(state: nState, message: sMessage)
  82. }
  83. if let delegate = Nexilis.shared.screenSharingDelegate {
  84. delegate.onJoinScreenSharing(state: nState, message: sMessage)
  85. }
  86. default:
  87. break
  88. }
  89. return 1
  90. }
  91. func incomingData(sPacketID: String!, oData: AnyObject!) throws {
  92. Nexilis.incomingData(packetId: sPacketID!, data: oData!)
  93. }
  94. func lateResponse(sPacketID: String!, sResponse: String!) throws {
  95. }
  96. func asycnACKReceived(sPacketID: String!) throws {
  97. //print("asycnACKReceived: \(sPacketID)")
  98. DispatchQueue.global().async {
  99. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  100. do {
  101. OutgoingThread.default.delOutgoing(fmdb: fmdb, packageId: sPacketID)
  102. } catch {
  103. rollback.pointee = true
  104. print("Access database error: \(error.localizedDescription)")
  105. }
  106. })
  107. }
  108. }
  109. func locationUpdated(lTime: Int64!, sLocationInfo: String!) {
  110. }
  111. func resetDB() {
  112. }
  113. }
  114. class NetworkMonitor {
  115. static let shared = NetworkMonitor()
  116. private let monitor = NWPathMonitor()
  117. private var isMonitoring = false
  118. var isConnected: Bool = false
  119. var fromDisconnect = false
  120. var timerReloadData: Timer?
  121. private var disconnectWorkItem: DispatchWorkItem?
  122. private init() {}
  123. func startMonitoring() {
  124. guard !isMonitoring else { return }
  125. monitor.pathUpdateHandler = { [weak self] path in
  126. guard let self = self else { return }
  127. self.canAccessGoogle { connected in
  128. if connected {
  129. // Cancel any pending "disconnected" work if connection is back
  130. self.disconnectWorkItem?.cancel()
  131. self.disconnectWorkItem = nil
  132. if !self.isConnected {
  133. self.isConnected = true
  134. self.handleConnected()
  135. }
  136. } else {
  137. // Debounce disconnection: wait 3s before declaring "offline"
  138. self.scheduleDisconnectionCheck()
  139. }
  140. }
  141. }
  142. let queue = DispatchQueue.global(qos: .background)
  143. monitor.start(queue: queue)
  144. isMonitoring = true
  145. }
  146. func stopMonitoring() {
  147. guard isMonitoring else { return }
  148. monitor.cancel()
  149. isMonitoring = false
  150. }
  151. private func scheduleDisconnectionCheck() {
  152. // Cancel any previous disconnection task
  153. disconnectWorkItem?.cancel()
  154. let workItem = DispatchWorkItem { [weak self] in
  155. guard let self = self else { return }
  156. self.isConnected = false
  157. self.handleDisconnected()
  158. }
  159. disconnectWorkItem = workItem
  160. // Wait 3 seconds before declaring disconnected
  161. DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: workItem)
  162. }
  163. private func handleDisconnected() {
  164. fromDisconnect = true
  165. DispatchQueue.main.async {
  166. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  167. imageView.tintColor = .white
  168. let banner = FloatingNotificationBanner(
  169. title: "Check your connection".localized(),
  170. subtitle: nil,
  171. titleFont: UIFont.systemFont(ofSize: 16),
  172. titleColor: nil,
  173. titleTextAlign: .left,
  174. subtitleFont: nil,
  175. subtitleColor: nil,
  176. subtitleTextAlign: nil,
  177. leftView: imageView,
  178. rightView: nil,
  179. style: .danger,
  180. colors: nil,
  181. iconPosition: .center
  182. )
  183. banner.show()
  184. if Utils.getSecureFolderEncrypt().isEmpty && Database.shared.database != nil {
  185. self.timerReloadData?.invalidate()
  186. self.timerReloadData = Timer.scheduledTimer(withTimeInterval: 3, repeats: false) { _ in
  187. Database.shared.database = nil
  188. FileEncryption.shared.aesKey = nil
  189. FileEncryption.shared.aesIV = nil
  190. Database.recreateInstance()
  191. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "disconnected_nexilis"), object: nil, userInfo: nil)
  192. if let navigationC = UIApplication.shared.visibleViewController as? UINavigationController {
  193. if navigationC.viewControllers.last is EditorPersonal ||
  194. navigationC.viewControllers.last is EditorGroup {
  195. navigationC.popViewController(animated: true)
  196. }
  197. }
  198. }
  199. }
  200. }
  201. }
  202. private func handleConnected() {
  203. if fromDisconnect {
  204. fromDisconnect = false
  205. DispatchQueue.main.async {
  206. self.timerReloadData?.invalidate()
  207. self.timerReloadData = nil
  208. let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
  209. imageView.tintColor = .white
  210. let banner = FloatingNotificationBanner(
  211. title: "You're Connected".localized(),
  212. subtitle: nil,
  213. titleFont: UIFont.systemFont(ofSize: 16),
  214. titleColor: nil,
  215. titleTextAlign: .left,
  216. subtitleFont: nil,
  217. subtitleColor: nil,
  218. subtitleTextAlign: nil,
  219. leftView: imageView,
  220. rightView: nil,
  221. style: .success,
  222. colors: nil,
  223. iconPosition: .center
  224. )
  225. banner.show()
  226. }
  227. if Database.shared.database == nil {
  228. Nexilis.getFeatureAccess()
  229. }
  230. }
  231. }
  232. func canAccessGoogle(completion: @escaping (Bool) -> Void) {
  233. guard let url = URL(string: "https://www.google.com") else {
  234. completion(false)
  235. return
  236. }
  237. var request = URLRequest(url: url)
  238. request.timeoutInterval = 5
  239. let task = URLSession.shared.dataTask(with: request) { _, response, _ in
  240. if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
  241. completion(true)
  242. } else {
  243. completion(false)
  244. }
  245. }
  246. task.resume()
  247. }
  248. }