APIS.swift 126 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217
  1. //
  2. // APIS.swift
  3. // NexilisLite
  4. //
  5. // Created by Akhmad Al Qindi Irsyam on 05/05/23.
  6. //
  7. import Foundation
  8. import UIKit
  9. import FMDB
  10. import NotificationBannerSwift
  11. import Toast_Swift
  12. import nuSDKService
  13. import AVFoundation
  14. import AVKit
  15. import Intents
  16. public class APIS: NSObject {
  17. private static var isAlertPresented = false
  18. public static func connect(appName: String, apiKey: String, delegate: ConnectDelegate, showButton: Bool = true, fromMAB: Bool = false) {
  19. APIS.appNm = appName.trimmingCharacters(in: .whitespacesAndNewlines)
  20. Nexilis.connect(apiKey: apiKey, delegate: delegate, showButton: showButton, fromMAB: fromMAB)
  21. }
  22. public static func getTotalCounter() -> Int32 {
  23. var counter: Int32?
  24. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  25. do {
  26. let query = """
  27. select SUM(counter) as total_counter
  28. from (
  29. select ms.counter from MESSAGE_SUMMARY ms, MESSAGE m, BUDDY b
  30. where ms.l_pin = b.f_pin and ms.message_id = m.message_id and m.is_call_center = 0
  31. union all
  32. select ms.counter from MESSAGE_SUMMARY ms, MESSAGE m
  33. where ms.l_pin = '-999' and ms.message_id = m.message_id
  34. union all
  35. select ms.counter from MESSAGE_SUMMARY ms, MESSAGE m
  36. where ms.l_pin = '-997' and ms.message_id = m.message_id
  37. union all
  38. select ms.counter from MESSAGE_SUMMARY ms, MESSAGE m, GROUPZ b
  39. where ms.l_pin = b.group_id and ms.message_id = m.message_id and m.is_call_center = 0
  40. union all
  41. select ms.counter from MESSAGE_SUMMARY ms, MESSAGE m, DISCUSSION_FORUM b, GROUPZ c
  42. where b.group_id = c.group_id and ms.l_pin = b.chat_id and ms.message_id = m.message_id and m.is_call_center = 0
  43. ) as subquery
  44. """
  45. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query), cursor.next() {
  46. counter = cursor.int(forColumnIndex: 0)
  47. cursor.close()
  48. }
  49. } catch {
  50. rollback.pointee = true
  51. print("Access database error: \(error.localizedDescription)")
  52. }
  53. })
  54. return counter ?? 0
  55. }
  56. private static func showChangeProfile() {
  57. guard !isAlertPresented else { return }
  58. isAlertPresented = true
  59. let alert = LibAlertController(title: "Set Profile".localized(), message: "You must set your profile to use this feature".localized(), preferredStyle: .alert)
  60. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  61. isAlertPresented = false
  62. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  63. controller.forceLogin = true
  64. let navigationController = CustomNavigationController(rootViewController: controller)
  65. navigationController.defaultStyle()
  66. if UIApplication.shared.visibleViewController?.navigationController != nil {
  67. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  68. } else {
  69. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  70. }
  71. }))
  72. if UIApplication.shared.visibleViewController?.navigationController != nil {
  73. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  74. } else {
  75. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  76. }
  77. }
  78. public static func openContactCenter(media: Int? = nil, category: Int? = nil) {
  79. let isChangeProfile = Utils.getSetProfile()
  80. if !isChangeProfile {
  81. APIS.showChangeProfile()
  82. return
  83. }
  84. if !Nexilis.checkingAccess(key: "call_center") {
  85. if Nexilis.checkingAccessAlert(key: "call_center") != "|" && !Nexilis.checkingAccessAlert(key: "call_center").isEmpty {
  86. let title = Nexilis.checkingAccessAlert(key: "call_center").components(separatedBy: "|")[0]
  87. let message = Nexilis.checkingAccessAlert(key: "call_center").components(separatedBy: "|")[1]
  88. APIS.nexilisShowAlertWithHTMLMessage(on: UIApplication.shared.visibleViewController ?? UIViewController(), title: title, message: message)
  89. } else {
  90. UIApplication.shared.visibleViewController?.view.makeToast("Feature disabled".localized(), duration: 5)
  91. }
  92. return
  93. }
  94. if User.isCallCenter(userType: (User.getData(pin: User.getMyPin())?.userType)!) {
  95. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "myHistoryCC") as! HistoryCCViewController
  96. controller.isOfficer = true
  97. controller.fromAPI = true
  98. let navigationController = CustomNavigationController(rootViewController: controller)
  99. navigationController.setNavigationBarHidden(false, animated: false)
  100. navigationController.navigationBar.isTranslucent = false
  101. navigationController.defaultStyle()
  102. if UIApplication.shared.visibleViewController?.navigationController != nil {
  103. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  104. } else {
  105. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  106. }
  107. } else {
  108. if media != nil || (media == nil && category != nil) {
  109. if media == nil || media! < 0 || media! > 2 {
  110. UIApplication.shared.visibleViewController?.view.makeToast("108:Invalid Contact Center media parameter (0:Chat, 1:Audio Call, 2:Video Call)".localized(), duration: 3)
  111. return
  112. }
  113. }
  114. if category != nil {
  115. if category != 0 {
  116. let service = CategoryCC.getDataFromServiceId(service_id: "\(category!)")
  117. if service == nil {
  118. UIApplication.shared.visibleViewController?.view.makeToast("109:Invalid Contact Center category parameter".localized(), duration: 3)
  119. return
  120. }
  121. let serviceChilds = CategoryCC.getDatafromParent(parent: service!.service_id)
  122. if serviceChilds.count > 0 {
  123. UIApplication.shared.visibleViewController?.view.makeToast("109:Invalid Contact Center category parameter".localized(), duration: 3)
  124. return
  125. }
  126. }
  127. }
  128. let isWaitingRequestCC: Bool = SecureUserDefaults.shared.value(forKey: "waitingRequestCC") ?? false
  129. if isWaitingRequestCC {
  130. let imageView = UIImageView(image: UIImage(systemName: "info.circle"))
  131. imageView.tintColor = .white
  132. let banner = FloatingNotificationBanner(title: "You have requested Call Center, please wait for response.".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .info, colors: nil, iconPosition: .center)
  133. banner.show()
  134. return
  135. }
  136. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  137. controller.isContactCenter = true
  138. if media != nil {
  139. controller.isDirectCC = true
  140. controller.channelContactCenter = "\(media!)"
  141. controller.serviceIdCC = category == nil ? "" : "\(category!)"
  142. }
  143. let navigationController = CustomNavigationController(rootViewController: controller)
  144. navigationController.defaultStyle()
  145. if UIApplication.shared.visibleViewController?.navigationController != nil {
  146. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  147. } else {
  148. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  149. }
  150. }
  151. }
  152. public static func openUrl(url: String) {
  153. let isChangeProfile = Utils.getSetProfile()
  154. if !isChangeProfile {
  155. APIS.showChangeProfile()
  156. return
  157. }
  158. let controller = BNIBookingWebView()
  159. controller.customUrl = url
  160. let navigationController = CustomNavigationController(rootViewController: controller)
  161. navigationController.defaultStyle()
  162. if UIApplication.shared.visibleViewController?.navigationController != nil {
  163. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  164. } else {
  165. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  166. }
  167. }
  168. public static func openNotificationCenter() {
  169. let isChangeProfile = Utils.getSetProfile()
  170. if !isChangeProfile {
  171. APIS.showChangeProfile()
  172. return
  173. }
  174. if !Nexilis.checkingAccess(key: "notification_center") {
  175. UIApplication.shared.visibleViewController?.view.makeToast("Feature disabled".localized(), duration: 5)
  176. return
  177. }
  178. let controller = HistoryBroadcastViewController()
  179. let navigationController = CustomNavigationController(rootViewController: controller)
  180. navigationController.defaultStyle()
  181. if UIApplication.shared.visibleViewController?.navigationController != nil {
  182. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  183. } else {
  184. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  185. }
  186. }
  187. public static func openChat() {
  188. let isChangeProfile = Utils.getSetProfile()
  189. if !isChangeProfile {
  190. APIS.showChangeProfile()
  191. return
  192. }
  193. let navigationController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactChatNav") as! UINavigationController
  194. Utils.addBackground(view: navigationController.view)
  195. let vc = navigationController.topViewController as! ContactChatViewController
  196. vc.noUCList = true
  197. navigationController.defaultStyle()
  198. if UIApplication.shared.visibleViewController?.navigationController != nil {
  199. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  200. } else {
  201. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  202. }
  203. }
  204. public static func openSmartChatbot() {
  205. let isChangeProfile = Utils.getSetProfile()
  206. if !isChangeProfile {
  207. APIS.showChangeProfile()
  208. return
  209. }
  210. let smartChatVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "chatGptVC") as! ChatGPTBotView
  211. smartChatVC.hidesBottomBarWhenPushed = true
  212. let navigationController = CustomNavigationController(rootViewController: smartChatVC)
  213. navigationController.defaultStyle()
  214. if UIApplication.shared.visibleViewController?.navigationController != nil {
  215. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  216. } else {
  217. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  218. }
  219. }
  220. public static func startChat(name: String) {
  221. if name.isEmpty {
  222. UIApplication.shared.visibleViewController?.view.makeToast("92:Username is empty".localized(), duration: 2)
  223. return
  224. }
  225. let user = User.getDataFromNameCanNil(name: name)
  226. if user == nil {
  227. UIApplication.shared.visibleViewController?.view.makeToast("91:Invalid name or you must add Username to your contact first".localized(), duration: 3)
  228. return
  229. }
  230. let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  231. editorPersonalVC.hidesBottomBarWhenPushed = true
  232. editorPersonalVC.unique_l_pin = user!.pin
  233. editorPersonalVC.fromNotification = true
  234. let navigationController = CustomNavigationController(rootViewController: editorPersonalVC)
  235. navigationController.modalPresentationStyle = .fullScreen
  236. navigationController.navigationBar.tintColor = .white
  237. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  238. navigationController.navigationBar.isTranslucent = false
  239. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  240. navigationController.navigationBar.barStyle = .black
  241. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  242. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  243. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  244. navigationController.navigationBar.titleTextAttributes = textAttributes
  245. if UIApplication.shared.visibleViewController?.navigationController != nil {
  246. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  247. } else {
  248. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  249. }
  250. }
  251. public static func openCall() {
  252. let isChangeProfile = Utils.getSetProfile()
  253. if !isChangeProfile {
  254. APIS.showChangeProfile()
  255. return
  256. }
  257. let callContact = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactSID")
  258. let navigationController = CustomNavigationController(rootViewController: callContact)
  259. navigationController.defaultStyle()
  260. if UIApplication.shared.visibleViewController?.navigationController != nil {
  261. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  262. } else {
  263. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  264. }
  265. }
  266. public static func openStreaming() {
  267. let isChangeProfile = Utils.getSetProfile()
  268. if !isChangeProfile {
  269. APIS.showChangeProfile()
  270. return
  271. }
  272. if !Nexilis.checkingAccess(key: "live_streaming") {
  273. if Nexilis.checkingAccessAlert(key: "live_streaming") != "|" && !Nexilis.checkingAccessAlert(key: "live_streaming").isEmpty {
  274. let title = Nexilis.checkingAccessAlert(key: "live_streaming").components(separatedBy: "|")[0]
  275. let message = Nexilis.checkingAccessAlert(key: "live_streaming").components(separatedBy: "|")[1]
  276. APIS.nexilisShowAlertWithHTMLMessage(on: UIApplication.shared.visibleViewController ?? UIViewController(), title: title, message: message)
  277. } else {
  278. UIApplication.shared.visibleViewController?.view.makeToast("Feature disabled".localized(), duration: 5)
  279. }
  280. return
  281. }
  282. let navigationController = CustomNavigationController(rootViewController: QmeraCreateStreamingViewController())
  283. navigationController.defaultStyle()
  284. if UIApplication.shared.visibleViewController?.navigationController != nil {
  285. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  286. } else {
  287. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  288. }
  289. }
  290. public static func openConference() {
  291. let isChangeProfile = Utils.getSetProfile()
  292. if !isChangeProfile {
  293. APIS.showChangeProfile()
  294. return
  295. }
  296. if !Nexilis.checkingAccess(key: "vconf_room") {
  297. if Nexilis.checkingAccessAlert(key: "vconf_room") != "|" && !Nexilis.checkingAccessAlert(key: "vconf_room").isEmpty {
  298. let title = Nexilis.checkingAccessAlert(key: "vconf_room").components(separatedBy: "|")[0]
  299. let message = Nexilis.checkingAccessAlert(key: "vconf_room").components(separatedBy: "|")[1]
  300. APIS.nexilisShowAlertWithHTMLMessage(on: UIApplication.shared.visibleViewController ?? UIViewController(), title: title, message: message)
  301. } else {
  302. UIApplication.shared.visibleViewController?.view.makeToast("Feature disabled".localized(), duration: 5)
  303. }
  304. return
  305. }
  306. let navigationController = CustomNavigationController(rootViewController: CreateSeminarViewController())
  307. navigationController.defaultStyle()
  308. if UIApplication.shared.visibleViewController?.navigationController != nil {
  309. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  310. } else {
  311. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  312. }
  313. }
  314. public static func openAudioCall() {
  315. let isChangeProfile = Utils.getSetProfile()
  316. if !isChangeProfile {
  317. APIS.showChangeProfile()
  318. return
  319. }
  320. if !Nexilis.checkingAccess(key: "audio_call") {
  321. UIApplication.shared.visibleViewController?.view.makeToast("Feature disabled".localized(), duration: 5)
  322. return
  323. }
  324. let callContact = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactSID") as! ContactCallViewController
  325. callContact.onlyAudioOrVideo = 1
  326. let navigationController = CustomNavigationController(rootViewController: callContact)
  327. navigationController.defaultStyle()
  328. if UIApplication.shared.visibleViewController?.navigationController != nil {
  329. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  330. } else {
  331. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  332. }
  333. }
  334. public static func startAudioCall(name: String) {
  335. if name.isEmpty {
  336. UIApplication.shared.visibleViewController?.view.makeToast("92:Username is empty".localized(), duration: 3)
  337. return
  338. }
  339. if !Nexilis.checkingAccess(key: "audio_call") {
  340. UIApplication.shared.visibleViewController?.view.makeToast("Feature disabled".localized(), duration: 5)
  341. return
  342. }
  343. let user = User.getDataFromNameCanNil(name: name)
  344. if user == nil {
  345. UIApplication.shared.visibleViewController?.view.makeToast("91:Invalid name or you must add Username to your contact first".localized(), duration: 3)
  346. return
  347. }
  348. if !CheckConnection.isConnectedToNetwork() {
  349. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  350. imageView.tintColor = .white
  351. let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
  352. banner.show()
  353. return
  354. }
  355. let controller = QmeraAudioViewController()
  356. controller.user = user
  357. controller.isOutgoing = true
  358. controller.modalPresentationStyle = .overFullScreen
  359. if UIApplication.shared.visibleViewController?.navigationController != nil {
  360. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  361. } else {
  362. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  363. }
  364. }
  365. public static func openVideoCall() {
  366. let isChangeProfile = Utils.getSetProfile()
  367. if !isChangeProfile {
  368. APIS.showChangeProfile()
  369. return
  370. }
  371. if !Nexilis.checkingAccess(key: "video_call") {
  372. UIApplication.shared.visibleViewController?.view.makeToast("Feature disabled".localized(), duration: 5)
  373. return
  374. }
  375. let callContact = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactSID") as! ContactCallViewController
  376. callContact.onlyAudioOrVideo = 2
  377. let navigationController = CustomNavigationController(rootViewController: callContact)
  378. navigationController.defaultStyle()
  379. if UIApplication.shared.visibleViewController?.navigationController != nil {
  380. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  381. } else {
  382. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  383. }
  384. }
  385. public static func startVideoCall(name: String) {
  386. if name.isEmpty {
  387. UIApplication.shared.visibleViewController?.view.makeToast("92:Username is empty".localized(), duration: 3)
  388. return
  389. }
  390. if !Nexilis.checkingAccess(key: "video_call") {
  391. UIApplication.shared.visibleViewController?.view.makeToast("Feature disabled".localized(), duration: 5)
  392. return
  393. }
  394. let user = User.getDataFromNameCanNil(name: name)
  395. if user == nil {
  396. UIApplication.shared.visibleViewController?.view.makeToast("91:Invalid name or you must add Username to your contact first".localized(), duration: 3)
  397. return
  398. }
  399. if !CheckConnection.isConnectedToNetwork() {
  400. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  401. imageView.tintColor = .white
  402. let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
  403. banner.show()
  404. return
  405. }
  406. let videoVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
  407. var data: [String: String?] = [:]
  408. data["f_pin"] = user!.pin
  409. data["name"] = user!.fullName
  410. data["picture"] = user!.thumb
  411. data["isOfficial"] = user!.official
  412. data["deviceId"] = user!.device_id
  413. data["isOffline"] = user!.offline_mode
  414. data["user_type"] = user!.userType
  415. videoVC.dataPerson.append(data)
  416. videoVC.isPresent = true
  417. videoVC.modalPresentationStyle = .overFullScreen
  418. if UIApplication.shared.visibleViewController?.navigationController != nil {
  419. UIApplication.shared.visibleViewController?.navigationController?.present(videoVC, animated: true, completion: nil)
  420. } else {
  421. UIApplication.shared.visibleViewController?.present(videoVC, animated: true, completion: nil)
  422. }
  423. }
  424. public static func openBroadcastForm() {
  425. let isChangeProfile = Utils.getSetProfile()
  426. if !isChangeProfile {
  427. APIS.showChangeProfile()
  428. return
  429. }
  430. if !Nexilis.checkingAccess(key: "broadcast_message") {
  431. UIApplication.shared.visibleViewController?.view.makeToast("Feature disabled".localized(), duration: 5)
  432. return
  433. }
  434. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "broadcastNav")
  435. if UIApplication.shared.visibleViewController?.navigationController != nil {
  436. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  437. } else {
  438. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  439. }
  440. }
  441. public static func openConversation() {
  442. let isChangeProfile = Utils.getSetProfile()
  443. if !isChangeProfile {
  444. APIS.showChangeProfile()
  445. return
  446. }
  447. let navigationController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactChatNav") as! UINavigationController
  448. Utils.addBackground(view: navigationController.view)
  449. navigationController.defaultStyle()
  450. if UIApplication.shared.visibleViewController?.navigationController != nil {
  451. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  452. } else {
  453. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  454. }
  455. }
  456. public static func openFavoriteMessage() {
  457. let isChangeProfile = Utils.getSetProfile()
  458. if !isChangeProfile {
  459. APIS.showChangeProfile()
  460. return
  461. }
  462. let editorStaredVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "staredVC") as! EditorStarMessages
  463. editorStaredVC.fromNotification = true
  464. let navigationController = CustomNavigationController(rootViewController: editorStaredVC)
  465. navigationController.defaultStyle()
  466. if UIApplication.shared.visibleViewController?.navigationController != nil {
  467. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  468. } else {
  469. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  470. }
  471. }
  472. public static func openSecureFolder() {
  473. let isChangeProfile = Utils.getSetProfile()
  474. if !isChangeProfile {
  475. APIS.showChangeProfile()
  476. return
  477. }
  478. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "secureFolderView") as! SecureFolderViewController
  479. let navigationController = CustomNavigationController(rootViewController: controller)
  480. navigationController.defaultStyle()
  481. if UIApplication.shared.visibleViewController?.navigationController != nil {
  482. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  483. } else {
  484. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  485. }
  486. }
  487. public static func openSecureBrowser() {
  488. let isChangeProfile = Utils.getSetProfile()
  489. if !isChangeProfile {
  490. APIS.showChangeProfile()
  491. return
  492. }
  493. let controller = BNIBookingWebView()
  494. controller.isSecureBrowser = true
  495. let navigationController = CustomNavigationController(rootViewController: controller)
  496. navigationController.defaultStyle()
  497. if UIApplication.shared.visibleViewController?.navigationController != nil {
  498. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  499. } else {
  500. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  501. }
  502. }
  503. public static func createCommunity() {
  504. let isChangeProfile = Utils.getSetProfile()
  505. if !isChangeProfile {
  506. APIS.showChangeProfile()
  507. return
  508. }
  509. let startedNewCommunity = UIViewController()
  510. if let viewComm = startedNewCommunity.view {
  511. viewComm.backgroundColor = .black.withAlphaComponent(0.1)
  512. let containerView = UIView()
  513. viewComm.addSubview(containerView)
  514. containerView.anchor(left: viewComm.leftAnchor, bottom: viewComm.bottomAnchor, right: viewComm.rightAnchor, minHeight: 40)
  515. containerView.backgroundColor = .white
  516. containerView.layer.cornerRadius = 15
  517. containerView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
  518. let closeButton = UIButton(type: .close)
  519. containerView.addSubview(closeButton)
  520. closeButton.anchor(top: containerView.topAnchor, right: containerView.rightAnchor, paddingTop: 10, paddingRight: 10, width: 30, height: 30)
  521. closeButton.layer.cornerRadius = 15
  522. closeButton.clipsToBounds = true
  523. closeButton.backgroundColor = .lightGray.withAlphaComponent(0.1)
  524. let config = UIImage.SymbolConfiguration(pointSize: 18, weight: .semibold)
  525. closeButton.setImage(UIImage(systemName: "xmark", withConfiguration: config), for: .normal)
  526. closeButton.addAction(UIAction { _ in
  527. startedNewCommunity.dismiss(animated: true)
  528. }, for: .touchUpInside)
  529. let imageComm = UIImageView(image: UIImage(named: "pb_community_social", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!)
  530. containerView.addSubview(imageComm)
  531. imageComm.anchor(top: closeButton.bottomAnchor, paddingTop: -40, centerX: containerView.centerXAnchor, width: 350, height: 250)
  532. let titleComm = UILabel()
  533. containerView.addSubview(titleComm)
  534. titleComm.anchor(top: imageComm.bottomAnchor, left: containerView.leftAnchor, right: containerView.rightAnchor, paddingLeft: 20, paddingRight: 20)
  535. titleComm.font = .boldSystemFont(ofSize: 30)
  536. titleComm.textColor = .label
  537. titleComm.numberOfLines = 0
  538. titleComm.textAlignment = .center
  539. titleComm.text = "Create a new community".localized()
  540. let descComm = UILabel()
  541. containerView.addSubview(descComm)
  542. descComm.anchor(top: titleComm.bottomAnchor, left: containerView.leftAnchor, right: containerView.rightAnchor, paddingTop: 8, paddingLeft: 20, paddingRight: 20)
  543. descComm.font = .systemFont(ofSize: 16)
  544. descComm.textColor = .label
  545. descComm.numberOfLines = 0
  546. descComm.textAlignment = .center
  547. descComm.text = "Bring together a neighborhood, school or more. Create topic-based groups for members, and easily send them admin anouncements.".localized()
  548. let buttonComm = UIButton(type: .custom)
  549. containerView.addSubview(buttonComm)
  550. buttonComm.anchor(top: descComm.bottomAnchor, left: containerView.leftAnchor, bottom: containerView.bottomAnchor, right: containerView.rightAnchor, paddingTop: 20, paddingLeft: 20, paddingBottom: 20, paddingRight: 20, height: 45)
  551. buttonComm.backgroundColor = .whatsappGreenColor
  552. buttonComm.layer.cornerRadius = 15
  553. buttonComm.clipsToBounds = true
  554. buttonComm.setTitle("Get started".localized(), for: .normal)
  555. buttonComm.setTitleColor(.white, for: .normal)
  556. buttonComm.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
  557. buttonComm.addAction(UIAction { _ in
  558. startedNewCommunity.dismiss(animated: true) {
  559. let navigationController = UINavigationController(rootViewController: CommunityNew())
  560. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  561. }
  562. }, for: .touchUpInside)
  563. }
  564. startedNewCommunity.modalPresentationStyle = .overCurrentContext
  565. if UIApplication.shared.visibleViewController?.navigationController != nil {
  566. UIApplication.shared.visibleViewController?.navigationController?.present(startedNewCommunity, animated: true, completion: nil)
  567. } else {
  568. UIApplication.shared.visibleViewController?.present(startedNewCommunity, animated: true, completion: nil)
  569. }
  570. }
  571. public static func openCreateGroup() {
  572. let isChangeProfile = Utils.getSetProfile()
  573. if !isChangeProfile {
  574. APIS.showChangeProfile()
  575. return
  576. }
  577. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "createGroupNav") as! UINavigationController
  578. Utils.addBackground(view: controller.view)
  579. let vc = controller.topViewController as! GroupCreateViewController
  580. vc.isDismiss = { id in
  581. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "groupDetailView") as! GroupDetailViewController
  582. controller.data = id
  583. controller.fromNotification = true
  584. let navigationController = CustomNavigationController(rootViewController: controller)
  585. navigationController.defaultStyle()
  586. DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
  587. if UIApplication.shared.visibleViewController?.navigationController != nil {
  588. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  589. } else {
  590. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  591. }
  592. })
  593. }
  594. controller.defaultStyle()
  595. if UIApplication.shared.visibleViewController?.navigationController != nil {
  596. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  597. } else {
  598. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  599. }
  600. }
  601. public static func openAddFriend() {
  602. let isChangeProfile = Utils.getSetProfile()
  603. if !isChangeProfile {
  604. APIS.showChangeProfile()
  605. return
  606. }
  607. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "addFriendNav") as! UINavigationController
  608. Utils.addBackground(view: controller.view)
  609. controller.defaultStyle()
  610. if UIApplication.shared.visibleViewController?.navigationController != nil {
  611. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  612. } else {
  613. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  614. }
  615. }
  616. public static func openSignUpOrSignIn() {
  617. let isChangeProfile = Utils.getSetProfile()
  618. if !isChangeProfile {
  619. APIS.showChangeProfile()
  620. return
  621. }
  622. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  623. controller.forceLogin = true
  624. let navigationController = CustomNavigationController(rootViewController: controller)
  625. navigationController.defaultStyle()
  626. if UIApplication.shared.visibleViewController?.navigationController != nil {
  627. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  628. } else {
  629. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  630. }
  631. }
  632. public static func openSetting() {
  633. let navigationController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "settingNav") as! UINavigationController
  634. let vc = navigationController.rootViewController as! SettingTableViewController
  635. vc.fromAPI = true
  636. Utils.addBackground(view: navigationController.view)
  637. navigationController.defaultStyle()
  638. if UIApplication.shared.visibleViewController is UINavigationController && (UIApplication.shared.visibleViewController as! UINavigationController).rootViewController is SettingTableViewController {
  639. return
  640. }
  641. if UIApplication.shared.visibleViewController?.navigationController != nil {
  642. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  643. } else {
  644. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  645. }
  646. }
  647. public static func openProfile() {
  648. let isChangeProfile = Utils.getSetProfile()
  649. if !isChangeProfile {
  650. APIS.showChangeProfile()
  651. return
  652. }
  653. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "profileView") as! ProfileViewController
  654. controller.data = User.getMyPin()!
  655. controller.flag = .me
  656. controller.fromAPI = true
  657. controller.dismissImage = { image, imageName in
  658. var dataImage: [AnyHashable : Any] = [:]
  659. dataImage["name"] = imageName
  660. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "imageFBUpdate"), object: nil, userInfo: dataImage)
  661. }
  662. let navigationController = CustomNavigationController(rootViewController: controller)
  663. navigationController.defaultStyle()
  664. if UIApplication.shared.visibleViewController?.navigationController != nil {
  665. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  666. } else {
  667. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  668. }
  669. }
  670. public static func openChatWallpaper(){
  671. let isChangeProfile = Utils.getSetProfile()
  672. if !isChangeProfile {
  673. APIS.showChangeProfile()
  674. return
  675. }
  676. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "chatWallpaper") as! ChatWallpaperViewController
  677. let navigationController = CustomNavigationController(rootViewController: controller)
  678. navigationController.defaultStyle()
  679. if UIApplication.shared.visibleViewController?.navigationController != nil {
  680. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  681. } else {
  682. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  683. }
  684. }
  685. public static func openWhiteboard() {
  686. let isChangeProfile = Utils.getSetProfile()
  687. if !isChangeProfile {
  688. APIS.showChangeProfile()
  689. return
  690. }
  691. let callContact = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactSID") as! ContactCallViewController
  692. callContact.startWhiteBoard = true
  693. let navigationController = CustomNavigationController(rootViewController: callContact)
  694. navigationController.defaultStyle()
  695. if UIApplication.shared.visibleViewController?.navigationController != nil {
  696. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  697. } else {
  698. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  699. }
  700. }
  701. public static func startWhiteboard(name: String) {
  702. if name.isEmpty {
  703. UIApplication.shared.visibleViewController?.view.makeToast("92:Username is empty".localized(), duration: 3)
  704. return
  705. }
  706. let user = User.getDataFromNameCanNil(name: name)
  707. if user == nil {
  708. UIApplication.shared.visibleViewController?.view.makeToast("91:Invalid name or you must add Username to your contact first".localized(), duration: 3)
  709. return
  710. }
  711. if !CheckConnection.isConnectedToNetwork() {
  712. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  713. imageView.tintColor = .white
  714. let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
  715. banner.show()
  716. return
  717. }
  718. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "wbVC") as! WhiteboardViewController
  719. controller.modalPresentationStyle = .overFullScreen
  720. controller.fromContact = 0
  721. controller.user = user
  722. if UIApplication.shared.visibleViewController?.navigationController != nil {
  723. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  724. } else {
  725. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  726. }
  727. }
  728. // public static func openScreenSharing() {
  729. // let isChangeProfile = Utils.getSetProfile()
  730. // if !isChangeProfile {
  731. // APIS.showChangeProfile()
  732. // return
  733. // }
  734. // let callContact = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactSID") as! ContactCallViewController
  735. // callContact.startSS = true
  736. // let navigationController = CustomNavigationController(rootViewController: callContact)
  737. // navigationController.defaultStyle()
  738. // if UIApplication.shared.visibleViewController?.navigationController != nil {
  739. // UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  740. // } else {
  741. // UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  742. // }
  743. // }
  744. public static func startScreenSharing(name: String) {
  745. if name.isEmpty {
  746. UIApplication.shared.visibleViewController?.view.makeToast("92:Username is empty".localized(), duration: 3)
  747. return
  748. }
  749. let user = User.getDataFromNameCanNil(name: name)
  750. if user == nil {
  751. UIApplication.shared.visibleViewController?.view.makeToast("91:Invalid name or you must add Username to your contact first".localized(), duration: 3)
  752. return
  753. }
  754. if !CheckConnection.isConnectedToNetwork() {
  755. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  756. imageView.tintColor = .white
  757. let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
  758. banner.show()
  759. return
  760. }
  761. let controller = ScreenSharingViewController()
  762. controller.modalPresentationStyle = .overFullScreen
  763. controller.fromContact = 0
  764. controller.user = user
  765. if UIApplication.shared.visibleViewController?.navigationController != nil {
  766. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  767. } else {
  768. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  769. }
  770. }
  771. public static func openWhiteboardAndScreenSharing() {
  772. let isChangeProfile = Utils.getSetProfile()
  773. if !isChangeProfile {
  774. APIS.showChangeProfile()
  775. return
  776. }
  777. let callContact = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "contactSID") as! ContactCallViewController
  778. callContact.startSS = true
  779. callContact.startWhiteBoard = true
  780. let navigationController = CustomNavigationController(rootViewController: callContact)
  781. navigationController.defaultStyle()
  782. if UIApplication.shared.visibleViewController?.navigationController != nil {
  783. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  784. } else {
  785. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  786. }
  787. }
  788. public static func signInAdmin(password: String) {
  789. if password.isEmpty {
  790. UIApplication.shared.visibleViewController?.view.makeToast("113:Password is empty".localized(), duration: 3)
  791. return
  792. }
  793. let isChangeProfile = Utils.getSetProfile()
  794. if !isChangeProfile {
  795. APIS.showChangeProfile()
  796. return
  797. }
  798. let isAdmin = User.isAdmin()
  799. if isAdmin {
  800. UIApplication.shared.visibleViewController?.view.makeToast("112:You already login or registered as Admin".localized(), duration: 3)
  801. return
  802. }
  803. if !CheckConnection.isConnectedToNetwork() || API.nGetCLXConnState() == 0 {
  804. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  805. imageView.tintColor = .white
  806. let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
  807. banner.show()
  808. return
  809. }
  810. Nexilis.showLoader()
  811. self.signInAdmin(password: password, completion: { result in
  812. if result {
  813. DispatchQueue.main.async {
  814. Nexilis.hideLoader {
  815. let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
  816. imageView.tintColor = .white
  817. let banner = FloatingNotificationBanner(title: "Successfully Sign-In Admin".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
  818. banner.show()
  819. }
  820. }
  821. } else {
  822. DispatchQueue.main.async {
  823. Nexilis.hideLoader {}
  824. }
  825. }
  826. })
  827. }
  828. private static func signInAdmin(password: String, completion: @escaping (Bool) -> ()) {
  829. DispatchQueue.global().async {
  830. let idMe = User.getMyPin() as String?
  831. let p_password = password
  832. let md5Hex = p_password
  833. var result: Bool = false
  834. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignInApiAdmin(p_name: idMe!, p_password: md5Hex)) {
  835. if response.isOk() {
  836. result = true
  837. }
  838. DispatchQueue.main.async {
  839. if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "11" {
  840. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  841. imageView.tintColor = .white
  842. let banner = FloatingNotificationBanner(title: "Username or password does not match".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
  843. banner.show()
  844. } else if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "20" {
  845. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  846. imageView.tintColor = .white
  847. let banner = FloatingNotificationBanner(title: "Invalid password".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
  848. banner.show()
  849. }
  850. }
  851. } else {
  852. DispatchQueue.main.async {
  853. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  854. imageView.tintColor = .white
  855. let banner = FloatingNotificationBanner(title: "Unable to access servers".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .top)
  856. banner.show()
  857. }
  858. }
  859. completion(result)
  860. }
  861. }
  862. public static func openSetAsOfficerForm() {
  863. let isChangeProfile = Utils.getSetProfile()
  864. if !isChangeProfile {
  865. APIS.showChangeProfile()
  866. return
  867. }
  868. let isAdmin = User.isAdmin()
  869. if !isAdmin {
  870. UIApplication.shared.visibleViewController?.view.makeToast("111:You must Sign In as Admin to use this feature".localized(), duration: 3)
  871. return
  872. }
  873. let controller = SetInternalCSAccount()
  874. controller.isSetCS = true
  875. controller.fromNotification = true
  876. let navigationController = CustomNavigationController(rootViewController: controller)
  877. navigationController.defaultStyle()
  878. if UIApplication.shared.visibleViewController?.navigationController != nil {
  879. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  880. } else {
  881. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  882. }
  883. }
  884. public static func sendSMS(phoneNumber: String, message: String = ""){
  885. let formattedNumber = phoneNumber.replacingOccurrences(of: "-", with: "")
  886. let urlStringEncoded = message.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
  887. let paramMessage = message.isEmpty ? "" : "&body=\(urlStringEncoded!)"
  888. let url = URL(string: "sms:\(formattedNumber)\(paramMessage)")
  889. if UIApplication.shared.canOpenURL(url!) {
  890. UIApplication.shared.open(url!)
  891. }
  892. }
  893. public static func sendWhatsapp(phoneNumber: String, message: String = "") {
  894. let formattedNumber = phoneNumber.replacingOccurrences(of: "+", with: "").replacingOccurrences(of: "-", with: "")
  895. let urlStringEncoded = message.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
  896. let paramMessage = message.isEmpty ? "" : "?text=\(urlStringEncoded!)"
  897. let url = URL(string: "https://wa.me/\(formattedNumber)\(paramMessage)")
  898. if UIApplication.shared.canOpenURL(url!) {
  899. UIApplication.shared.open(url!, options: [:]) { (success) in
  900. // if success {
  901. // //print("WhatsApp accessed successfully")
  902. // } else {
  903. // //print("Error accessing WhatsApp")
  904. // }
  905. }
  906. }
  907. }
  908. public static func changeUsername(uname: String) {
  909. let isChangeProfile = Utils.getSetProfile()
  910. if !isChangeProfile {
  911. APIS.showChangeProfile()
  912. return
  913. }
  914. let finalUname = uname.replacingOccurrences(of: "[\\n\\r\\t~%()\"]", with: "", options: .regularExpression)
  915. if finalUname == User.getData(pin: User.getMyPin())?.fullName {
  916. UIApplication.shared.visibleViewController?.view.makeToast("102:Duplicate username".localized(), duration: 3)
  917. return
  918. }
  919. if finalUname.count == 0 {
  920. UIApplication.shared.visibleViewController?.view.makeToast("103:Username is empty".localized(), duration: 3)
  921. return
  922. }
  923. if finalUname.count < 3 {
  924. UIApplication.shared.visibleViewController?.view.makeToast("104:Username length is too short".localized(), duration: 3)
  925. return
  926. }
  927. let a = finalUname.split(separator: " ", maxSplits: 1)
  928. let first = String(a[0])
  929. let last = a.count == 2 ? String(a[1]) : ""
  930. DispatchQueue.global().async {
  931. if let resp = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangePersonInfoName(firstname: first, lastname: last)) {
  932. if resp.isOk() {
  933. Database.shared.database?.inTransaction({ fmdb, rollback in
  934. do {
  935. _ = Database.shared.updateRecord(fmdb: fmdb, table: "BUDDY", cvalues: ["first_name": first , "last_name": last], _where: "f_pin = '\(User.getMyPin())'")
  936. } catch {
  937. rollback.pointee = true
  938. print("Access database error: \(error.localizedDescription)")
  939. }
  940. })
  941. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateFifthTab"), object: nil, userInfo: nil)
  942. DispatchQueue.main.async {
  943. Nexilis.hideLoader {
  944. let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
  945. imageView.tintColor = .white
  946. let banner = FloatingNotificationBanner(title: "Successfully changed name".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
  947. banner.show()
  948. }
  949. }
  950. } else if resp.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "1a" {
  951. DispatchQueue.main.async {
  952. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  953. imageView.tintColor = .white
  954. let banner = FloatingNotificationBanner(title: "Username has been registered, please use another name".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
  955. banner.show()
  956. }
  957. }
  958. }
  959. }
  960. }
  961. public static func openMail() {
  962. Nexilis.openmailAction()
  963. }
  964. public static func sendPushToken(_ token: String, isResend: Bool = false, isCall: Bool = false) {
  965. DispatchQueue.global().async{
  966. if !isCall {
  967. if Utils.getTokenAPN().isEmpty || token != Utils.getTokenAPN() {
  968. Utils.setTokenAPN(value: token)
  969. }
  970. DispatchQueue.global().async {
  971. while API.nGetCLXConnState() == 0 {
  972. Thread.sleep(forTimeInterval: 1)
  973. }
  974. _ = Nexilis.write(message: CoreMessage_TMessageBank.getToken(token: token, tokenCall: Utils.getTokenCall()))
  975. }
  976. }
  977. else {
  978. if Utils.getTokenCall().isEmpty || token != Utils.getTokenCall() {
  979. Utils.setTokenCall(value: token)
  980. }
  981. // DispatchQueue.global().async {
  982. // while API.nGetCLXConnState() == 0 {
  983. // Thread.sleep(forTimeInterval: 1)
  984. // }
  985. // print("SEND TOKEN CALL")
  986. // _ = Nexilis.write(message: CoreMessage_TMessageBank.getToken(token: token, isCall: true))
  987. // }
  988. }
  989. }
  990. }
  991. public static var uuidCall: UUID?
  992. public static var fpinCall: String?
  993. public static func showNotificationNexilis(_ userInfo: [AnyHashable : Any]) {
  994. print("MASUK SHOW NOTIFICATION NEXILIS: \(userInfo)")
  995. if checkAppStateisBackground() {
  996. // Nexilis.sendStateToServer(s: "MASUK SHOW NOTIFICATION NEXILIS")
  997. // print("MASUK SHOW NOTIFICATION NEXILIS: \(userInfo)")
  998. DispatchQueue.main.async {
  999. if let payload = userInfo["payload"] as? [String: Any] {
  1000. if let messagePayload = payload["message"] as? [String: Any] {
  1001. if let data = messagePayload["data"] as? [String: Any] {
  1002. let code = data["nx_code"] as? String ?? ""
  1003. if code == "CL01" {
  1004. if let message = data["bodies"] as? [String: String] {
  1005. let idAck = data["message_id"] as? String ?? ""
  1006. let messageToSave = TMessage()
  1007. messageToSave.mBodies = message
  1008. do {
  1009. var messageExist = false
  1010. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1011. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(message[CoreMessage_TMessageKey.MESSAGE_ID] ?? "")'"), cursor.next() {
  1012. messageExist = true
  1013. cursor.close()
  1014. }
  1015. })
  1016. if messageExist {
  1017. ackAPN(id: idAck)
  1018. return
  1019. }
  1020. } catch {
  1021. print("error saving message: \(error)")
  1022. }
  1023. APIS.addNotificationNexilis(messageToSave)
  1024. ackAPN(id: idAck)
  1025. Nexilis.saveMessage(message: messageToSave, withStatus: false, fromAPNS: true)
  1026. }
  1027. } else if code == "CL03" {
  1028. let callFromName = data["call-from-name"] as? String ?? ""
  1029. let callFrom = data["call-from"] as? String ?? ""
  1030. let callType = data["call-type"] as? String ?? ""
  1031. // uuidCall = UUID()
  1032. fpinCall = callFrom
  1033. Nexilis.callAPNActivated = true
  1034. let center = UNUserNotificationCenter.current()
  1035. let content = UNMutableNotificationContent()
  1036. content.title = callFromName
  1037. if callType == "1" {
  1038. content.body = "Incoming Audio Call".localized()
  1039. } else {
  1040. content.body = "Incoming Video Call".localized()
  1041. }
  1042. content.userInfo = ["id" : callFrom, "type" : code, "callType": callType]
  1043. content.sound = nil
  1044. let request = UNNotificationRequest(identifier: callFrom, content: content, trigger: nil)
  1045. center.add(request) { error in
  1046. if let error = error {
  1047. print("Error scheduling notification: \(error.localizedDescription)")
  1048. }
  1049. }
  1050. let session = AVAudioSession.sharedInstance()
  1051. do {
  1052. try session.setCategory(.playback, options: [.duckOthers])
  1053. try session.setActive(true)
  1054. } catch {
  1055. print("Audio session error: \(error)")
  1056. }
  1057. Nexilis.playRingtoneCall()
  1058. } else if code == "CL02" {
  1059. print("data \(data)")
  1060. let callFromName = data["call-cancel-name"] as? String ?? ""
  1061. let callFrom = data["call-cancel"] as? String ?? ""
  1062. let callType = data["call-type"] as? String ?? ""
  1063. // if let uuidCall = uuidCall {
  1064. Nexilis.stopRingtoneCall()
  1065. Nexilis.callAPNActivated = false
  1066. let center = UNUserNotificationCenter.current()
  1067. center.removeDeliveredNotifications(withIdentifiers: [callFrom])
  1068. var textCall = ""
  1069. if callType == "1" {
  1070. textCall = "audio"
  1071. } else {
  1072. textCall = "video"
  1073. }
  1074. let content = UNMutableNotificationContent()
  1075. content.title = callFromName
  1076. content.body = "☎️ Missed \(textCall) call".localized()
  1077. content.userInfo = ["id" : callFrom, "type" : code, "callType": callType]
  1078. content.sound = nil
  1079. let request = UNNotificationRequest(identifier: callFrom, content: content, trigger: nil)
  1080. center.add(request) { error in
  1081. if let error = error {
  1082. print("Error scheduling notification: \(error.localizedDescription)")
  1083. }
  1084. }
  1085. Nexilis.saveMessageCall(idCall: (User.getMyPin() ?? "") + CoreMessage_TMessageUtil.getTID(), textMessage: "Missed \(textCall) call".localized() + " at 0", fPin: callFrom, lPin: (User.getMyPin() ?? ""), timeCall: String(Date().currentTimeMillis()), attachment_type: MessageScope.MISSED_CALL)
  1086. }
  1087. }
  1088. }
  1089. } else if let message_id = userInfo["message_id"] as? String {
  1090. getMessageById(id: message_id)
  1091. }
  1092. }
  1093. }
  1094. }
  1095. public static func showNotificationCallKitNexilis(payload: [AnyHashable : Any], completion: @escaping () -> ()) {
  1096. if let messagePayload = payload["payload"] as? [String: Any] {
  1097. if let message = messagePayload["message"] as? [String: Any] {
  1098. if let data = message["data"] as? [String: Any] {
  1099. let nxCode = data["nx_code"] as? String ?? ""
  1100. let callFromName = data["call-from-name"] as? String ?? ""
  1101. let callCancelName = data["call-cancel-name"] as? String ?? ""
  1102. let callFrom = data["call-from"] as? String ?? ""
  1103. let callCancel = data["call-cancel"] as? String ?? ""
  1104. let callType = data["call-type"] as? String ?? ""
  1105. if nxCode == "CL03" {
  1106. Nexilis.callAPNActivated = true
  1107. APIS.uuidCall = UUID()
  1108. CallManager.shared.reportIncomingCall(uuid: APIS.uuidCall ?? UUID(), callerName: callFromName, callerId: callFrom, isVideo: callType != "1")
  1109. } else {
  1110. if APIS.uuidCall != nil {
  1111. CallManager.shared.endCall(uuid: APIS.uuidCall!) {
  1112. Nexilis.callAPNActivated = false
  1113. APIS.uuidCall = nil
  1114. let center = UNUserNotificationCenter.current()
  1115. var textCall = ""
  1116. if callType == "1" {
  1117. textCall = "audio"
  1118. } else {
  1119. textCall = "video"
  1120. }
  1121. let content = UNMutableNotificationContent()
  1122. content.title = callCancelName
  1123. content.body = "☎️ Missed \(textCall) call".localized()
  1124. content.userInfo = ["id" : callFrom, "type" : nxCode, "callType": callType]
  1125. content.sound = nil
  1126. let request = UNNotificationRequest(identifier: callCancel, content: content, trigger: nil)
  1127. center.add(request) { error in
  1128. if let error = error {
  1129. print("Error scheduling notification: \(error.localizedDescription)")
  1130. }
  1131. }
  1132. Nexilis.saveMessageCall(idCall: (User.getMyPin() ?? "") + CoreMessage_TMessageUtil.getTID(), textMessage: "Missed \(textCall) call".localized() + " at 0", fPin: callCancel, lPin: (User.getMyPin() ?? ""), timeCall: String(Date().currentTimeMillis()), attachment_type: MessageScope.MISSED_CALL)
  1133. }
  1134. } else if UIApplication.shared.visibleViewController is QmeraAudioViewController || UIApplication.shared.visibleViewController is QmeraVideoViewController {
  1135. var dataMessage: [AnyHashable : Any] = [:]
  1136. dataMessage["call_cancel"] = true
  1137. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.callFCM), object: nil, userInfo: dataMessage)
  1138. }
  1139. }
  1140. }
  1141. }
  1142. }
  1143. }
  1144. private static func ackAPN(id: String) {
  1145. DispatchQueue.global(qos: .background).async {
  1146. // Nexilis.sendStateToServer(s: "send ack from apn")
  1147. let parameter: [String : Any] = [
  1148. "pin": User.getMyPin() ?? "",
  1149. "message_id": id
  1150. ]
  1151. Utils.postDataWithCookiesAndUserAgent(from: URL(string: Utils.getDomainOpr() + "ack_message")!, parameter: parameter, isFormData: true) { data, response, error in
  1152. }
  1153. }
  1154. }
  1155. private static func getMessageById(id: String) {
  1156. DispatchQueue.global(qos: .background).async {
  1157. let parameter: [String : Any] = [
  1158. "pin": User.getMyPin() ?? "",
  1159. "message_id": id
  1160. ]
  1161. Utils.postDataWithCookiesAndUserAgent(from: URL(string: Utils.getDomainOpr() + "pull_notification")!, parameter: parameter, isFormData: true) { data, response, error in
  1162. if let data = data {
  1163. do {
  1164. if let dataString = String(data: data, encoding: .utf8) {
  1165. if let jsonObj = try JSONSerialization.jsonObject(with: dataString.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [String: Any] {
  1166. let dataObj = jsonObj["data"] as? String ?? ""
  1167. let message = TMessage(data: dataObj)
  1168. if Utils.getSecureFolderOffline() == "0" && IncomingThread.dispatch == nil {
  1169. if API.nGetCLXConnState() == 0 {
  1170. do {
  1171. let id = Utils.getConnectionID()
  1172. try API.initConnection(sAPIK: Nexilis.sAPIKey, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: id, sStartWH: "09:00")
  1173. } catch {}
  1174. }
  1175. if FileEncryption.shared.aesKey == nil {
  1176. IncomingThread.dispatch = DispatchGroup()
  1177. IncomingThread.dispatch?.enter()
  1178. Nexilis.getFeatureAccess()
  1179. IncomingThread.dispatch?.wait()
  1180. IncomingThread.dispatch = nil
  1181. }
  1182. }
  1183. print("save from APIS")
  1184. Nexilis.saveMessage(message: message, withStatus: false, fromAPNS: true)
  1185. ackAPN(id: id)
  1186. DispatchQueue.main.async {
  1187. UIApplication.shared.applicationIconBadgeNumber = Int(APIS.getTotalCounter())
  1188. }
  1189. }
  1190. }
  1191. } catch {
  1192. }
  1193. }
  1194. }
  1195. // Nexilis.sendStateToServer(s: "send ack from apn")
  1196. // do {
  1197. // if API.nGetCLXConnState() == 0 {
  1198. // let id = Utils.getConnectionID()
  1199. // try API.initConnection(sAPIK: Nexilis.sAPIKey, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: id, sStartWH: "09:00")
  1200. // while API.nGetCLXConnState() == 0 {
  1201. // print("nGetCLXConnState: 0")
  1202. // Thread.sleep(forTimeInterval: 1)
  1203. // }
  1204. // print("nGetCLXConnState: lewat")
  1205. // getMessage()
  1206. // } else {
  1207. // getMessage()
  1208. // }
  1209. // func getMessage() {
  1210. // if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.getMessageById(messageId: id), timeout: 30 * 1000) {
  1211. // print("result: \(result.toLogString())")
  1212. // if result.isOk() {
  1213. // let respData = result.getBody(key: CoreMessage_TMessageKey.DATA)
  1214. // if let data = Data(base64Encoded: respData, options: .ignoreUnknownCharacters),
  1215. // let decodedString = String(data: data, encoding: .utf8) {
  1216. // let message = TMessage(data: decodedString)
  1217. // print("message: \(message.toLogString())")
  1218. // }
  1219. // } else {
  1220. //
  1221. // }
  1222. // } else {
  1223. // }
  1224. // }
  1225. // } catch {
  1226. //
  1227. // }
  1228. }
  1229. }
  1230. public static func addNotificationNexilis(_ message: TMessage) {
  1231. var text = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_TEXT)
  1232. text = text.toNormalString()
  1233. let nameUser = message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME)
  1234. var threadIdentifier = message.getBody(key: CoreMessage_TMessageKey.OPPOSITE_PIN)
  1235. let scope = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_SCOPE_ID)
  1236. if threadIdentifier.isEmpty {
  1237. if scope == "4" {
  1238. threadIdentifier = message.getBody(key: CoreMessage_TMessageKey.CHAT_ID).isEmpty ? message.getBody(key: CoreMessage_TMessageKey.L_PIN) : message.getBody(key: CoreMessage_TMessageKey.CHAT_ID)
  1239. } else {
  1240. threadIdentifier = message.getBody(key: CoreMessage_TMessageKey.F_PIN)
  1241. }
  1242. }
  1243. let messageId = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
  1244. var nameSubtitle = ""
  1245. let imageId = CoreMessage_TMessageKey.IMAGE_ID
  1246. let videoId = CoreMessage_TMessageKey.VIDEO_ID
  1247. let fileId = CoreMessage_TMessageKey.FILE_ID
  1248. let audioId = CoreMessage_TMessageKey.AUDIO_ID
  1249. let attachmentFlag = CoreMessage_TMessageKey.ATTACHMENT_FLAG
  1250. let messageScopeId = CoreMessage_TMessageKey.MESSAGE_SCOPE_ID
  1251. let credential = CoreMessage_TMessageKey.CREDENTIAL
  1252. let gif_id = CoreMessage_TMessageKey.GIF_ID
  1253. let is_secret = CoreMessage_TMessageKey.IS_SECRET
  1254. if message.getBody(key: is_secret) == "1" {
  1255. text = "You got messages..."
  1256. } else if message.getBody(key: gif_id) != "" {
  1257. text = "Sent GIF 🎬"
  1258. } else if !message.getBody(key: imageId).isEmpty {
  1259. text = "Sent Image 📷"
  1260. } else if message.getBody(key: attachmentFlag) == "11" {
  1261. text = "Sent Sticker ❤️"
  1262. } else if !message.getBody(key: videoId).isEmpty {
  1263. text = "Sent Video 📹"
  1264. } else if !message.getBody(key: fileId).isEmpty {
  1265. if message.getBody(key: messageScopeId) == "18" {
  1266. text = "Sent Form 📄"
  1267. } else {
  1268. text = "Sent File 📄"
  1269. }
  1270. } else if !message.getBody(key: audioId).isEmpty {
  1271. text = "Sent Audio ♫"
  1272. } else if text.contains("Share%20location%20") {
  1273. text = "Sent Location 📌"
  1274. } else if message.getBody(key: attachmentFlag) == "27" {
  1275. text = "Sent Live Streaming"
  1276. } else if message.getBody(key: attachmentFlag) == "26" {
  1277. text = "Sent Seminar"
  1278. } else if message.getBody(key: attachmentFlag) == "25" {
  1279. text = "Sent Video Conference Room"
  1280. } else if message.getBody(key: attachmentFlag) == "24" {
  1281. text = "Sent Quiz"
  1282. } else if message.getBody(key: credential) == "1" {
  1283. text = "Sent Confidential Message"
  1284. }
  1285. var type = "1"
  1286. var nameTopic = "Lounge".localized()
  1287. var idGroup = ""
  1288. if scope == "3" || scope == "18" || scope == "5"{
  1289. type = "0"
  1290. }
  1291. var soundId: String = SecureUserDefaults.shared.value(forKey: "newNotifSoundPersonal") ?? "001:Nexilis Message (Default)"
  1292. if type == "1" {
  1293. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1294. do {
  1295. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT title, group_id FROM DISCUSSION_FORUM WHERE chat_id='\(threadIdentifier)'"), cursor.next() {
  1296. nameTopic = cursor.string(forColumnIndex: 0) ?? ""
  1297. idGroup = cursor.string(forColumnIndex: 1) ?? ""
  1298. cursor.close()
  1299. }
  1300. if idGroup.isEmpty {
  1301. idGroup = threadIdentifier
  1302. }
  1303. if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_name, image_id FROM GROUPZ WHERE group_id='\(idGroup)'"), cursorGroup.next() {
  1304. let nameGroup = cursorGroup.string(forColumnIndex: 0) ?? ""
  1305. nameSubtitle = "\(nameGroup) (\(nameTopic))"
  1306. cursorGroup.close()
  1307. }
  1308. } catch {
  1309. rollback.pointee = true
  1310. print("Access database error: \(error.localizedDescription)")
  1311. }
  1312. })
  1313. soundId = SecureUserDefaults.shared.value(forKey: "newNotifSoundGroup") ?? "001:Nexilis Message (Default)"
  1314. if idGroup.isEmpty {
  1315. return
  1316. }
  1317. }
  1318. var nameSound = soundId.components(separatedBy: ":")[1].replacingOccurrences(of: " ", with: "_")
  1319. var fromPref = false
  1320. if nameSound.contains("_(Default)") {
  1321. if !Utils.getDefaultIncomingMsg().isEmpty {
  1322. nameSound = Utils.getDefaultIncomingMsg()
  1323. fromPref = true
  1324. } else {
  1325. nameSound = nameSound.replacingOccurrences(of: "_(Default)", with: "")
  1326. }
  1327. }
  1328. copySoundToLocalPath(nameSound, fromPref)
  1329. let center = UNUserNotificationCenter.current()
  1330. let content = UNMutableNotificationContent()
  1331. content.title = nameUser
  1332. if type == "1" {
  1333. content.body = text.richText(group_id: idGroup).string
  1334. content.subtitle = nameSubtitle
  1335. } else {
  1336. content.body = text.richText().string
  1337. }
  1338. content.userInfo = ["id" : threadIdentifier, "type" : type]
  1339. content.sound = UNNotificationSound(named: UNNotificationSoundName("\(nameSound).mp3"))
  1340. let request = UNNotificationRequest(identifier: messageId, content: content, trigger: nil)
  1341. center.add(request) { error in
  1342. if let error = error {
  1343. print("Error scheduling notification: \(error.localizedDescription)")
  1344. }
  1345. }
  1346. DispatchQueue.main.async {
  1347. UIApplication.shared.applicationIconBadgeNumber = Int(APIS.getTotalCounter())
  1348. }
  1349. }
  1350. private static func copySoundToLocalPath(_ nameSound: String, _ fromPref: Bool) {
  1351. var sourceURL: URL?
  1352. if fromPref {
  1353. let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
  1354. let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
  1355. let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
  1356. if let dirPath = paths.first {
  1357. let audioURL = URL(fileURLWithPath: dirPath).appendingPathComponent(nameSound)
  1358. if FileManager.default.fileExists(atPath: audioURL.path) {
  1359. sourceURL = audioURL
  1360. } else if FileEncryption.shared.isSecureExists(filename: nameSound) {
  1361. do {
  1362. if var audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
  1363. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
  1364. if dataDecrypt != nil {
  1365. audioData = dataDecrypt!
  1366. }
  1367. let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
  1368. let tempPath = cachesDirectory.appendingPathComponent(nameSound)
  1369. try audioData.write(to: tempPath)
  1370. sourceURL = tempPath
  1371. }
  1372. } catch {
  1373. }
  1374. } else {
  1375. sourceURL = Bundle.resourceBundle(for: Nexilis.self).url(forResource: nameSound, withExtension: "mp3")
  1376. if sourceURL == nil {
  1377. sourceURL = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: nameSound, withExtension: "mp3")
  1378. }
  1379. }
  1380. }
  1381. } else {
  1382. sourceURL = Bundle.resourceBundle(for: Nexilis.self).url(forResource: nameSound, withExtension: "mp3")
  1383. if sourceURL == nil {
  1384. sourceURL = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: nameSound, withExtension: "mp3")
  1385. }
  1386. }
  1387. if sourceURL == nil {
  1388. return
  1389. }
  1390. let fileManager = FileManager.default
  1391. let soundDirectory = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!.appendingPathComponent("Sounds", isDirectory: true)
  1392. if !fileManager.fileExists(atPath: soundDirectory.path) {
  1393. do {
  1394. try fileManager.createDirectory(at: soundDirectory, withIntermediateDirectories: true, attributes: nil)
  1395. } catch {
  1396. print("Error creating Sounds directory: \(error)")
  1397. return
  1398. }
  1399. }
  1400. let destinationURL = soundDirectory.appendingPathComponent("\(nameSound).mp3")
  1401. if !fileManager.fileExists(atPath: destinationURL.path) {
  1402. do {
  1403. try fileManager.copyItem(at: sourceURL!, to: destinationURL)
  1404. } catch {
  1405. }
  1406. }
  1407. }
  1408. public static func openNotificationNexilis(_ response: UNNotificationResponse) {
  1409. DispatchQueue.main.async{
  1410. if let userInfo = response.notification.request.content.userInfo as? [String: String] {
  1411. let id = userInfo["id"] ?? ""
  1412. let type = userInfo["type"] ?? ""
  1413. let callType = userInfo["callType"] ?? ""
  1414. if let navigationC = UIApplication.shared.visibleViewController as? UINavigationController {
  1415. if navigationC.viewControllers[navigationC.viewControllers.count - 1] is EditorPersonal || navigationC.viewControllers[navigationC.viewControllers.count - 1] is EditorGroup {
  1416. navigationC.popViewController(animated: true)
  1417. }
  1418. }
  1419. showEditorOrCallFromAPN(id, type, callType)
  1420. } else {
  1421. let userInfo = response.notification.request.content.userInfo
  1422. DispatchQueue.main.async {
  1423. if let message_id = userInfo[CoreMessage_TMessageKey.MESSAGE_ID] as? String {
  1424. var f_pin = ""
  1425. var l_pin = ""
  1426. var message_scope_id = ""
  1427. var pin = ""
  1428. var chat_id = ""
  1429. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1430. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, l_pin, message_scope_id, chat_id from MESSAGE where message_id = '\(message_id)'"), cursor.next() {
  1431. f_pin = cursor.string(forColumnIndex: 0) ?? ""
  1432. l_pin = cursor.string(forColumnIndex: 1) ?? ""
  1433. message_scope_id = cursor.string(forColumnIndex: 2) ?? ""
  1434. chat_id = cursor.string(forColumnIndex: 3) ?? ""
  1435. pin = f_pin == User.getMyPin() ? l_pin : f_pin
  1436. if message_scope_id == "4" {
  1437. pin = chat_id.isEmpty ? l_pin : chat_id
  1438. }
  1439. cursor.close()
  1440. }
  1441. })
  1442. if let navigationC = UIApplication.shared.visibleViewController as? UINavigationController {
  1443. if navigationC.viewControllers[navigationC.viewControllers.count - 1] is EditorPersonal || navigationC.viewControllers[navigationC.viewControllers.count - 1] is EditorGroup {
  1444. navigationC.popViewController(animated: false)
  1445. }
  1446. }
  1447. showEditorOrCallFromAPN(pin, message_scope_id == "4" ? "1" : !message_scope_id.isEmpty ? "0" : "", "CL01")
  1448. }
  1449. }
  1450. }
  1451. }
  1452. // UNUserNotificationCenter.current().removeAllDeliveredNotifications()
  1453. }
  1454. private static func showEditorOrCallFromAPN(_ id: String, _ type: String, _ callType: String) {
  1455. if type.isEmpty {
  1456. return
  1457. }
  1458. if type == "0" {
  1459. if User.getDataCanNil(pin: id) == nil && id != "-999" && id != "-997" {
  1460. return
  1461. }
  1462. let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  1463. editorPersonalVC.hidesBottomBarWhenPushed = true
  1464. editorPersonalVC.unique_l_pin = id
  1465. editorPersonalVC.fromNotification = true
  1466. let navigationController = CustomNavigationController(rootViewController: editorPersonalVC)
  1467. navigationController.modalPresentationStyle = .fullScreen
  1468. navigationController.navigationBar.tintColor = .white
  1469. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  1470. navigationController.navigationBar.isTranslucent = false
  1471. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  1472. navigationController.navigationBar.barStyle = .black
  1473. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  1474. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  1475. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  1476. navigationController.navigationBar.titleTextAttributes = textAttributes
  1477. if UIApplication.shared.visibleViewController is UINavigationController && Nexilis.fromMAB {
  1478. editorPersonalVC.fromNotification = false
  1479. UIApplication.shared.visibleViewController?.show(editorPersonalVC, sender: nil)
  1480. } else {
  1481. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  1482. }
  1483. } else if type == "1" {
  1484. var groupExist = false
  1485. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1486. var idGroup = ""
  1487. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT title, group_id FROM DISCUSSION_FORUM WHERE chat_id='\(id)'"), cursor.next() {
  1488. groupExist = true
  1489. cursor.close()
  1490. } else {
  1491. if idGroup.isEmpty {
  1492. idGroup = id
  1493. }
  1494. if let cursorGroup = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_name, image_id FROM GROUPZ WHERE group_id='\(idGroup)'"), cursorGroup.next() {
  1495. groupExist = true
  1496. cursorGroup.close()
  1497. }
  1498. }
  1499. })
  1500. if !groupExist {
  1501. return
  1502. }
  1503. let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "editorGroupVC") as! EditorGroup
  1504. editorGroupVC.hidesBottomBarWhenPushed = true
  1505. editorGroupVC.unique_l_pin = id
  1506. editorGroupVC.fromNotification = true
  1507. let navigationController = CustomNavigationController(rootViewController: editorGroupVC)
  1508. navigationController.modalPresentationStyle = .fullScreen
  1509. navigationController.navigationBar.tintColor = .white
  1510. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  1511. navigationController.navigationBar.isTranslucent = false
  1512. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  1513. navigationController.navigationBar.barStyle = .black
  1514. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  1515. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  1516. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  1517. navigationController.navigationBar.titleTextAttributes = textAttributes
  1518. if UIApplication.shared.visibleViewController is UINavigationController && Nexilis.fromMAB {
  1519. editorGroupVC.fromNotification = false
  1520. UIApplication.shared.visibleViewController?.show(editorGroupVC, sender: nil)
  1521. } else {
  1522. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  1523. }
  1524. } else if type == "CL03" {
  1525. Nexilis.stopRingtoneCall()
  1526. if !Nexilis.callAPNActivated {
  1527. return
  1528. }
  1529. if callType == "1" {
  1530. if let user = User.getData(pin: id), user.firstName == "User".localized() {
  1531. return
  1532. }
  1533. let controller = QmeraAudioViewController()
  1534. controller.isOutgoing = false
  1535. controller.user = User.getData(pin: id)
  1536. controller.autoAcceptAPN = true
  1537. controller.modalPresentationStyle = .overCurrentContext
  1538. if UIApplication.shared.visibleViewController is UIAlertController {
  1539. let vc = UIApplication.shared.visibleViewController as! UIAlertController
  1540. vc.dismiss(animated: true, completion: {
  1541. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1542. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  1543. } else {
  1544. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  1545. }
  1546. })
  1547. return
  1548. }
  1549. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1550. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  1551. } else {
  1552. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  1553. }
  1554. } else {
  1555. if let user = User.getData(pin: id), user.firstName == "User".localized() {
  1556. return
  1557. }
  1558. let videoController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
  1559. videoController.fPin = id
  1560. videoController.isInisiator = false
  1561. videoController.autoAcceptAPN = true
  1562. let navigationController = CustomNavigationController(rootViewController: videoController)
  1563. navigationController.modalPresentationStyle = .fullScreen
  1564. if UIApplication.shared.visibleViewController is UIAlertController {
  1565. let vc = UIApplication.shared.visibleViewController as! UIAlertController
  1566. vc.dismiss(animated: true, completion: {
  1567. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1568. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  1569. } else {
  1570. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  1571. }
  1572. })
  1573. return
  1574. }
  1575. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1576. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  1577. } else {
  1578. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  1579. }
  1580. }
  1581. }
  1582. }
  1583. public static func checkAppStateisBackground() -> Bool {
  1584. let state = UIApplication.shared.applicationState
  1585. switch state {
  1586. case .active:
  1587. return false
  1588. case .inactive:
  1589. return false
  1590. case .background:
  1591. return true
  1592. @unknown default:
  1593. return false
  1594. }
  1595. }
  1596. public static func enterBackground() {
  1597. // if !API.bAVisOngoing() {
  1598. // API.deinitConnection()
  1599. // }
  1600. notifTimer.invalidate()
  1601. stopNotif = true
  1602. if Utils.getSecureFolderOffline() == "0" {
  1603. Database.shared.database = nil
  1604. FileEncryption.shared.aesKey = nil
  1605. FileEncryption.shared.aesIV = nil
  1606. }
  1607. FloatingButton.datePull = nil
  1608. }
  1609. public static var notifTimer = Timer()
  1610. public static var stopNotif = false
  1611. public static var afterEnterBackground = false
  1612. public static func enterForeground() {
  1613. APIS.checkNotificationPermission(completion: { isAllowed in
  1614. if !isAllowed {
  1615. showEnableNotificationsAlert()
  1616. } else {
  1617. UIApplication.shared.registerForRemoteNotifications()
  1618. }
  1619. })
  1620. DispatchQueue.main.async {
  1621. stopNotif = true
  1622. self.notifTimer = Timer.scheduledTimer(withTimeInterval: 30, repeats: false) { _ in
  1623. stopNotif = false
  1624. }
  1625. do {
  1626. if !Nexilis.afterConnect && API.nGetCLXConnState() == 0 {
  1627. let id = Utils.getConnectionID()
  1628. try API.initConnection(sAPIK: Nexilis.sAPIKey, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: id, sStartWH: "09:00")
  1629. }
  1630. // listIdentifierNotif.removeAll()
  1631. Nexilis.afterConnect = false
  1632. } catch {
  1633. }
  1634. }
  1635. checkDataForShareExtension()
  1636. UIApplication.shared.applicationIconBadgeNumber = 0
  1637. UNUserNotificationCenter.current().removeAllDeliveredNotifications()
  1638. // DispatchQueue.global().async {
  1639. // while API.nGetCLXConnState() == 0 {
  1640. // Thread.sleep(forTimeInterval: 0.5)
  1641. // }
  1642. // if let vers = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.checkVersion()) {
  1643. // let dataVersion = vers.getBody(key: CoreMessage_TMessageKey.DATA)
  1644. // let type = vers.getBody(key: CoreMessage_TMessageKey.TYPE)
  1645. // if dataVersion != "1" {
  1646. // DispatchQueue.main.async {
  1647. // showExpiredVersion(mandatory: type == "1")
  1648. // }
  1649. // }
  1650. // }
  1651. // }
  1652. if Utils.getSecureFolderOffline() == "0" && afterEnterBackground && Database.shared.database == nil && Utils.getSetProfile() {
  1653. Database.recreateInstance()
  1654. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "disconnected_nexilis"), object: nil, userInfo: nil)
  1655. if let navigationC = UIApplication.shared.visibleViewController as? UINavigationController {
  1656. if navigationC.viewControllers[navigationC.viewControllers.count - 1] is EditorPersonal || navigationC.viewControllers[navigationC.viewControllers.count - 1] is EditorGroup {
  1657. navigationC.popViewController(animated: true)
  1658. }
  1659. }
  1660. // Nexilis.getFeatureAccessWithKey(key: ["secure_folder_encrypt_key", "secure_folder_encrypt_iv", "secure_folder_offline"])
  1661. Nexilis.getFeatureAccess()
  1662. }
  1663. afterEnterBackground = true
  1664. }
  1665. public static func willEnterForeground() {
  1666. // if APIS.uuidCall != nil {
  1667. // CallManager.shared.endCall(uuid: APIS.uuidCall!) {
  1668. // APIS.uuidCall = nil
  1669. // }
  1670. // }
  1671. }
  1672. private static func checkNotificationPermission(completion: @escaping (Bool) -> Void) {
  1673. let center = UNUserNotificationCenter.current()
  1674. center.getNotificationSettings { settings in
  1675. DispatchQueue.main.async {
  1676. switch settings.authorizationStatus {
  1677. case .authorized, .provisional, .notDetermined:
  1678. completion(true) // Notifications are allowed
  1679. case .denied, .ephemeral:
  1680. completion(false) // Notifications are disabled or not requested
  1681. @unknown default:
  1682. completion(false)
  1683. }
  1684. }
  1685. }
  1686. }
  1687. public static func nexilisShowAlertWithHTMLMessage(on viewController: UIViewController, title: String, message: String = "<b>Bold</b> and <i>italic</i> text in an alert") {
  1688. let alert = UIAlertController(title: title, message: "", preferredStyle: .alert)
  1689. let titleFont = UIFont.boldSystemFont(ofSize: 16)
  1690. let titleAttributes = [NSAttributedString.Key.font: titleFont]
  1691. alert.setValue(NSAttributedString(string: title, attributes: titleAttributes), forKey: "attributedTitle")
  1692. var message = message
  1693. message = message.replacingOccurrences(of: "<b>", with: "*")
  1694. message = message.replacingOccurrences(of: "</b>", with: "*")
  1695. message = message.replacingOccurrences(of: "<i>", with: "_")
  1696. message = message.replacingOccurrences(of: "</i>", with: "_")
  1697. alert.setValue(message.richText(fontSize: 14), forKey: "attributedMessage")
  1698. alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
  1699. viewController.present(alert, animated: true, completion: nil)
  1700. }
  1701. static func showWarningFile(type: Int) {
  1702. alertControllerExpired = LibAlertController(
  1703. title: type == -1 ? "⚠️ Suspicious File Detected".localized() : "⚠️ Unrecognized File Type".localized(),
  1704. message: type == -1 ? "The file appears to have a mismatched name and extension, which may indicate a malicious file. Please verify the file’s source and format before uploading it.".localized() : "The selected item is not listed in the system dashboard.".localized(),
  1705. preferredStyle: .alert
  1706. )
  1707. alertControllerExpired.addAction(UIAlertAction(title: "OK".localized(), style: .default, handler: nil))
  1708. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1709. UIApplication.shared.visibleViewController?.navigationController?.present(alertControllerExpired, animated: true, completion: nil)
  1710. } else {
  1711. UIApplication.shared.visibleViewController?.present(alertControllerExpired, animated: true, completion: nil)
  1712. }
  1713. }
  1714. private static func showEnableNotificationsAlert() {
  1715. guard !isAlertPresented else { return }
  1716. isAlertPresented = true
  1717. let alertController = LibAlertController(
  1718. title: "Enable Notification".localized(),
  1719. message: "To stay updated, please enable notification in the Settings.".localized(),
  1720. preferredStyle: .alert
  1721. )
  1722. alertController.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { _ in
  1723. isAlertPresented = false
  1724. }))
  1725. alertController.addAction(UIAlertAction(title: "Go to Settings".localized(), style: .default, handler: { _ in
  1726. isAlertPresented = false
  1727. openAppSettings()
  1728. }))
  1729. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1730. UIApplication.shared.visibleViewController?.navigationController?.present(alertController, animated: true, completion: nil)
  1731. } else {
  1732. UIApplication.shared.visibleViewController?.present(alertController, animated: true, completion: nil)
  1733. }
  1734. }
  1735. static func showRestartApp() {
  1736. alertControllerExpired = LibAlertController(
  1737. title: "Restart Required".localized(),
  1738. message: "Oops! Something went wrong. Please restart the app to continue.".localized(),
  1739. preferredStyle: .alert
  1740. )
  1741. alertControllerExpired.addAction(UIAlertAction(title: "OK".localized(), style: .default, handler: { _ in
  1742. exit(0)
  1743. }))
  1744. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1745. UIApplication.shared.visibleViewController?.navigationController?.present(alertControllerExpired, animated: true, completion: nil)
  1746. } else {
  1747. UIApplication.shared.visibleViewController?.present(alertControllerExpired, animated: true, completion: nil)
  1748. }
  1749. }
  1750. private static var alertControllerExpired: LibAlertController!
  1751. public static func showExpiredVersion(mandatory: Bool) {
  1752. func showAl() {
  1753. alertControllerExpired = LibAlertController(
  1754. title: "Update Available".localized(),
  1755. message: "A new version is now available. Please update to the latest version to enjoy new features and important improvements.".localized(),
  1756. preferredStyle: .alert
  1757. )
  1758. if !mandatory {
  1759. alertControllerExpired.addAction(UIAlertAction(title: "Later".localized(), style: .cancel, handler: nil))
  1760. }
  1761. alertControllerExpired.addAction(UIAlertAction(title: "Update Now".localized(), style: .default, handler: { _ in
  1762. if APIS.appNm == "OneApp" {
  1763. let appStoreURL = URL(string: "https://apps.apple.com/app/id6741251571")!
  1764. UIApplication.shared.open(appStoreURL)
  1765. } else {
  1766. let appStoreURL = URL(string: "https://apps.apple.com/app/")!
  1767. UIApplication.shared.open(appStoreURL)
  1768. }
  1769. }))
  1770. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1771. UIApplication.shared.visibleViewController?.navigationController?.present(alertControllerExpired, animated: true, completion: nil)
  1772. } else {
  1773. UIApplication.shared.visibleViewController?.present(alertControllerExpired, animated: true, completion: nil)
  1774. }
  1775. }
  1776. if alertControllerExpired != nil {
  1777. alertControllerExpired.dismiss(animated: true) {
  1778. showAl()
  1779. }
  1780. } else {
  1781. showAl()
  1782. }
  1783. }
  1784. private static func openAppSettings() {
  1785. if let settingsURL = URL(string: UIApplication.openSettingsURLString) {
  1786. if UIApplication.shared.canOpenURL(settingsURL) {
  1787. UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil)
  1788. }
  1789. }
  1790. }
  1791. public static func willTerminate() {
  1792. Nexilis.destroyAll()
  1793. }
  1794. public static func checkDataForShareExtension() {
  1795. DispatchQueue.global().async {
  1796. if let userDefaults = UserDefaults(suiteName: nameGroupShared) {
  1797. if let value = userDefaults.string(forKey: "sharedItem") {
  1798. if !value.isEmpty {
  1799. if let jsonData = value.data(using: .utf8) {
  1800. do {
  1801. if let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
  1802. let typeImage = 2
  1803. let typeVideo = 3
  1804. let typeFile = 4
  1805. let typeAudio = 5
  1806. let typeContact = json["typeContact"] as? String ?? "0"
  1807. var data = json["data"] as? String ?? ""
  1808. let idContact = json["idContact"] as? String ?? ""
  1809. let typeShare = json["typeShare"] as? Int ?? 1
  1810. var message = TMessage()
  1811. var groupId = ""
  1812. var chatId = ""
  1813. let scopeId = typeContact == "1" ? "4" : "3"
  1814. let thumb = json["thumb"] as? String ?? ""
  1815. let imageId = json["image"] as? String ?? ""
  1816. let videoId = json["video"] as? String ?? ""
  1817. let fileId = json["file"] as? String ?? ""
  1818. let audioId = json["audio"] as? String ?? ""
  1819. var renamedFileId = ""
  1820. var renamedAudioId = ""
  1821. var attachmentFlag = ""
  1822. if scopeId == "4" {
  1823. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1824. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id id FROM DISCUSSION_FORUM WHERE chat_id = '\(idContact)'"), cursor.next() {
  1825. groupId = cursor.string(forColumnIndex: 0) ?? ""
  1826. chatId = idContact
  1827. cursor.close()
  1828. } else {
  1829. groupId = idContact
  1830. }
  1831. })
  1832. }
  1833. if typeShare == typeImage {
  1834. if let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: nameGroupShared) {
  1835. let sharedImageURL = appGroupURL.appendingPathComponent(imageId)
  1836. let sharedThumbURL = appGroupURL.appendingPathComponent(thumb)
  1837. let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  1838. if FileManager.default.fileExists(atPath: sharedImageURL.path) {
  1839. let file = documentDir.appendingPathComponent(imageId)
  1840. if !FileManager().fileExists(atPath: file.path) {
  1841. try? FileManager.default.copyItem(at: sharedImageURL, to: file)
  1842. }
  1843. }
  1844. if FileManager.default.fileExists(atPath: sharedThumbURL.path) {
  1845. let file = documentDir.appendingPathComponent(thumb)
  1846. if !FileManager().fileExists(atPath: file.path) {
  1847. try? FileManager.default.copyItem(at: sharedThumbURL, to: file)
  1848. }
  1849. }
  1850. }
  1851. attachmentFlag = "1"
  1852. } else if typeShare == typeVideo {
  1853. if let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: nameGroupShared) {
  1854. let sharedVideoURL = appGroupURL.appendingPathComponent(videoId)
  1855. let sharedThumbURL = appGroupURL.appendingPathComponent(thumb)
  1856. let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  1857. if FileManager.default.fileExists(atPath: sharedVideoURL.path) {
  1858. let file = documentDir.appendingPathComponent(videoId)
  1859. if !FileManager().fileExists(atPath: file.path) {
  1860. try? FileManager.default.copyItem(at: sharedVideoURL, to: file)
  1861. }
  1862. }
  1863. if FileManager.default.fileExists(atPath: sharedThumbURL.path) {
  1864. let file = documentDir.appendingPathComponent(thumb)
  1865. if !FileManager().fileExists(atPath: file.path) {
  1866. try? FileManager.default.copyItem(at: sharedThumbURL, to: file)
  1867. }
  1868. }
  1869. }
  1870. attachmentFlag = "2"
  1871. } else if typeShare == typeFile {
  1872. if let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: nameGroupShared) {
  1873. renamedFileId = "Nexilis_\(Date().currentTimeMillis())_" + fileId
  1874. let sharedFileURL = appGroupURL.appendingPathComponent(fileId)
  1875. let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  1876. if FileManager.default.fileExists(atPath: sharedFileURL.path) {
  1877. let file = documentDir.appendingPathComponent(renamedFileId)
  1878. if !FileManager().fileExists(atPath: file.path) {
  1879. try? FileManager.default.copyItem(at: sharedFileURL, to: file)
  1880. }
  1881. }
  1882. data = "\(fileId)|\(data)"
  1883. }
  1884. attachmentFlag = "6"
  1885. } else if typeShare == typeAudio {
  1886. if let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: nameGroupShared) {
  1887. renamedAudioId = "Nexilis_\(Date().currentTimeMillis())_" + audioId
  1888. let sharedFileURL = appGroupURL.appendingPathComponent(audioId)
  1889. let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  1890. if FileManager.default.fileExists(atPath: sharedFileURL.path) {
  1891. let file = documentDir.appendingPathComponent(renamedAudioId)
  1892. if !FileManager().fileExists(atPath: file.path) {
  1893. try? FileManager.default.copyItem(at: sharedFileURL, to: file)
  1894. }
  1895. }
  1896. data = "\(audioId)|\(data)"
  1897. }
  1898. attachmentFlag = "5"
  1899. }
  1900. message = CoreMessage_TMessageBank.sendMessage(l_pin: groupId.isEmpty ? idContact : groupId, message_scope_id: scopeId, status: scopeId == "3" ? "1" : "2", message_text: data, credential: "0", attachment_flag: attachmentFlag, ex_blog_id: "", message_large_text: "", ex_format: "", image_id: imageId, audio_id: renamedAudioId, video_id: videoId, file_id: renamedFileId, thumb_id: thumb, reff_id: "", read_receipts: "4", chat_id: chatId, is_call_center: "0", call_center_id: "", opposite_pin: scopeId == "3" ? (User.getMyPin() ?? "") : idContact, gif_id: "", isForwarded: "0", isSecret: "0")
  1901. Nexilis.addQueueMessage(message: message)
  1902. userDefaults.set("", forKey: "sharedItem")
  1903. userDefaults.synchronize()
  1904. }
  1905. } catch {
  1906. print("Error parsing JSON: \(error)")
  1907. }
  1908. }
  1909. }
  1910. }
  1911. }
  1912. DispatchQueue.global().asyncAfter(deadline: .now() + 0.5, execute: {
  1913. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
  1914. })
  1915. }
  1916. }
  1917. public static func setDataForShareExtension() {
  1918. DispatchQueue.global().async {
  1919. if let userDefaults = UserDefaults(suiteName: nameGroupShared) {
  1920. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1921. var dataShared: [[String: Any]] = []
  1922. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin id, image_id image, first_name || ' ' || ifnull(last_name, '') name FROM BUDDY WHERE f_pin != '\(User.getMyPin() ?? "")' AND f_pin != '-997' AND official_account != '1'") {
  1923. while cursor.next() {
  1924. var dataTemp: [String: Any] = [:]
  1925. for columnIndex in 0..<cursor.columnCount {
  1926. if let columnName = cursor.columnName(for: columnIndex) {
  1927. if let value = cursor.object(forColumn: columnName) {
  1928. if columnName == "image" {
  1929. dataTemp[columnName] = value
  1930. if let imageString = dataTemp[columnName] as? String, !imageString.isEmpty {
  1931. do {
  1932. if FileEncryption.shared.isSecureExists(filename: imageString) {
  1933. if var data = try FileEncryption.shared.readSecure(filename: imageString) {
  1934. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
  1935. if dataDecrypt != nil {
  1936. data = dataDecrypt!
  1937. }
  1938. if let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: nameGroupShared) {
  1939. let sharedFileURL = appGroupURL.appendingPathComponent(imageString)
  1940. if !FileManager.default.fileExists(atPath: sharedFileURL.path) {
  1941. try? data.write(to: sharedFileURL)
  1942. }
  1943. }
  1944. }
  1945. }
  1946. } catch {
  1947. }
  1948. }
  1949. } else {
  1950. dataTemp[columnName] = value
  1951. }
  1952. dataTemp["type"] = 0
  1953. }
  1954. }
  1955. }
  1956. dataShared.append(dataTemp)
  1957. }
  1958. cursor.close()
  1959. }
  1960. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT group_id id, image_id image, f_name name FROM GROUPZ WHERE official != 1") {
  1961. while cursor.next() {
  1962. var dataTemp: [String: Any] = [:]
  1963. for columnIndex in 0..<cursor.columnCount {
  1964. if let columnName = cursor.columnName(for: columnIndex) {
  1965. if let value = cursor.object(forColumn: columnName) {
  1966. if columnName == "name" {
  1967. dataTemp[columnName] = "\(value) (Lounge)"
  1968. } else if columnName == "image" {
  1969. dataTemp[columnName] = value
  1970. if let imageString = dataTemp[columnName] as? String, !imageString.isEmpty {
  1971. do {
  1972. if FileEncryption.shared.isSecureExists(filename: imageString) {
  1973. if var data = try FileEncryption.shared.readSecure(filename: imageString) {
  1974. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
  1975. if dataDecrypt != nil {
  1976. data = dataDecrypt!
  1977. }
  1978. if let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: nameGroupShared) {
  1979. let sharedFileURL = appGroupURL.appendingPathComponent(imageString)
  1980. if !FileManager.default.fileExists(atPath: sharedFileURL.path) {
  1981. try? data.write(to: sharedFileURL)
  1982. }
  1983. }
  1984. }
  1985. }
  1986. } catch {
  1987. }
  1988. }
  1989. } else {
  1990. dataTemp[columnName] = value
  1991. }
  1992. dataTemp["type"] = 1
  1993. }
  1994. }
  1995. }
  1996. dataShared.append(dataTemp)
  1997. let group_id = cursor.string(forColumnIndex: 0) ?? ""
  1998. let image_group = cursor.string(forColumnIndex: 1) ?? ""
  1999. let name_group = cursor.string(forColumnIndex: 2) ?? ""
  2000. if let cursorTopic = Database.shared.getRecords(fmdb: fmdb, query: "SELECT chat_id id, thumb image, title name FROM DISCUSSION_FORUM WHERE group_id = '\(group_id)'") {
  2001. while cursorTopic.next() {
  2002. var dataTempTopic: [String: Any] = [:]
  2003. for columnIndex in 0..<cursorTopic.columnCount {
  2004. if let columnName = cursorTopic.columnName(for: columnIndex) {
  2005. if let value = cursorTopic.object(forColumn: columnName) {
  2006. if columnName == "name" {
  2007. dataTempTopic[columnName] = "\(name_group) (\(value))"
  2008. } else if columnName == "image" {
  2009. dataTempTopic[columnName] = "\(value)".isEmpty ? image_group : "\(value)"
  2010. if let imageString = dataTempTopic[columnName] as? String, !imageString.isEmpty {
  2011. do {
  2012. if FileEncryption.shared.isSecureExists(filename: imageString) {
  2013. if var data = try FileEncryption.shared.readSecure(filename: imageString) {
  2014. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
  2015. if dataDecrypt != nil {
  2016. data = dataDecrypt!
  2017. }
  2018. if let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: nameGroupShared) {
  2019. let sharedFileURL = appGroupURL.appendingPathComponent(imageString)
  2020. if !FileManager.default.fileExists(atPath: sharedFileURL.path) {
  2021. try? data.write(to: sharedFileURL)
  2022. }
  2023. }
  2024. }
  2025. }
  2026. } catch {
  2027. }
  2028. }
  2029. } else {
  2030. dataTempTopic[columnName] = value
  2031. }
  2032. dataTempTopic["type"] = 1
  2033. }
  2034. }
  2035. }
  2036. dataShared.append(dataTempTopic)
  2037. }
  2038. cursorTopic.close()
  2039. }
  2040. }
  2041. cursor.close()
  2042. }
  2043. do {
  2044. let jsonData = try JSONSerialization.data(withJSONObject: dataShared, options: .prettyPrinted)
  2045. if let jsonString = String(data: jsonData, encoding: .utf8) {
  2046. userDefaults.set(jsonString, forKey: "shareContacts")
  2047. userDefaults.synchronize()
  2048. }
  2049. } catch {
  2050. print("Error converting to JSON: \(error)")
  2051. }
  2052. })
  2053. }
  2054. }
  2055. }
  2056. public static func setCheckEmulator(isActive: Bool) {
  2057. // Utils.bCheckEmulator = isActive
  2058. }
  2059. public static func setCheckRootedDevice(isActive: Bool) {
  2060. // Utils.bCheckRooted = isActive
  2061. }
  2062. public static func setPreventScreenCapture(isActive: Bool) {
  2063. // Utils.bPreventScreenCapture = isActive
  2064. }
  2065. public static func setNameGroupShare(_ name: String) {
  2066. nameGroupShared = name
  2067. }
  2068. public static func openImageNexilis(image: UIImage, data: Data? = nil, isGIF: Bool = false) {
  2069. let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
  2070. previewImageVC.image = image
  2071. previewImageVC.isHiddenTextField = true
  2072. previewImageVC.isGIF = isGIF
  2073. previewImageVC.dataGIF = data
  2074. previewImageVC.modalPresentationStyle = .custom
  2075. previewImageVC.modalTransitionStyle = .crossDissolve
  2076. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2077. UIApplication.shared.visibleViewController?.navigationController?.present(previewImageVC, animated: true, completion: nil)
  2078. } else {
  2079. UIApplication.shared.visibleViewController?.present(previewImageVC, animated: true, completion: nil)
  2080. }
  2081. }
  2082. public static func openVideoNexilis(videoURL: URL) {
  2083. let player = AVPlayer(url: videoURL)
  2084. let playerVC = AVPlayerViewController()
  2085. playerVC.modalPresentationStyle = .custom
  2086. playerVC.player = player
  2087. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2088. UIApplication.shared.visibleViewController?.navigationController?.present(playerVC, animated: true, completion: nil)
  2089. } else {
  2090. UIApplication.shared.visibleViewController?.present(playerVC, animated: true, completion: nil)
  2091. }
  2092. }
  2093. private static var appNm = "";
  2094. public static func getAppNm() -> String {
  2095. return appNm
  2096. }
  2097. private static var nameGroupShared = "group.nexilis.share";
  2098. public static func getnameGroupShared() -> String {
  2099. return nameGroupShared
  2100. }
  2101. }
  2102. extension UINavigationController {
  2103. func defaultStyle() {
  2104. self.view.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .black : .white
  2105. self.modalPresentationStyle = .fullScreen
  2106. self.navigationBar.tintColor = .white
  2107. self.navigationBar.barTintColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  2108. self.navigationBar.isTranslucent = false
  2109. self.navigationBar.overrideUserInterfaceStyle = .dark
  2110. self.navigationBar.barStyle = .black
  2111. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  2112. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  2113. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  2114. self.navigationBar.titleTextAttributes = textAttributes
  2115. }
  2116. }