Nexilis.swift 201 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565
  1. //
  2. // Qmera.swift
  3. // Runner
  4. //
  5. // Created by Yayan Dwi on 15/04/20.
  6. // Copyright © 2020 The Chromium Authors. All rights reserved.
  7. //
  8. import Foundation
  9. import nuSDKService
  10. import AVFoundation
  11. import AVKit
  12. import UIKit
  13. import FMDB
  14. import QuickLook
  15. import NotificationBannerSwift
  16. public class Nexilis: NSObject {
  17. public static var sAPIKey = ""
  18. public static var ADDRESS = ""
  19. // static let ADDRESS_33 = "192.168.0.33"
  20. // static let ADDRESS_RELEASE = "202.158.33.26" //CBN
  21. // static let ADDRESS_RELEASE = "108.137.84.148" //AWS
  22. // static let PORT = 45328
  23. // static let PORT = 65328 // 33
  24. static var PORT = PORT_RELEASE
  25. static let PORT_33 = 62328
  26. static let PORT_RELEASE = 42328
  27. static var nSessionMode: Int! = 1
  28. static var dispatch: DispatchGroup?
  29. let callManager = CallManager()
  30. var providerDelegate: CallProviderDelegate?
  31. public static let shared = Nexilis()
  32. public static var broadcastTimer = Timer()
  33. public static var broadcastList = [[String: String]]()
  34. public static var onGoingPushCC: [String: String] = [:]
  35. public static var openBroadcast = false
  36. public static var loadingAlert = LibAlertController()
  37. public static var floatingButton = FloatingButton()
  38. public static var showButtonFB = false
  39. public static var imageCache = NSCache<NSString, UIImage>()
  40. public static let listenerReceiveChat = "onReceiveChatLibLite"
  41. public static let listenerStatusChat = "onMessageChatLibLite"
  42. public static let listenerTypingChat = "onTypingChatLibLite"
  43. public static let listenerStatusCall = "onStatusCallLibLite"
  44. public static var showLibraryNotification = true
  45. public static let STREAMING_SEMINAR_ENDED = 88
  46. public static let VIDEO_CALL_END = 38
  47. public static let VIDEO_CALL_MUTE_UNMUTE = 36
  48. public static let VIDEO_CALL_ZOOM = 35
  49. public static let VIDEO_CAMERA_PARAMS_CHANED = 34
  50. public static let VIDEO_CALL_RINGING = 33
  51. public static let VIDEO_CALL_OFFHOOK = 32
  52. public static let VIDEO_CALL_INCOMING = 31
  53. public static let AUDIO_CALL_END = 28
  54. public static let AUDIO_CALL_RINGING = 23
  55. public static let AUDIO_CALL_OFFHOOK = 22
  56. public static let AUDIO_CALL_INCOMING = 21
  57. public static let VIDEO_RINGING = 11
  58. public static let ENDED = 8
  59. public static let INITIATING = 4
  60. public static let AUDIO_RINGING = 1
  61. public static let OUTGOING_CALL = 0
  62. public static let OFFLINE = -3
  63. public static let BUSY = -4
  64. public static let IDX_QUEUE_SYSTEM = 2
  65. public static let IDX_NOTIF_CENTER = 3
  66. public static let IDX_CC_STREAM = 4
  67. public static let IDX_CHAT = 6
  68. public static let IDX_CALL = 7
  69. public static let IDX_STREAM = 8
  70. public static let IDX_CC = 9
  71. public static let IDX_CALL_AUDIO = 11
  72. public static let IDX_CALL_VIDEO = 12
  73. public static let IDX_WHITEBOARD = 13
  74. public static let IDX_SCREENSHARING = 14
  75. public static let IDX_WB_SS = 15
  76. public static let IDX_BROADCAST_FORM = 16
  77. public static let IDX_CONVERSATION = 17
  78. public static let IDX_FAVORITEMESSAGE = 18
  79. public static let IDX_CONFERENCE_ROOM_FORM = 19
  80. public static let IDX_EMAIL_CONFIGURATION = 20
  81. public static let IDX_CREATE_GROUP = 21
  82. public static let IDX_ADDFRIEND = 22
  83. public static let IDX_SIGNUP_OR_IN_PAGE = 23
  84. public static let IDX_POST = 99
  85. public static let IDX_SELF_ACT = 100
  86. public static let IDX_SOCIAL_COMMERCE = 101
  87. public static let IDX_NEWS = 102
  88. private func createDelegate() {
  89. //print("createDelegate...")
  90. callDelegate = self
  91. messageDelegate = self
  92. groupDelegate = self
  93. personInfoDelegate = self
  94. providerDelegate = CallProviderDelegate(callManager: callManager)
  95. }
  96. public static func connect(apiKey: String, delegate: ConnectDelegate, showButton: Bool = true, fromMAB: Bool = false) {
  97. do {
  98. Nexilis.shared.createDelegate()
  99. Nexilis.sAPIKey = apiKey
  100. Nexilis.showButtonFB = showButton
  101. Database.shared.openDatabase()
  102. IncomingThread.default.run()
  103. imageCache.countLimit = 100
  104. imageCache.totalCostLimit = 1024 * 1024 * 200
  105. let address = Nexilis.getAddress(apiKey:apiKey)
  106. if address.count == 0 {
  107. return
  108. }
  109. UserDefaults.standard.set(address, forKey: "address")
  110. UserDefaults.standard.set(address[0], forKey: "server")
  111. Nexilis.dispatch = DispatchGroup()
  112. Nexilis.dispatch?.enter()
  113. var server = UserDefaults.standard.string(forKey: "server")
  114. if let s = server, let a = UserDefaults.standard.stringArray(forKey: "address"), s != a[0] {
  115. server = a[0]
  116. UserDefaults.standard.set(server, forKey: "server")
  117. }
  118. var ip = ""
  119. var port = 0
  120. if let s = server {
  121. let data = s.split(separator: ":")
  122. ip = String(data[0])
  123. if let p = Int(data[1]) {
  124. port = p
  125. }
  126. }
  127. Nexilis.ADDRESS = ip
  128. Nexilis.PORT = port
  129. //print(API.sGetVersion())
  130. var id = ""
  131. if let device_id = UserDefaults.standard.string(forKey: "device_id") {
  132. try API.initConnection(bSwitchIP: false, sAPIK: apiKey, aAppMain: nil, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: device_id, sStartWH: "09:00")
  133. } else if let me = UserDefaults.standard.string(forKey: "me") {
  134. try API.initConnection(bSwitchIP: false, sAPIK: apiKey, aAppMain: nil, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: me, sStartWH: "09:00")
  135. } else {
  136. let uuid = UIDevice.current.identifierForVendor?.uuidString ?? "UNK-DEVICE"
  137. try API.initConnection(bSwitchIP: false, sAPIK: apiKey, aAppMain: nil, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: uuid, sStartWH: "09:00")
  138. id = uuid
  139. }
  140. // wait until connection true
  141. Nexilis.dispatch?.wait()
  142. Nexilis.dispatch = nil
  143. // Nexilis.initiateAudio()
  144. if(!id.isEmpty && (UserDefaults.standard.string(forKey: "me") == nil)){
  145. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignUpApi(api: apiKey, p_pin: id), timeout: 30 * 1000){
  146. id = response.getBody(key: CoreMessage_TMessageKey.F_PIN, default_value: "")
  147. let enable_signup = (response.getBody(key: CoreMessage_TMessageKey.IS_ENABLED_ANONYMOUS, default_value: "0")) == "1"
  148. Utils.setForceAnonymous(value: enable_signup)
  149. if(!id.isEmpty) {
  150. Nexilis.changeUser(f_pin: id)
  151. UserDefaults.standard.setValue(id, forKey: "me")
  152. }
  153. }
  154. }
  155. if UserDefaults.standard.string(forKey: "apiKey") == nil {
  156. UserDefaults.standard.setValue(apiKey, forKey: "apiKey")
  157. }
  158. if let me = UserDefaults.standard.string(forKey: "me") {
  159. if Utils.getForceAnonymous() || (!Utils.getForceAnonymous() && Utils.getSetProfile()) {
  160. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  161. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT * FROM BUDDY where f_pin = '\(me)' ") {
  162. if !cursorData.next() {
  163. _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: me))
  164. }
  165. cursorData.close()
  166. }
  167. })
  168. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  169. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT image_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorData.next() {
  170. do {
  171. let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  172. let file = documentDir.appendingPathComponent(cursorData.string(forColumnIndex: 0)!)
  173. if !FileManager().fileExists(atPath: file.path) {
  174. Download().startHTTP(forKey: cursorData.string(forColumnIndex: 0)!) { (name, progress) in}
  175. }
  176. } catch {}
  177. cursorData.close()
  178. }
  179. })
  180. }
  181. getServiceBank()
  182. getPullWorkingArea()
  183. getPullGroupNoMember()
  184. delegate.onSuccess(userId: me)
  185. getPullDefaultCC()
  186. if showButton {
  187. DispatchQueue.main.async {
  188. var viewController = UIApplication.shared.windows.first?.rootViewController
  189. var notNull = false
  190. while !notNull {
  191. viewController = UIApplication.shared.windows.first?.rootViewController
  192. if viewController != nil && Utils.getFinishInitPrefsr() {
  193. notNull = true
  194. }
  195. }
  196. addFB(viewController: viewController!, fromMAB: fromMAB)
  197. }
  198. }
  199. }
  200. Nexilis.destroyAll()
  201. OutgoingThread.default.run()
  202. InquiryThread.default.run()
  203. if UIFont.systemFont(ofSize: 12).familyName == ".AppleSystemUIFont" {
  204. UIFont.libOverrideInitialize()
  205. }
  206. if Utils.getSetProfile() && !Utils.getFinishInitPrefsr() {
  207. Utils.setFinishInitPrefs(value: true)
  208. }
  209. //print("MANIA \(UIFont.systemFont(ofSize: 12)) <> \(UIFont.italicSystemFont(ofSize: 12)) <> \(UIFont.boldSystemFont(ofSize: 12))")
  210. }
  211. catch {
  212. //print(error)
  213. delegate.onFailed(error: "99:Something went wrong")
  214. }
  215. }
  216. static func addFB(viewController: UIViewController, fromMAB: Bool) {
  217. if fromMAB {
  218. var vc = viewController
  219. if viewController is UINavigationController {
  220. vc = (viewController as! UINavigationController).rootViewController!
  221. }
  222. vc.view.addSubview(floatingButton)
  223. floatingButton.mySettingDelegate = vc as? any SettingMABDelegate
  224. } else {
  225. viewController.view.addSubview(floatingButton)
  226. }
  227. }
  228. private static func getPullDefaultCC() {
  229. DispatchQueue.global().async {
  230. if let response = Nexilis.writeSync(message: getPrefs(key: "default_cc"), timeout: 30 * 1000) {
  231. if response.mBodies[CoreMessage_TMessageKey.ERRCOD] == "00" {
  232. let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
  233. if let json = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: []) as? [[String: Any?]] {
  234. if json.count > 0 , let default_cc = json[0]["default_cc"] as? String {
  235. Utils.setDefaultCC(value: default_cc)
  236. }
  237. }
  238. }
  239. }
  240. }
  241. }
  242. private static func getPrefs(key: String) -> TMessage {
  243. let tMessage = NexilisLite.TMessage()
  244. let me = UserDefaults.standard.string(forKey: "me")
  245. tMessage.mCode = "PPR"
  246. tMessage.mStatus = CoreMessage_TMessageUtil.getTID()
  247. tMessage.mBodies[CoreMessage_TMessageKey.F_PIN] = me
  248. tMessage.mBodies[CoreMessage_TMessageKey.KEY] = key
  249. return tMessage
  250. }
  251. private static func getPullGroupNoMember() {
  252. DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
  253. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.pullGroupNoMember(), timeout: 30 * 1000), response.isOk() {
  254. let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
  255. //print("KUACAU \(data)")
  256. if !data.isEmpty {
  257. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  258. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  259. do {
  260. for json in jsonArray {
  261. let group_id = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.GROUP_ID)
  262. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "GROUP_NM", cvalues: [
  263. "group_id" : group_id,
  264. "f_name" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.GROUP_NAME),
  265. "scope_id" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.MESSAGE_SCOPE_ID),
  266. "image_id": CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.THUMB_ID),
  267. "quote": CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.QUOTE),
  268. "last_update" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LAST_UPDATE),
  269. "created_by" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.CREATED_BY),
  270. "created_date" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.CREATED_DATE),
  271. "ex_block" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.BLOCK),
  272. "folder_id" : "",
  273. "chat_modifier" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.CHAT_MODIFIER),
  274. "group_type" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.IS_ORGANIZATION),
  275. "parent" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.PARENT_ID),
  276. "level" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LEVEL),
  277. "is_open" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.IS_OPEN),
  278. "official" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.OFFICIAL_ACCOUNT),
  279. "level_edu" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LEVEL_EDU),
  280. "materi_edu" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.MATERI_EDU),
  281. "is_education" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.IS_EDUCATION)
  282. ], replace: true)
  283. }
  284. } catch {
  285. rollback.pointee = true
  286. //print(error)
  287. }
  288. })
  289. }
  290. }
  291. }
  292. })
  293. }
  294. private static func getServiceBank() {
  295. DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
  296. _ = Nexilis.write(message: CoreMessage_TMessageBank.getServiceBank())
  297. })
  298. }
  299. private static func getPullWorkingArea() {
  300. DispatchQueue.global().asyncAfter(deadline: .now(), execute: {
  301. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getWorkingAreaContactCenter(), timeout: 30 * 1000), response.isOk() {
  302. let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
  303. if !data.isEmpty {
  304. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  305. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  306. do {
  307. for json in jsonArray {
  308. var parent = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.PARENT_ID)
  309. if parent.isEmpty {
  310. parent = "-99"
  311. }
  312. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "WORKING_AREA", cvalues: [
  313. "area_id" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.WORKING_AREA),
  314. "name" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.NAME),
  315. "parent" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.PARENT_ID),
  316. "level" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LEVEL)
  317. ], replace: true)
  318. }
  319. } catch {
  320. rollback.pointee = true
  321. //print(error)
  322. }
  323. })
  324. }
  325. }
  326. }
  327. })
  328. }
  329. public static func destroyAll() {
  330. let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
  331. if !onGoingCC.isEmpty {
  332. let requester = onGoingCC.components(separatedBy: ",")[0]
  333. let officer = onGoingCC.isEmpty ? "" : onGoingCC.components(separatedBy: ",")[1]
  334. let complaintId = onGoingCC.isEmpty ? "" : onGoingCC.components(separatedBy: ",")[2]
  335. let idMe = UserDefaults.standard.string(forKey: "me")!
  336. let startTimeCC = UserDefaults.standard.string(forKey: "startTimeCC") ?? ""
  337. let date = "\(Date().currentTimeMillis())"
  338. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  339. do {
  340. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "CALL_CENTER_HISTORY", cvalues: [
  341. "type" : "0",
  342. "title" : "Contact Center".localized(),
  343. "time" : startTimeCC,
  344. "f_pin" : officer,
  345. "data" : complaintId,
  346. "time_end" : date,
  347. "complaint_id" : complaintId,
  348. "members" : "",
  349. "requester": requester
  350. ], replace: true)
  351. } catch {
  352. rollback.pointee = true
  353. //print(error)
  354. }
  355. })
  356. if officer == idMe {
  357. _ = Nexilis.write(message: CoreMessage_TMessageBank.endCallCenter(complaint_id: complaintId, l_pin: requester))
  358. } else {
  359. if requester == idMe {
  360. _ = Nexilis.write(message: CoreMessage_TMessageBank.endCallCenter(complaint_id: complaintId, l_pin: officer))
  361. } else {
  362. _ = Nexilis.write(message: CoreMessage_TMessageBank.leaveCCRoomInvite(ticket_id: complaintId))
  363. }
  364. }
  365. UserDefaults.standard.removeObject(forKey: "onGoingCC")
  366. UserDefaults.standard.removeObject(forKey: "membersCC")
  367. UserDefaults.standard.removeObject(forKey: "startTimeCC")
  368. if UIApplication.shared.applicationState == .active {
  369. DispatchQueue.main.async {
  370. let imageView = UIImageView(image: UIImage(systemName: "info.circle"))
  371. imageView.tintColor = .white
  372. let banner = FloatingNotificationBanner(title: "Call Center Session has ended".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)
  373. banner.show()
  374. }
  375. }
  376. }
  377. if !Nexilis.onGoingPushCC.isEmpty {
  378. DispatchQueue.global().async {
  379. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: Nexilis.onGoingPushCC["channel"]!, l_pin: Nexilis.onGoingPushCC["l_pin"]!))
  380. }
  381. }
  382. UserDefaults.standard.removeObject(forKey: "inEditorPersonal")
  383. UserDefaults.standard.removeObject(forKey: "inEditorGroup")
  384. UserDefaults.standard.removeObject(forKey: "waitingRequestCC")
  385. }
  386. public static func changeUser(f_pin: String){
  387. do {
  388. //print("change user to fpin")
  389. Nexilis.dispatch = DispatchGroup()
  390. Nexilis.dispatch?.enter()
  391. try API.switchUser(cbiI: Callback(), sUserID: f_pin)
  392. // wait until connection true
  393. Nexilis.dispatch?.wait()
  394. Nexilis.dispatch = nil
  395. //print("success change user to fpin")
  396. // _ = Nexilis.write(message: CoreMessage_TMessageBank.getChangeConnectionID(p_pin: f_pin))
  397. } catch{
  398. //print(error)
  399. }
  400. }
  401. public static func apiSendChat(destination: String, message: String, isGroup: Bool, thumbnailName: String = "", imageName: String = "", videoName: String = "", fileName: String = "", audioName: String = "", replyMessageId : String = "") -> String {
  402. let message = CoreMessage_TMessageBank.sendMessage(l_pin: destination, message_scope_id: isGroup ? "4" : "3", status: "3", message_text: message, credential: "", attachment_flag: !imageName.isEmpty ? "1" : !videoName.isEmpty ? "2" : !audioName.isEmpty ? "5" : !fileName.isEmpty ? "6" : "0", ex_blog_id: "", message_large_text: "", ex_format: "", image_id: imageName, audio_id: audioName, video_id: videoName, file_id: fileName, thumb_id: thumbnailName, reff_id: replyMessageId, read_receipts: "4", chat_id: "", is_call_center: "0", call_center_id: "", opposite_pin: User.getMyPin() ?? "")
  403. addQueueMessage(message: message)
  404. return message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
  405. }
  406. public static func apiInitiateAudioCall(destination: String) {
  407. API.initiateCCall(sParty: destination)
  408. }
  409. public static func apiReceiveAudioCall(destination: String) {
  410. API.receiveCCall(sParty: destination)
  411. }
  412. public static func apiInitiateVideoCall(destination: String, backCamera: Bool = false, listRemoteViews: [UIImageView], localView: UIImageView, remoteViewSpeaker: UIImageView) {
  413. API.initiateCCall(sParty: destination, nCamIdx: backCamera ? 0 : 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViews, ivLocalView: localView, ivRemoteZ: remoteViewSpeaker)
  414. }
  415. public static func apiReceiveVideoCall(destination: String, backCamera: Bool = false, listRemoteViews: [UIImageView], localView: UIImageView, remoteViewSpeaker: UIImageView) {
  416. API.receiveCCall(sParty: destination, nCamIdx: backCamera ? 0 : 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViews, ivLocalView: localView, ivRemoteZ: remoteViewSpeaker)
  417. }
  418. public static func apiInitiateStreaming(localView: UIImageView, titleStream: String = "", backCamera: Bool = false) {
  419. API.initiateBC(sTitle: titleStream, nCamIdx: backCamera ? 0 : 1, nResIdx: 2, nVQuality: 4, ivLocalView: localView)
  420. }
  421. public static func apiJoinStreaming(streamerId: String, remoteView: UIImageView) {
  422. API.joinBC(sBroadcasterID: streamerId, ivRemoteView: remoteView)
  423. }
  424. public static func apiTerminateStreaming(streamerId: String?) {
  425. API.terminateBC(sBroadcasterID: streamerId)
  426. }
  427. public static func apiEndAllCall() {
  428. API.terminateCall(sParty: nil)
  429. }
  430. public static func addQueueMessage(message: TMessage) {
  431. // OutgoingThread.default.addQueue(message: message)
  432. InquiryThread.default.addQueue(message: message)
  433. }
  434. public static func deleteQueueMessage(message: TMessage) {
  435. OutgoingThread.default.addQueue(message: message)
  436. }
  437. private static var wbDelegate: WhiteboardDelegate?
  438. private static var wbReceiver: WhiteboardReceiver?
  439. public static func setWhiteboardDelegate(delegate: WhiteboardDelegate?){
  440. Nexilis.wbDelegate = delegate
  441. }
  442. public static func getWhiteboardDelegate() -> WhiteboardDelegate? {
  443. return Nexilis.wbDelegate
  444. }
  445. public static func setWhiteboardReceiver(receiver: WhiteboardReceiver?){
  446. Nexilis.wbReceiver = receiver
  447. }
  448. public static func getWhiteboardReceiver() -> WhiteboardReceiver? {
  449. return Nexilis.wbReceiver
  450. }
  451. public static func getEditorPersonal() -> EditorPersonal {
  452. return AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  453. }
  454. public static func getEditorGroup() -> EditorGroup {
  455. return AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
  456. }
  457. public static func getEditorStarMessage() -> EditorStarMessages {
  458. return AppStoryBoard.Palio.instance.instantiateViewController(identifier: "staredVC") as! EditorStarMessages
  459. }
  460. static func getAddress(apiKey: String) -> [String] {
  461. var result = [String]()
  462. let url = URL(string: "https://newuniverse.io/dipp/NuN1v3rs3/Qm3r4i0/get_ip?account=\(apiKey)")!
  463. let urlConfig = URLSessionConfiguration.default
  464. urlConfig.requestCachePolicy = .returnCacheDataElseLoad
  465. urlConfig.timeoutIntervalForRequest = 10.0
  466. urlConfig.timeoutIntervalForResource = 10.0
  467. let semaphore = DispatchSemaphore(value: 0)
  468. let task = URLSession(configuration: urlConfig).dataTask(with: url) {(data, response, error) in
  469. guard let data = data else {
  470. semaphore.signal()
  471. return
  472. }
  473. let html = String(data: data, encoding: .utf8)!
  474. let base64Address = html.components(separatedBy: "<body>")[1].components(separatedBy: "</body>")[0].trimmingCharacters(in: .whitespacesAndNewlines)
  475. if let addressData = Data(base64Encoded: base64Address), let decodeAddress = String(data: addressData, encoding: .utf8) {
  476. let rows = decodeAddress.trimmingCharacters(in: CharacterSet.newlines).split(separator: ",")
  477. for r in rows {
  478. let _address = r.split(separator: ":")
  479. var ip:String = ""
  480. let _data = _address[0].split(separator: ".", maxSplits: 4, omittingEmptySubsequences: false)
  481. ip.append(String(_data[3]))
  482. ip.append(".")
  483. ip.append(String(_data[1]))
  484. ip.append(".")
  485. ip.append(String(_data[0]))
  486. ip.append(".")
  487. ip.append(String(_data[2]))
  488. result.append(ip + ":" + _address[2])
  489. }
  490. }
  491. semaphore.signal()
  492. }
  493. task.resume()
  494. _ = semaphore.wait(timeout: .distantFuture)
  495. //print("[App] getAddress:", result)
  496. return result
  497. }
  498. static func getCLMUserId() -> String {
  499. guard let me = UserDefaults.standard.string(forKey: "me") else {
  500. return ""
  501. }
  502. return me
  503. }
  504. public static func writeSync(message: TMessage, timeout: Int = 15 * 1000) -> TMessage? {
  505. do {
  506. //print(">> SENDING MESSAGE >> ", message.toLogString())
  507. if let data = try API.sGetResponse(sRequest: message.pack(), lTimeout: timeout, bKeepTOResp: true) {
  508. let response = TMessage(data: data)
  509. //print("<< RESPONSE MESSAGE << ", response.toLogString())
  510. return response
  511. }
  512. } catch {
  513. //print(error)
  514. }
  515. return nil
  516. }
  517. public static func write(message: TMessage, timeout: Int = 15 * 1000) -> String? {
  518. do {
  519. if API.nGetCLXConnState() == 0 {
  520. return nil
  521. }
  522. //print(">> SENDING MESSAGE >> ", message.toLogString())
  523. if message.getMedia().count == 0 {
  524. if let data = try API.sSend(sData: message.pack(), nPriority: 1, lTimeout: timeout) {
  525. //print("<< RESPONSE MESSAGE << ", data)
  526. return data
  527. }
  528. }
  529. // media
  530. if let data = try API.sSend(abData: message.toBytes(), nPriority: 2, lTimeout: timeout) {
  531. //print("<< RESPONSE MESSAGE << ", data)
  532. return data
  533. }
  534. } catch {
  535. //print(error)
  536. }
  537. return nil
  538. }
  539. public static func writeDraw(data: String, timeout: Int = 15 * 1000) -> String? {
  540. do {
  541. if !API.bInetConnAvailable() {
  542. return nil
  543. }
  544. //print(">> SENDING MESSAGE >> ", data)
  545. if let data = try API.sSend(sData: data, nPriority: 1, lTimeout: timeout) {
  546. //print("<< RESPONSE MESSAGE << ", data)
  547. return data
  548. }
  549. } catch {
  550. //print(error)
  551. }
  552. return nil
  553. }
  554. public static func response(packetId: String, message: TMessage, timeout: Int = 15 * 1000) -> String? {
  555. var result: String? = nil
  556. do {
  557. if !API.bInetConnAvailable() {
  558. return nil
  559. }
  560. //print(">> RESPONSE >> " + packetId + " " + message.toLogString());
  561. result = try API.sSendResponse(sRequestID: packetId, sResponse: message.pack(), lTimeout: timeout)
  562. } catch {
  563. //print(error)
  564. }
  565. return result
  566. }
  567. public static func responseString(packetId: String, message: String, timeout: Int = 15 * 1000) -> String? {
  568. var result: String? = nil
  569. do {
  570. if !API.bInetConnAvailable() {
  571. return nil
  572. }
  573. //print(">> RESPONSE >> " + packetId + " " + message);
  574. result = try API.sSendResponse(sRequestID: packetId, sResponse: message, lTimeout: timeout)
  575. } catch {
  576. //print(error)
  577. }
  578. return result
  579. }
  580. public static func setSpeaker(_ isEnabled: Bool) {
  581. do {
  582. API.adjustVolume(fValue: isEnabled ? 10.0: 3.0)
  583. } catch {
  584. }
  585. }
  586. // public static func initiateAudio() {
  587. // do {
  588. // try AVAudioSession.sharedInstance().setPreferredSampleRate(AVAudioSession.sharedInstance().sampleRate)
  589. // } catch {
  590. // }
  591. // }
  592. // public static func startAudio(isVideo: Bool = true) {
  593. // do {
  594. // try AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: .defaultToSpeaker)
  595. // try AVAudioSession.sharedInstance().setMode(.voiceChat)
  596. // try AVAudioSession.sharedInstance().overrideOutputAudioPort(isVideo ? .speaker : .none)
  597. // try AVAudioSession.sharedInstance().setActive(true)
  598. // } catch {
  599. // }
  600. // }
  601. //
  602. // public static func stopAudio() {
  603. // do {
  604. // try AVAudioSession.sharedInstance().setCategory(.soloAmbient)
  605. // try AVAudioSession.sharedInstance().setMode(.default)
  606. // try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
  607. // try AVAudioSession.sharedInstance().setActive(true)
  608. // } catch {
  609. // }
  610. // }
  611. public static func muteMicrophone(isMute: Bool!){
  612. do {
  613. if(isMute){
  614. try AVAudioSession.sharedInstance().setCategory(.playback)
  615. }
  616. else{
  617. try AVAudioSession.sharedInstance().setCategory(.playAndRecord)
  618. }
  619. }catch{
  620. //print(error)
  621. }
  622. }
  623. public static func buttonClicked(index: Int, id: String = "") {
  624. //print("BTNCLICK \(index) \(id)")
  625. if index == IDX_QUEUE_SYSTEM || index == IDX_NEWS || index == IDX_SOCIAL_COMMERCE {
  626. openUrl(url: id)
  627. } else if index == IDX_NOTIF_CENTER {
  628. APIS.openNotificationCenter()
  629. } else if index == IDX_CHAT {
  630. APIS.openChat()
  631. } else if index == IDX_CALL {
  632. APIS.openCall()
  633. } else if index == IDX_STREAM {
  634. APIS.openStreaming()
  635. } else if index == IDX_CC {
  636. APIS.openContactCenter()
  637. } else if index == IDX_ADDFRIEND {
  638. APIS.openAddFriend()
  639. } else if index == IDX_WB_SS {
  640. APIS.openWhiteboardAndScreenSharing()
  641. } else if index == IDX_WHITEBOARD {
  642. APIS.openWhiteboard()
  643. } else if index == IDX_SCREENSHARING {
  644. APIS.openWhiteboardAndScreenSharing()
  645. } else if index == IDX_POST {
  646. } else if index == IDX_CONVERSATION {
  647. APIS.startConversation()
  648. } else if index == IDX_FAVORITEMESSAGE {
  649. APIS.openFavoriteMessage()
  650. } else {
  651. openApp(id: id)
  652. }
  653. }
  654. public static func openUrl(isBNI: Bool = false, url: String = "") {
  655. let isChangeProfile = Utils.getSetProfile()
  656. if !isChangeProfile {
  657. let alert = LibAlertController(title: "Change Profile".localized(), message: "You must change your name to use this feature".localized(), preferredStyle: .alert)
  658. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  659. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  660. controller.forceLogin = true
  661. let navigationController = UINavigationController(rootViewController: controller)
  662. navigationController.modalPresentationStyle = .fullScreen
  663. navigationController.navigationBar.tintColor = .white
  664. navigationController.navigationBar.barTintColor = .mainColor
  665. navigationController.navigationBar.isTranslucent = false
  666. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  667. navigationController.navigationBar.barStyle = .black
  668. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  669. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  670. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  671. navigationController.navigationBar.titleTextAttributes = textAttributes
  672. navigationController.view.backgroundColor = .mainColor
  673. if UIApplication.shared.visibleViewController?.navigationController != nil {
  674. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  675. } else {
  676. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  677. }
  678. }))
  679. if UIApplication.shared.visibleViewController?.navigationController != nil {
  680. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  681. } else {
  682. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  683. }
  684. return
  685. }
  686. let controller = BNIBookingWebView()
  687. if !isBNI {
  688. controller.customUrl = url
  689. }
  690. if UIApplication.shared.visibleViewController?.navigationController != nil {
  691. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  692. } else {
  693. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  694. }
  695. }
  696. public static func openApp(id: String) {
  697. //print("openApp itms-apps://apple.com/app/\(id)")
  698. let isChangeProfile = Utils.getSetProfile()
  699. if !isChangeProfile {
  700. let alert = LibAlertController(title: "Change Profile".localized(), message: "You must change your name to use this feature".localized(), preferredStyle: .alert)
  701. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  702. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  703. controller.forceLogin = true
  704. let navigationController = UINavigationController(rootViewController: controller)
  705. navigationController.modalPresentationStyle = .fullScreen
  706. navigationController.navigationBar.tintColor = .white
  707. navigationController.navigationBar.barTintColor = .mainColor
  708. navigationController.navigationBar.isTranslucent = false
  709. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  710. navigationController.navigationBar.barStyle = .black
  711. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  712. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  713. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  714. navigationController.navigationBar.titleTextAttributes = textAttributes
  715. navigationController.view.backgroundColor = .mainColor
  716. if UIApplication.shared.visibleViewController?.navigationController != nil {
  717. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  718. } else {
  719. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  720. }
  721. }))
  722. if UIApplication.shared.visibleViewController?.navigationController != nil {
  723. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  724. } else {
  725. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  726. }
  727. return
  728. }
  729. if id == nil {
  730. return
  731. }
  732. if let url = URL(string: "itms-apps://apple.com/app/\(id)") {
  733. UIApplication.shared.open(url)
  734. }
  735. }
  736. static func openmailAction() {
  737. if let googleUrl = NSURL(string: "googlegmail://"), UIApplication.shared.canOpenURL(googleUrl as URL) {
  738. openMail(googleUrl)
  739. } else if let mailURL = NSURL(string: "message://"), UIApplication.shared.canOpenURL(mailURL as URL) {
  740. openMail(mailURL)
  741. } else if let outlookURL = NSURL(string: "ms-outlook://"), UIApplication.shared.canOpenURL(outlookURL as URL) {
  742. openMail(outlookURL)
  743. } else if let yahooURL = NSURL(string: "ymail://"), UIApplication.shared.canOpenURL(yahooURL as URL) {
  744. openMail(yahooURL)
  745. } else if let sparkUrl = NSURL(string: "readdle-spark://"), UIApplication.shared.canOpenURL(sparkUrl as URL) {
  746. openMail(sparkUrl)
  747. } else {
  748. // showAlert
  749. }
  750. }
  751. private static func openMail(_ url: NSURL) {
  752. UIApplication.shared.open(url as URL, options: [:], completionHandler: nil)
  753. }
  754. static var alertChangeProfile = LibAlertController()
  755. public static func checkIsChangePerson() -> Bool {
  756. let isChangeProfile = Utils.getSetProfile()
  757. if !isChangeProfile {
  758. alertChangeProfile.dismiss(animated: false)
  759. alertChangeProfile = LibAlertController(title: "Change Profile".localized(), message: "You must change your name to use this feature".localized().localized(), preferredStyle: .alert)
  760. alertChangeProfile.addAction(UIAlertAction(title: "Cancel".localized(), style: .destructive, handler: nil))
  761. alertChangeProfile.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  762. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  763. controller.forceLogin = true
  764. let navigationController = UINavigationController(rootViewController: controller)
  765. navigationController.modalPresentationStyle = .fullScreen
  766. navigationController.navigationBar.tintColor = .white
  767. navigationController.navigationBar.barTintColor = .mainColor
  768. navigationController.navigationBar.isTranslucent = false
  769. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  770. navigationController.navigationBar.barStyle = .black
  771. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  772. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  773. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  774. navigationController.navigationBar.titleTextAttributes = textAttributes
  775. navigationController.view.backgroundColor = .mainColor
  776. let rootVC = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController
  777. if rootVC?.presentedViewController == nil {
  778. rootVC?.present(navigationController, animated: true, completion: nil)
  779. } else {
  780. rootVC?.presentedViewController?.present(navigationController, animated: true, completion: nil)
  781. }
  782. }))
  783. let rootVC = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController
  784. if rootVC?.presentedViewController == nil {
  785. rootVC?.present(alertChangeProfile, animated: true, completion: nil)
  786. } else {
  787. rootVC?.presentedViewController?.present(alertChangeProfile, animated: true, completion: nil)
  788. }
  789. return false
  790. }
  791. return true
  792. }
  793. public static func showLoader() {
  794. loadingAlert = LibAlertController(title: nil, message: "Please wait...".localized(), preferredStyle: .alert)
  795. let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
  796. loadingIndicator.hidesWhenStopped = true
  797. loadingIndicator.style = .medium
  798. loadingIndicator.startAnimating()
  799. loadingAlert.view.addSubview(loadingIndicator)
  800. UIApplication.shared.visibleViewController?.present(loadingAlert, animated: true, completion: nil)
  801. }
  802. public static func hideLoader(completion: @escaping () -> ()) {
  803. loadingAlert.dismiss(animated: true, completion: completion)
  804. }
  805. private static var groupWait = DispatchGroup()
  806. private static var waitQueue = [String: TMessage]()
  807. private static var onDispatchGroupLeave = ""
  808. public static func writeAndWait(message: TMessage, timeout: Int = 15 * 1000) -> TMessage? {
  809. groupWait.enter()
  810. _ = write(message: message, timeout: timeout)
  811. waitQueue[message.getStatus()] = message
  812. if groupWait.wait(timeout: .now() + 15) == .timedOut {
  813. waitQueue.removeValue(forKey: message.getStatus())
  814. groupWait.leave()
  815. return nil
  816. }
  817. return waitQueue.removeValue(forKey: message.getStatus())
  818. }
  819. static func incomingData(packetId: String, data: AnyObject) {
  820. let message = TMessage()
  821. if data is String {
  822. let d = data as! String
  823. guard message.unpack(data: d) else {
  824. //print("UNKNOWN DATA STRING...", data)
  825. if(data.hasPrefix("WB")){
  826. let dataWB = data.components(separatedBy: "/")
  827. if(dataWB[1] == "1"){
  828. let x = dataWB[2]
  829. let y = dataWB[3]
  830. let w = dataWB[4]
  831. let h = dataWB[5]
  832. let fc = dataWB[6]
  833. let sw = dataWB[7]
  834. let xo = dataWB[8]
  835. let yo = dataWB[9]
  836. if(Nexilis.getWhiteboardDelegate() != nil){
  837. Nexilis.getWhiteboardDelegate()!.draw(x: x, y: y, w: w, h: h, fc: fc, sw: sw, xo: xo, yo: yo, data: "")
  838. }
  839. } else if(dataWB[1] == "3") {
  840. if(Nexilis.getWhiteboardDelegate() != nil){
  841. Nexilis.getWhiteboardDelegate()!.clear()
  842. }
  843. } else if(dataWB[1] == "2"){
  844. if(Nexilis.getWhiteboardReceiver() != nil){
  845. Nexilis.getWhiteboardReceiver()!.incomingWB(roomId: dataWB[2])
  846. }
  847. } else if(dataWB[1] == "22"){
  848. } else if(dataWB[1] == "88"){
  849. if(Nexilis.getWhiteboardReceiver() != nil){
  850. Nexilis.getWhiteboardReceiver()!.cancel(roomId: dataWB[2])
  851. }
  852. }
  853. }
  854. return
  855. }
  856. } else if data is [UInt8] {
  857. let d = data as! [UInt8]
  858. guard message.unpack(bytes_data: d) else {
  859. //print("UNKNOWN DATA BYTES...", data)
  860. return
  861. }
  862. }
  863. message.mBodies[CoreMessage_TMessageKey.PACKET_ID] = packetId
  864. if let _ = waitQueue[message.getStatus()] {
  865. //print("MESSAGE INCOMING DATA \(message.toLogString())")
  866. if message.mBodies.keys.contains(CoreMessage_TMessageKey.ERRCOD) {
  867. if onDispatchGroupLeave != message.getStatus() {
  868. onDispatchGroupLeave = message.getStatus()
  869. //print("LEAVE GROUP INCOMING DATA")
  870. waitQueue[message.getStatus()] = message
  871. groupWait.leave()
  872. return
  873. }
  874. }
  875. }
  876. IncomingThread.default.addQueue(message: message)
  877. }
  878. static func saveMessage(message: TMessage, withStatus: Bool = true) {
  879. guard let me = UserDefaults.standard.string(forKey: "me") else {
  880. return
  881. }
  882. let message_id = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_ID, default_value : "")
  883. guard !message_id.isEmpty else {
  884. return
  885. }
  886. let f_pin = message.getBody(key : CoreMessage_TMessageKey.F_PIN, default_value : "")
  887. guard !f_pin.isEmpty else {
  888. return
  889. }
  890. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  891. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(message_id)'") {
  892. if cursor.next() {
  893. //print("message exist")
  894. return
  895. }
  896. cursor.close()
  897. }
  898. let l_pin = message.getBody(key : CoreMessage_TMessageKey.L_PIN, default_value : "")
  899. let scope = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_SCOPE_ID, default_value : "3")
  900. let status = message.getBody(key : CoreMessage_TMessageKey.STATUS, default_value : "")
  901. let chat_id = message.getBody(key : CoreMessage_TMessageKey.CHAT_ID, default_value : "")
  902. let broadcast_flag = message.getBody(key: CoreMessage_TMessageKey.BROADCAST_FLAG, default_value: "0")
  903. let is_call_center = message.getBody(key: CoreMessage_TMessageKey.IS_CALL_CENTER, default_value: "0")
  904. let call_center_id = message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID, default_value: "")
  905. let opposite_pin = message.getBody(key: CoreMessage_TMessageKey.OPPOSITE_PIN, default_value: "")
  906. //print("prepare save db")
  907. do {
  908. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
  909. "message_id" : message_id,
  910. "f_pin" : f_pin,
  911. "f_display_name" : message.getBody(key : CoreMessage_TMessageKey.F_DISPLAY_NAME, default_value : ""),
  912. "l_pin" : l_pin,
  913. "l_user_id" : message.getBody(key : CoreMessage_TMessageKey.L_USER_ID, default_value : ""),
  914. "message_scope_id" : scope,
  915. "server_date" : message.getBody(key: CoreMessage_TMessageKey.SERVER_DATE, default_value : String(Date().currentTimeMillis())),
  916. "status" : status,
  917. "message_text" : message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString(),
  918. "audio_id" : message.getBody(key : CoreMessage_TMessageKey.AUDIO_ID, default_value : ""),
  919. "video_id" : message.getBody(key : CoreMessage_TMessageKey.VIDEO_ID, default_value : ""),
  920. "image_id" : message.getBody(key : CoreMessage_TMessageKey.IMAGE_ID, default_value : ""),
  921. "file_id" : message.getBody(key : CoreMessage_TMessageKey.FILE_ID, default_value : ""),
  922. "thumb_id" : message.getBody(key : CoreMessage_TMessageKey.THUMB_ID, default_value : ""),
  923. "opposite_pin" : message.getBody(key : CoreMessage_TMessageKey.OPPOSITE_PIN, default_value : ""),
  924. "format" : message.getBody(key : CoreMessage_TMessageKey.FORMAT, default_value : ""),
  925. "blog_id" : message.getBody(key : CoreMessage_TMessageKey.BLOG_ID, default_value : ""),
  926. "read_receipts" : message.getBody(key: CoreMessage_TMessageKey.READ_RECEIPTS, default_value: "0"),
  927. "chat_id" : chat_id,
  928. "account_type" : message.getBody(key : CoreMessage_TMessageKey.BUSINESS_CATEGORY, default_value : "1"),
  929. "credential" : message.getBody(key : CoreMessage_TMessageKey.CREDENTIAL, default_value : ""),
  930. "reff_id" : message.getBody(key : CoreMessage_TMessageKey.REF_ID, default_value : ""),
  931. "message_large_text" : message.getBody(key : CoreMessage_TMessageKey.BODY, default_value : "").toNormalString(),
  932. "attachment_flag" : message.getBody(key: CoreMessage_TMessageKey.ATTACHMENT_FLAG, default_value: "0"),
  933. "local_timestamp" : message.getBody(key: CoreMessage_TMessageKey.LOCAL_TIMESTAMP, default_value : String(Date().currentTimeMillis())),
  934. "broadcast_flag" : broadcast_flag,
  935. "is_call_center" : is_call_center,
  936. "call_center_id" : call_center_id
  937. ], replace: true)
  938. } catch {
  939. rollback.pointee = true
  940. //print(error)
  941. }
  942. if withStatus {
  943. do {
  944. if scope == "4" {
  945. for pin in getGroupMembers(fmdb: fmdb, l_pin: l_pin) {
  946. if f_pin == pin { continue }
  947. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  948. "message_id" : message_id,
  949. "status" : status,
  950. "f_pin" : pin,
  951. "last_update" : Date().currentTimeMillis()
  952. ], replace: true)
  953. }
  954. } else {
  955. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  956. "message_id" : message_id,
  957. "status" : status,
  958. "f_pin" : l_pin,
  959. "last_update" : Date().currentTimeMillis()
  960. ], replace: true)
  961. }
  962. } catch {
  963. rollback.pointee = true
  964. //print(error)
  965. }
  966. }
  967. var pin = l_pin
  968. if l_pin == me {
  969. pin = f_pin
  970. }
  971. if !chat_id.isEmpty {
  972. pin = chat_id
  973. }
  974. var counter : Int? = nil
  975. if !withStatus {
  976. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
  977. counter = Int(cursor.int(forColumnIndex: 0))
  978. counter! += 1
  979. cursor.close()
  980. //print("select db message summary")
  981. }
  982. if counter == nil {
  983. counter = 1
  984. //print("set counter message summary")
  985. }
  986. }
  987. if counter == nil {
  988. counter = 0
  989. }
  990. if is_call_center == "0" {
  991. do {
  992. var queryGetLastMessageId = "SELECT message_id FROM MESSAGE where f_pin = '\(pin)' OR l_pin = '\(pin)' order by server_date desc LIMIT 1"
  993. if scope == "4" {
  994. queryGetLastMessageId = "SELECT message_id FROM MESSAGE where l_pin = '\(pin)' order by server_date desc LIMIT 1"
  995. if !chat_id.isEmpty {
  996. queryGetLastMessageId = "SELECT message_id FROM MESSAGE where chat_id = '\(pin)' order by server_date desc LIMIT 1"
  997. }
  998. }
  999. var messageId = ""
  1000. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: queryGetLastMessageId), cursorData.next() {
  1001. messageId = cursorData.string(forColumnIndex: 0) ?? ""
  1002. cursorData.close()
  1003. }
  1004. if !messageId.isEmpty {
  1005. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
  1006. "l_pin" : pin,
  1007. "message_id" : messageId,
  1008. "counter" : counter!
  1009. ], replace: true)
  1010. }
  1011. } catch {
  1012. rollback.pointee = true
  1013. //print(error)
  1014. }
  1015. }
  1016. if !withStatus {
  1017. DispatchQueue.main.async {
  1018. if let delegate = Nexilis.shared.messageDelegate, Utils.getSetProfile() {
  1019. message.mBodies[CoreMessage_TMessageKey.MESSAGE_TEXT] = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString()
  1020. delegate.onReceive(message: message)
  1021. }
  1022. }
  1023. }
  1024. //print("insert db message summary \(message_id)")
  1025. })
  1026. }
  1027. public static func saveMessageBot(textMessage: String, blog_id: String, attachment_type:String)->Void{
  1028. guard let me = UserDefaults.standard.string(forKey: "me") else {
  1029. return
  1030. }
  1031. var user_id:String? = ""
  1032. let message_id = me + CoreMessage_TMessageUtil.getTID()
  1033. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1034. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select user_id from BUDDY where f_pin = '\(me)'"), cursor.next() {
  1035. user_id = cursor.string(forColumnIndex: 0)
  1036. cursor.close()
  1037. }
  1038. })
  1039. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1040. do {
  1041. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
  1042. "message_id" : message_id ,
  1043. "f_pin" : "-999",
  1044. "f_display_name" : "Bot",
  1045. "l_pin" : me,
  1046. "l_user_id" : String(user_id!),
  1047. "message_scope_id" : "3",
  1048. "server_date" : String(Date().currentTimeMillis()),
  1049. "status" : "3",
  1050. "message_text" : textMessage,
  1051. "audio_id" : "",
  1052. "video_id" : "",
  1053. "image_id" : "",
  1054. "file_id" : "",
  1055. "thumb_id" : "",
  1056. "opposite_pin" : "",
  1057. "format" : "",
  1058. "blog_id" : blog_id,
  1059. "read_receipts" : "0",
  1060. "chat_id" : "",
  1061. "account_type" : "1",
  1062. "credential" :"",
  1063. "reff_id" : "",
  1064. "message_large_text" : "",
  1065. "attachment_flag" : attachment_type,
  1066. "local_timestamp" : String(Date().currentTimeMillis())
  1067. ], replace: true)
  1068. } catch {
  1069. rollback.pointee = true
  1070. //print(error)
  1071. }
  1072. })
  1073. let pin = "-999"
  1074. var counter : Int? = nil
  1075. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1076. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
  1077. counter = Int(cursor.int(forColumnIndex: 0))
  1078. counter! += 1
  1079. cursor.close()
  1080. //print("select db message summary")
  1081. }
  1082. })
  1083. if counter == nil {
  1084. counter = 1
  1085. //print("set counter message summary")
  1086. }
  1087. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1088. do {
  1089. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
  1090. "l_pin" : pin,
  1091. "message_id" : message_id,
  1092. "counter" : counter!
  1093. ], replace: true)
  1094. } catch {
  1095. rollback.pointee = true
  1096. //print(error)
  1097. }
  1098. })
  1099. //print("insert db message summary \(message_id)")
  1100. }
  1101. static func updateMessageStatus(message: TMessage) -> Void {
  1102. let message_id = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_ID, default_value : "")
  1103. guard !message_id.isEmpty else {
  1104. return
  1105. }
  1106. let status = message.getBody(key : CoreMessage_TMessageKey.STATUS, default_value : "")
  1107. guard !status.isEmpty else {
  1108. return
  1109. }
  1110. let l_pin = message.getBody(key : CoreMessage_TMessageKey.L_PIN, default_value : "")
  1111. guard !l_pin.isEmpty else {
  1112. return
  1113. }
  1114. Database.shared.database?.inTransaction({ (fmdb, rollbac) in
  1115. if message_id.starts(with: "-1") || message_id.starts(with: "-2") {
  1116. for s in message_id.split(separator: ",") {
  1117. let t = s.trimmingCharacters(in: .whitespaces)
  1118. if t == "-1" || t == "-2" {
  1119. continue
  1120. }
  1121. if status == "3" {
  1122. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1123. "status" : status,
  1124. "time_delivered" : String(Date().currentTimeMillis()),
  1125. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
  1126. } else if status == "4" {
  1127. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1128. "status" : status,
  1129. "time_read" : String(Date().currentTimeMillis()),
  1130. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
  1131. } else if status == "8" {
  1132. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1133. "status" : status,
  1134. "time_ack" : String(Date().currentTimeMillis()),
  1135. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
  1136. } else {
  1137. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1138. "status" : status,
  1139. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
  1140. }
  1141. }
  1142. } else {
  1143. if status == "3" {
  1144. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1145. "status" : status,
  1146. "time_delivered" : String(Date().currentTimeMillis()),
  1147. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
  1148. } else if status == "4" {
  1149. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1150. "status" : status,
  1151. "time_read" : String(Date().currentTimeMillis()),
  1152. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
  1153. } else if status == "8" {
  1154. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1155. "status" : status,
  1156. "time_ack" : String(Date().currentTimeMillis()),
  1157. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
  1158. } else {
  1159. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1160. "status" : status,
  1161. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
  1162. }
  1163. }
  1164. })
  1165. }
  1166. static func getGroupMembers(fmdb: FMDatabase, l_pin: String) -> [String] {
  1167. var result = [String]()
  1168. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin from GROUPZ_MEMBER where group_id = '\(l_pin)'") {
  1169. while cursor.next() {
  1170. if let value = cursor.string(forColumnIndex: 0) {
  1171. result.append(value)
  1172. }
  1173. }
  1174. cursor.close()
  1175. }
  1176. return result
  1177. }
  1178. static func getVideoThumbnail(name: String, completion: @escaping (Bool)->()) {
  1179. DispatchQueue.global().async {
  1180. do {
  1181. let fileManager = FileManager.default
  1182. let documentDir = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  1183. let fileDir = documentDir.appendingPathComponent(name)
  1184. let path = fileDir.path
  1185. if FileManager.default.fileExists(atPath: path) {
  1186. let asset = AVAsset(url: URL(fileURLWithPath: path))
  1187. let avAssetImageGenerator = AVAssetImageGenerator(asset: asset)
  1188. avAssetImageGenerator.appliesPreferredTrackTransform = true
  1189. let thumnailTime = CMTimeMake(value: 2, timescale: 1)
  1190. let thumbImage = UIImage(cgImage: try avAssetImageGenerator.copyCGImage(at: thumnailTime, actualTime: nil))
  1191. guard let data = thumbImage.jpegData(compressionQuality: 1.0) else {
  1192. completion(false)
  1193. return
  1194. }
  1195. let thumbFileDir = documentDir.appendingPathComponent("THUMB_" + name)
  1196. try data.write(to: thumbFileDir)
  1197. completion(true)
  1198. } else {
  1199. completion(false)
  1200. }
  1201. } catch {
  1202. //print(error)
  1203. }
  1204. }
  1205. }
  1206. static func resizedImage(at url: URL, for size: CGSize) -> UIImage? {
  1207. guard let image = UIImage(contentsOfFile: url.path) else {
  1208. return nil
  1209. }
  1210. let renderer = UIGraphicsImageRenderer(size: size)
  1211. return renderer.image { (context) in
  1212. image.draw(in: CGRect(origin: .zero, size: size))
  1213. }
  1214. }
  1215. static func initFollowing() -> Void {
  1216. if let me = UserDefaults.standard.string(forKey: "me") {
  1217. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getListFollowing(l_pin: me)) {
  1218. let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
  1219. if !data.isEmpty {
  1220. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  1221. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1222. do {
  1223. for json in jsonArray {
  1224. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "FOLLOW", cvalues: [
  1225. "f_pin" : CoreMessage_TMessageUtil.getString(json: json, key: "pin")
  1226. ], replace: true)
  1227. }
  1228. } catch {
  1229. rollback.pointee = true
  1230. //print(error)
  1231. }
  1232. })
  1233. }
  1234. }
  1235. }
  1236. }
  1237. }
  1238. // do {
  1239. // _ = try Database.shared.insertRecord(fmdb: fmdb, table: "CALL_CENTER_HISTORY", cvalues: [
  1240. // "type" : "1",
  1241. // "title" : displayName,
  1242. // "time" : timeStart,
  1243. // "f_pin" : f_pin,
  1244. // "data" : dataCC,
  1245. // "time_end" : date,
  1246. // "complaint_id" : complaint_id.isEmpty ? "C\(date)" : complaint_id,
  1247. // "members" : "",
  1248. // "requester": ""
  1249. // ], replace: true)
  1250. // _ = try Database.shared.insertRecord(fmdb: fmdb, table: "PREFS", cvalues: [
  1251. // "key" : "CC:\(f_pin)",
  1252. // "value" : status,
  1253. // ], replace: true)
  1254. // ret = true
  1255. // } catch {
  1256. // rollback.pointee = true
  1257. // //print(error)
  1258. // }
  1259. private static var uploadQueue = DispatchQueue(label: "UPLOAD_DICT", attributes: .concurrent)
  1260. private static var UPLOAD_DICT = [String: Network]()
  1261. static func removeUploadFile(forKey: String) -> Network? {
  1262. var _result: Network? = nil
  1263. uploadQueue.sync {
  1264. _result = self.UPLOAD_DICT.removeValue(forKey: forKey)
  1265. }
  1266. return _result
  1267. }
  1268. static func putUploadFile(forKey: String, uploader: Network) {
  1269. uploadQueue.async (flags: .barrier) {
  1270. self.UPLOAD_DICT[forKey] = uploader
  1271. }
  1272. }
  1273. static func getUploadFile(forKey: String) -> Network? {
  1274. var _result: Network? = nil
  1275. uploadQueue.sync {
  1276. _result = self.UPLOAD_DICT[forKey]
  1277. }
  1278. return _result
  1279. }
  1280. private static var downloadQueue = DispatchQueue(label: "DOWNLOAD_DICT", attributes: .concurrent)
  1281. private static var DOWNLOAD_DICT = [String:Download]()
  1282. static func addDownload(forKey : String, download: Download){
  1283. downloadQueue.async (flags: .barrier) {
  1284. self.DOWNLOAD_DICT[forKey] = download
  1285. }
  1286. }
  1287. static func getDownload(forKey: String) -> Download? {
  1288. var _result: Download? = nil
  1289. downloadQueue.sync {
  1290. _result = self.DOWNLOAD_DICT[forKey]
  1291. }
  1292. return _result
  1293. }
  1294. static func removeDownload(forKey: String) -> Download? {
  1295. var _result: Download? = nil
  1296. downloadQueue.sync {
  1297. _result = self.DOWNLOAD_DICT.removeValue(forKey: forKey)
  1298. }
  1299. return _result
  1300. }
  1301. static func writeImageToFile(data: Data, fileName: String){
  1302. guard let directory = FileManager.default.urls(for: .picturesDirectory, in: .userDomainMask).last else {
  1303. return
  1304. }
  1305. let fileURL = directory.appendingPathComponent("\(fileName)")
  1306. if FileManager.default.fileExists(atPath: fileURL.path) {
  1307. if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
  1308. fileHandle.seekToEndOfFile()
  1309. fileHandle.write(data)
  1310. fileHandle.closeFile()
  1311. } else {
  1312. //print("Can't open file to write")
  1313. }
  1314. } else {
  1315. do {
  1316. try data.write(to: fileURL, options: .atomic)
  1317. } catch {
  1318. //print("Unable to write in new file")
  1319. }
  1320. }
  1321. }
  1322. static func writeVideoToFile(data: Data, fileName: String){
  1323. guard let directory = FileManager.default.urls(for: .moviesDirectory, in: .userDomainMask).last else {
  1324. return
  1325. }
  1326. let fileURL = directory.appendingPathComponent("\(fileName)")
  1327. if FileManager.default.fileExists(atPath: fileURL.path) {
  1328. if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
  1329. fileHandle.seekToEndOfFile()
  1330. fileHandle.write(data)
  1331. fileHandle.closeFile()
  1332. } else {
  1333. //print("Can't open file to write")
  1334. }
  1335. } else {
  1336. do {
  1337. try data.write(to: fileURL, options: .atomic)
  1338. } catch {
  1339. //print("Unable to write in new file")
  1340. }
  1341. }
  1342. }
  1343. static func writeDocumentsToFile(data: Data, fileName: String){
  1344. guard let directory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last else {
  1345. return
  1346. }
  1347. let fileURL = directory.appendingPathComponent("\(fileName)")
  1348. if FileManager.default.fileExists(atPath: fileURL.path) {
  1349. if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
  1350. fileHandle.seekToEndOfFile()
  1351. fileHandle.write(data)
  1352. fileHandle.closeFile()
  1353. } else {
  1354. //print("Can't open file to write")
  1355. }
  1356. } else {
  1357. do {
  1358. try data.write(to: fileURL, options: .atomic)
  1359. } catch {
  1360. //print("Unable to write in new file")
  1361. }
  1362. }
  1363. }
  1364. public static func checkMicPermission() -> Bool {
  1365. var permissionCheck: Bool = false
  1366. switch AVAudioSession.sharedInstance().recordPermission {
  1367. case .granted:
  1368. permissionCheck = true
  1369. case .denied:
  1370. permissionCheck = false
  1371. case .undetermined:
  1372. AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
  1373. if granted {
  1374. permissionCheck = true
  1375. } else {
  1376. permissionCheck = false
  1377. }
  1378. })
  1379. default:
  1380. break
  1381. }
  1382. return permissionCheck
  1383. }
  1384. public static func checkCameraPermission() -> Int {
  1385. var permissionCheck: Int = -1
  1386. if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
  1387. permissionCheck = 1
  1388. } else if AVCaptureDevice.authorizationStatus(for: .video) == .denied {
  1389. permissionCheck = 0
  1390. } else {
  1391. AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) -> Void in
  1392. })
  1393. }
  1394. return permissionCheck
  1395. }
  1396. public static func startTimer(){
  1397. broadcastTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: {_ in
  1398. if(!openBroadcast && !broadcastList.isEmpty){
  1399. openBroadcast = true
  1400. let m = broadcastList.removeFirst()
  1401. //print("broadcast show: \(m)")
  1402. DispatchQueue.main.async {
  1403. Nexilis.shared.showBroadcastMessage(m: m)
  1404. }
  1405. }
  1406. })
  1407. }
  1408. /*
  1409. * Delegate
  1410. */
  1411. weak open var loginDelegate: LoginDelegate?
  1412. weak open var messageDelegate: MessageDelegate?
  1413. weak open var groupDelegate: GroupDelegate?
  1414. weak open var callDelegate: CallDelegate?
  1415. weak open var streamingDelagate: LiveStreamingDelegate?
  1416. weak open var seminarDelegate: SeminarDelegate?
  1417. weak open var personInfoDelegate: PersonInfoDelegate?
  1418. weak open var screenSharingDelegate: ScreenSharingDelegate?
  1419. weak open var commentDelegate: CommentDelegate?
  1420. weak open var uploadDelegate: UploadDelegate?
  1421. weak open var timelineDelegate: TimelineDelegate?
  1422. weak open var connectionDelegate: ConnectionDelegate?
  1423. var floating: FloatingNotificationBanner!
  1424. var stateUnfriend = ""
  1425. }
  1426. struct LibFontName {
  1427. static let regular = "Poppins-Regular"
  1428. static let bold = "Poppins-SemiBold"
  1429. static let italic = "Poppins-Italic"
  1430. static let medium = "Poppins-Medium"
  1431. static let boldItalic = "Poppins-SemiBoldItalic"
  1432. }
  1433. extension UIFontDescriptor.AttributeName {
  1434. static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
  1435. }
  1436. extension UIFont {
  1437. static var isOverrided: Bool = false
  1438. static let FONT_SELECT = 0
  1439. @objc class func libSystemFont(ofSize size: CGFloat) -> UIFont? {
  1440. jbs_registerFont(withFilenameString: LibFontName.regular)
  1441. return UIFont(name: LibFontName.regular, size: size)
  1442. }
  1443. @objc class func libSystemFontWeight(ofSize size: CGFloat, weight: UIFont.Weight) -> UIFont? {
  1444. if weight == .medium {
  1445. jbs_registerFont(withFilenameString: LibFontName.medium)
  1446. return UIFont(name: LibFontName.medium, size: size)
  1447. } else if weight == .semibold {
  1448. jbs_registerFont(withFilenameString: LibFontName.boldItalic)
  1449. return UIFont(name: LibFontName.boldItalic, size: size)
  1450. }
  1451. return UIFont(name: LibFontName.regular, size: size)
  1452. }
  1453. @objc class func libBoldSystemFont(ofSize size: CGFloat) -> UIFont? {
  1454. jbs_registerFont(withFilenameString: LibFontName.bold)
  1455. return UIFont(name: LibFontName.bold, size: size)
  1456. }
  1457. @objc class func libItalicSystemFont(ofSize size: CGFloat) -> UIFont? {
  1458. jbs_registerFont(withFilenameString: LibFontName.italic)
  1459. return UIFont(name: LibFontName.italic, size: size)
  1460. }
  1461. @objc convenience init(myCoder aDecoder: NSCoder) {
  1462. guard
  1463. let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
  1464. let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
  1465. self.init(myCoder: aDecoder)
  1466. return
  1467. }
  1468. var fontName = ""
  1469. switch fontAttribute {
  1470. case "CTFontRegularUsage":
  1471. fontName = LibFontName.regular
  1472. case "CTFontEmphasizedUsage", "CTFontBoldUsage":
  1473. fontName = LibFontName.bold
  1474. case "CTFontObliqueUsage":
  1475. fontName = LibFontName.italic
  1476. default:
  1477. fontName = LibFontName.regular
  1478. }
  1479. self.init(name: fontName, size: fontDescriptor.pointSize)!
  1480. }
  1481. class func libOverrideInitialize() {
  1482. guard self == UIFont.self, !isOverrided, FONT_SELECT == 0 else { return }
  1483. // Avoid method swizzling run twice and revert to original initialize function
  1484. isOverrided = true
  1485. if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
  1486. let mySystemFontMethod = class_getClassMethod(self, #selector(libSystemFont(ofSize:))) {
  1487. method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
  1488. }
  1489. if let systemFontWeightMethod = class_getClassMethod(self, #selector(systemFont(ofSize:weight:))),
  1490. let mySystemFontWeightMethod = class_getClassMethod(self, #selector(libSystemFontWeight(ofSize:weight:))) {
  1491. method_exchangeImplementations(systemFontWeightMethod, mySystemFontWeightMethod)
  1492. }
  1493. if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
  1494. let myBoldSystemFontMethod = class_getClassMethod(self, #selector(libBoldSystemFont(ofSize:))) {
  1495. method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
  1496. }
  1497. if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
  1498. let myItalicSystemFontMethod = class_getClassMethod(self, #selector(libItalicSystemFont(ofSize:))) {
  1499. method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
  1500. }
  1501. if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))), // Trick to get over the lack of UIFont.init(coder:))
  1502. let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) {
  1503. method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
  1504. }
  1505. }
  1506. class func jbs_registerFont(withFilenameString filenameString: String) {
  1507. // guard let pathForResourceString = Bundle.resourceBundle(for: Nexilis.self).path(forResource: filenameString, ofType: "otf") else { //resourcesMediaBundle
  1508. // //print("UIFont+: Failed to register font - path for resource not found.")
  1509. // return
  1510. // }
  1511. guard let pathForResourceURL = Bundle.resourceBundle(for: Nexilis.self).url(forResource: filenameString, withExtension: "otf") else { //resourcesMediaBundle
  1512. //print("UIFont+: Failed to register font - path for resource not found.")
  1513. return
  1514. }
  1515. var errorRef: Unmanaged<CFError>? = nil
  1516. CTFontManagerRegisterFontsForURL(pathForResourceURL as CFURL, .process, &errorRef)
  1517. // guard let fontData = NSData(contentsOfFile: pathForResourceString) else {
  1518. // //print("UIFont+: Failed to register font - font data could not be loaded.")
  1519. // return
  1520. // }
  1521. //
  1522. // guard let dataProvider = CGDataProvider(data: fontData) else {
  1523. // //print("UIFont+: Failed to register font - data provider could not be loaded.")
  1524. // return
  1525. // }
  1526. //
  1527. // guard let font = CGFont(dataProvider) else {
  1528. // //print("UIFont+: Failed to register font - font could not be loaded.")
  1529. // return
  1530. // }
  1531. //
  1532. // var errorRef: Unmanaged<CFError>? = nil
  1533. // if (CTFontManagerRegisterGraphicsFont(font, &errorRef) == false) {
  1534. // }
  1535. }
  1536. }
  1537. public protocol LoginDelegate: NSObjectProtocol {
  1538. func onProgress(code: String, progress: Int)
  1539. func onProcess(message: String, status: String)
  1540. }
  1541. public protocol MessageDelegate: NSObjectProtocol {
  1542. func onReceive(message: TMessage)
  1543. func onReceiveComment(message: TMessage)
  1544. func onReceive(message: [AnyHashable: Any?])
  1545. func onMessage(message: TMessage)
  1546. func onUpload(name: String, progress: Double)
  1547. func onTyping(message: TMessage)
  1548. }
  1549. public protocol GroupDelegate: NSObjectProtocol {
  1550. func onGroup(code: String, f_pin: String, groupId: String)
  1551. func onTopic(code: String, f_pin: String, topicId: String)
  1552. func onMember(code: String, f_pin: String, groupId: String, member: String)
  1553. }
  1554. public protocol DownloadDelegate: NSObjectProtocol {
  1555. func onDownloadProgress(fileName: String, progress: Double)
  1556. }
  1557. public protocol CallDelegate: NSObjectProtocol {
  1558. func onIncomingCall(state: Int, message: String)
  1559. func onStatusCall(state: Int, message: String)
  1560. }
  1561. public protocol LiveStreamingDelegate: NSObjectProtocol {
  1562. func onStartLS(state: Int, message: String)
  1563. func onJoinLS(state: Int, message: String)
  1564. }
  1565. public protocol SeminarDelegate: NSObjectProtocol {
  1566. func onStartSeminar(state: Int, message: String)
  1567. func onJoinSeminar(state: Int, message: String)
  1568. }
  1569. public protocol VideoCallDelegate: NSObjectProtocol {
  1570. func onInitiateVideoCall(destination:String,state: Int, message: String)
  1571. func onAcceptVideoCall(originator:String,state: Int, message: String)
  1572. func onVideoCallReceiverTerminate(originator:String,state: Int, message: String)
  1573. }
  1574. public protocol PersonInfoDelegate: NSObjectProtocol {
  1575. func onUpdatePersonInfo(state: Int, message: String)
  1576. }
  1577. public protocol ScreenSharingDelegate: NSObjectProtocol {
  1578. func onStartScreenSharing(state:Int,message:String)
  1579. func onJoinScreenSharing(state:Int,message:String)
  1580. }
  1581. public protocol CommentDelegate: NSObjectProtocol {
  1582. func onReceiveComment(message: TMessage)
  1583. func onDeleteComment(message: TMessage)
  1584. }
  1585. public protocol UploadDelegate: NSObjectProtocol {
  1586. func onUploadProgress(fileName: String, progress: Double)
  1587. }
  1588. public protocol TimelineDelegate: NSObjectProtocol {
  1589. func onPostUpdate(status: String, message: String)
  1590. }
  1591. public protocol ConnectionDelegate: NSObjectProtocol {
  1592. func connectionStateChanged(userId: String!, deviceId: String, state: Bool)
  1593. }
  1594. public protocol ConnectDelegate: NSObjectProtocol {
  1595. func onSuccess(userId: String)
  1596. func onFailed(error: String)
  1597. }
  1598. public enum AppStoryBoard: String {
  1599. case Palio = "Palio"
  1600. public var instance: UIStoryboard {
  1601. return UIStoryboard(name: self.rawValue, bundle: Bundle.resourceBundle(for: Nexilis.self))
  1602. }
  1603. }
  1604. public var uuidOngoing = UUID()
  1605. extension Nexilis: CallDelegate {
  1606. func displayIncomingCall(uuid: UUID, handle: String, hasVideo: Bool = false, completion: ((Error?) -> Void)? = nil) {
  1607. providerDelegate?.reportIncomingCall(uuid: uuid, handle: handle, hasVideo: hasVideo, completion: completion)
  1608. }
  1609. public func onIncomingCall(state: Int, message: String) {
  1610. DispatchQueue.main.async {
  1611. let idMe = UserDefaults.standard.string(forKey: "me")!
  1612. let myData = User.getData(pin: idMe)
  1613. let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
  1614. if !onGoingCC.isEmpty {
  1615. return
  1616. }
  1617. let deviceId = message.split(separator: ",")[0]
  1618. if myData?.offline_mode == "1" || self.stateUnfriend == deviceId {
  1619. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
  1620. API.terminateCall(sParty: nil)
  1621. })
  1622. return
  1623. }
  1624. var isShowAlert: Double?
  1625. let canShow = UIApplication.shared.visibleViewController
  1626. if canShow != nil && !(canShow is UINavigationController) {
  1627. if !(canShow is EditorPersonal) {
  1628. isShowAlert = 0
  1629. } else {
  1630. isShowAlert = 1.5
  1631. }
  1632. } else if canShow != nil {
  1633. if canShow is UINavigationController {
  1634. let canShowNC = canShow as! UINavigationController
  1635. if !(canShowNC.visibleViewController is EditorPersonal) {
  1636. isShowAlert = 0
  1637. } else {
  1638. isShowAlert = 1.5
  1639. }
  1640. } else {
  1641. isShowAlert = 0
  1642. }
  1643. }
  1644. if (state == Nexilis.AUDIO_CALL_INCOMING && message.split(separator: ",")[1] != "joining Ac.room on channel 0") {
  1645. let data = User.getDataCanNil(pin: String(deviceId))
  1646. if data == nil {
  1647. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
  1648. API.terminateCall(sParty: nil)
  1649. })
  1650. return
  1651. }
  1652. // let backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
  1653. // uuidOngoing = UUID()
  1654. // self.displayIncomingCall(uuid: uuidOngoing, handle: String(deviceId), hasVideo: false) { error in
  1655. // UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
  1656. // }
  1657. let controller = QmeraAudioViewController()
  1658. controller.user = User.getData(pin: String(deviceId))
  1659. controller.isOutgoing = false
  1660. controller.modalPresentationStyle = .overCurrentContext
  1661. if UIApplication.shared.visibleViewController is UIAlertController {
  1662. let vc = UIApplication.shared.visibleViewController as! UIAlertController
  1663. vc.dismiss(animated: true, completion: {
  1664. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1665. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  1666. } else {
  1667. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  1668. }
  1669. })
  1670. return
  1671. }
  1672. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1673. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  1674. } else {
  1675. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  1676. }
  1677. // API.receiveCCall(sParty: String(deviceId))
  1678. } else if state == Nexilis.VIDEO_CALL_INCOMING {
  1679. let dataUser = User.getDataCanNil(pin: String(deviceId))
  1680. if dataUser == nil {
  1681. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
  1682. API.terminateCall(sParty: nil)
  1683. })
  1684. return
  1685. }
  1686. let videoController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
  1687. videoController.fPin = String(deviceId)
  1688. videoController.isInisiator = false
  1689. let navigationController = UINavigationController(rootViewController: videoController)
  1690. navigationController.modalPresentationStyle = .fullScreen
  1691. if UIApplication.shared.visibleViewController is UIAlertController {
  1692. let vc = UIApplication.shared.visibleViewController as! UIAlertController
  1693. vc.dismiss(animated: true, completion: {
  1694. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1695. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  1696. } else {
  1697. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  1698. }
  1699. })
  1700. return
  1701. }
  1702. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1703. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  1704. } else {
  1705. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  1706. }
  1707. }
  1708. }
  1709. }
  1710. public func onStatusCall(state: Int, message: String) {
  1711. // let r = message.split(separator: ",")
  1712. // if state == Nexilis.AUDIO_CALL_RINGING {
  1713. // if let call = callManager.call(with: String(r[0])) {
  1714. // //print("onStatusCall:connectingCall")
  1715. // DispatchQueue.main.async {
  1716. // call.connectingCall()
  1717. // }
  1718. // }
  1719. // } else if state == Nexilis.AUDIO_CALL_OFFHOOK {
  1720. //// if let call = callManager.call(with: String(r[1])) {
  1721. // //print("onStatusCall:answerCall")
  1722. //// DispatchQueue.main.async {
  1723. //// call.answerCall()
  1724. //// }
  1725. //// }
  1726. // } else if state == Nexilis.AUDIO_CALL_END {
  1727. // DispatchQueue.main.async {
  1728. // if QmeraAudioViewController().viewIfLoaded?.window == nil {
  1729. // Nexilis.shared.callManager.end(call: Call(uuid: uuidOngoing))
  1730. // }
  1731. // }
  1732. // }
  1733. var dataCall: [AnyHashable : Any] = [:]
  1734. dataCall["state"] = state
  1735. dataCall["message"] = message
  1736. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerStatusCall), object: nil, userInfo: dataCall)
  1737. }
  1738. }
  1739. var previewItem : NSURL?
  1740. var listCCIdInv: [String] = []
  1741. extension Nexilis: MessageDelegate {
  1742. public func onReceiveComment(message: TMessage) {
  1743. var dataMessage: [AnyHashable : Any] = [:]
  1744. dataMessage["message"] = message
  1745. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onReceiveComment"), object: nil, userInfo: dataMessage)
  1746. }
  1747. @objc func tapLinkBroadcast(_ sender: ObjectGesture) {
  1748. var stringURl = sender.message_id.lowercased()
  1749. if stringURl.starts(with: "www.") {
  1750. stringURl = "https://" + stringURl.replacingOccurrences(of: "www.", with: "")
  1751. }
  1752. guard let url = URL(string: stringURl) else { return }
  1753. UIApplication.shared.open(url)
  1754. }
  1755. func showBroadcastMessage(m: [String: String]) {
  1756. let fileType = m[CoreMessage_TMessageKey.CATEGORY_FLAG]!
  1757. let broadcastVC = UIViewController()
  1758. if let viewBroadcast = broadcastVC.view {
  1759. broadcastVC.modalPresentationStyle = .custom
  1760. viewBroadcast.backgroundColor = .black.withAlphaComponent(0.3)
  1761. let stringLink = m[CoreMessage_TMessageKey.LINK] ?? ""
  1762. let containerView = UIView()
  1763. viewBroadcast.addSubview(containerView)
  1764. if stringLink.isEmpty {
  1765. containerView.anchor(centerX: viewBroadcast.centerXAnchor, centerY: viewBroadcast.centerYAnchor, width: viewBroadcast.bounds.width - 40, minHeight: 100, maxHeight: viewBroadcast.bounds.height - 100)
  1766. } else {
  1767. containerView.anchor(centerX: viewBroadcast.centerXAnchor, centerY: viewBroadcast.centerYAnchor, width: viewBroadcast.bounds.width - 40, minHeight: 200, maxHeight: viewBroadcast.bounds.height - 100)
  1768. }
  1769. containerView.backgroundColor = .white.withAlphaComponent(0.9)
  1770. containerView.layer.cornerRadius = 15.0
  1771. containerView.clipsToBounds = true
  1772. let subContainerView = UIView()
  1773. subContainerView.backgroundColor = .clear
  1774. containerView.addSubview(subContainerView)
  1775. subContainerView.anchor(top: containerView.topAnchor, left: containerView.leftAnchor, bottom: containerView.bottomAnchor, right: containerView.rightAnchor, paddingTop: 20.0, paddingLeft: 10.0, paddingBottom: 20.0, paddingRight: 10.0)
  1776. let buttonClose = UIButton(type: .close)
  1777. buttonClose.frame.size = CGSize(width: 30, height: 30)
  1778. buttonClose.layer.cornerRadius = 15.0
  1779. buttonClose.clipsToBounds = true
  1780. buttonClose.backgroundColor = .secondaryColor.withAlphaComponent(0.5)
  1781. buttonClose.actionHandle(controlEvents: .touchUpInside,
  1782. ForAction:{() -> Void in
  1783. broadcastVC.dismiss(animated: true, completion: {
  1784. Nexilis.broadcastList.remove(at: 0)
  1785. if Nexilis.broadcastList.count > 0 {
  1786. Nexilis.shared.showBroadcastMessage(m: Nexilis.broadcastList[0])
  1787. }
  1788. })
  1789. })
  1790. containerView.addSubview(buttonClose)
  1791. buttonClose.anchor(top: containerView.topAnchor, right: containerView.rightAnchor, width: 30, height: 30)
  1792. let title = UILabel()
  1793. title.font = .systemFont(ofSize: 18, weight: .bold)
  1794. title.text = m["MERNAM"]
  1795. title.textAlignment = .center
  1796. subContainerView.addSubview(title)
  1797. title.anchor(top: subContainerView.topAnchor, left: subContainerView.leftAnchor, right: subContainerView.rightAnchor)
  1798. let titleBroadcast = UILabel()
  1799. subContainerView.addSubview(titleBroadcast)
  1800. titleBroadcast.translatesAutoresizingMaskIntoConstraints = false
  1801. NSLayoutConstraint.activate([
  1802. titleBroadcast.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 20.0),
  1803. titleBroadcast.leadingAnchor.constraint(equalTo: subContainerView.leadingAnchor),
  1804. titleBroadcast.trailingAnchor.constraint(equalTo: subContainerView.trailingAnchor),
  1805. ])
  1806. titleBroadcast.font = UIFont.systemFont(ofSize: 14, weight: .semibold)
  1807. titleBroadcast.numberOfLines = 0
  1808. titleBroadcast.attributedText = m[CoreMessage_TMessageKey.TITLE]!.richText()
  1809. titleBroadcast.textColor = .black
  1810. let descBroadcast = UILabel()
  1811. subContainerView.addSubview(descBroadcast)
  1812. descBroadcast.translatesAutoresizingMaskIntoConstraints = false
  1813. let constraintDesc = descBroadcast.bottomAnchor.constraint(equalTo: subContainerView.bottomAnchor)
  1814. if !stringLink.isEmpty{
  1815. constraintDesc.constant = constraintDesc.constant - 30
  1816. }
  1817. if fileType != BroadcastViewController.FILE_TYPE_CHAT {
  1818. constraintDesc.constant = constraintDesc.constant - 260
  1819. }
  1820. NSLayoutConstraint.activate([
  1821. descBroadcast.topAnchor.constraint(equalTo: titleBroadcast.bottomAnchor, constant: 10),
  1822. descBroadcast.leadingAnchor.constraint(equalTo: subContainerView.leadingAnchor),
  1823. descBroadcast.trailingAnchor.constraint(equalTo: subContainerView.trailingAnchor),
  1824. constraintDesc,
  1825. ])
  1826. descBroadcast.font = UIFont.systemFont(ofSize: 12)
  1827. descBroadcast.numberOfLines = 0
  1828. descBroadcast.attributedText = m[CoreMessage_TMessageKey.MESSAGE_TEXT_ENG]!.richText()
  1829. descBroadcast.textColor = .black
  1830. let linkBroadcast = UILabel()
  1831. if !stringLink.isEmpty {
  1832. subContainerView.addSubview(linkBroadcast)
  1833. linkBroadcast.translatesAutoresizingMaskIntoConstraints = false
  1834. NSLayoutConstraint.activate([
  1835. linkBroadcast.topAnchor.constraint(equalTo: descBroadcast.bottomAnchor, constant: 10),
  1836. linkBroadcast.leadingAnchor.constraint(equalTo: subContainerView.leadingAnchor),
  1837. linkBroadcast.trailingAnchor.constraint(equalTo: subContainerView.trailingAnchor),
  1838. ])
  1839. linkBroadcast.font = UIFont.systemFont(ofSize: 12)
  1840. linkBroadcast.isUserInteractionEnabled = true
  1841. linkBroadcast.numberOfLines = 2
  1842. let attributedString = NSMutableAttributedString(string: stringLink, attributes:[NSAttributedString.Key.link: URL(string: stringLink)!])
  1843. linkBroadcast.attributedText = attributedString
  1844. let tap = ObjectGesture(target: self, action: #selector(tapLinkBroadcast))
  1845. tap.message_id = stringLink
  1846. linkBroadcast.addGestureRecognizer(tap)
  1847. }
  1848. let thumb = m[CoreMessage_TMessageKey.THUMB_ID] ?? ""
  1849. let image = m[CoreMessage_TMessageKey.IMAGE_ID] ?? ""
  1850. let video = m[CoreMessage_TMessageKey.VIDEO_ID] ?? ""
  1851. let file = m[CoreMessage_TMessageKey.FILE_ID] ?? ""
  1852. if fileType != BroadcastViewController.FILE_TYPE_CHAT {
  1853. let imageBroadcast = UIImageView()
  1854. subContainerView.addSubview(imageBroadcast)
  1855. imageBroadcast.translatesAutoresizingMaskIntoConstraints = false
  1856. var constImage = imageBroadcast.topAnchor.constraint(equalTo: descBroadcast.bottomAnchor, constant: 10)
  1857. if !stringLink.isEmpty {
  1858. constImage = imageBroadcast.topAnchor.constraint(equalTo: linkBroadcast.bottomAnchor, constant: 10)
  1859. }
  1860. NSLayoutConstraint.activate([
  1861. constImage,
  1862. imageBroadcast.leadingAnchor.constraint(equalTo: subContainerView.leadingAnchor),
  1863. imageBroadcast.trailingAnchor.constraint(equalTo: subContainerView.trailingAnchor),
  1864. imageBroadcast.heightAnchor.constraint(equalToConstant: 250)
  1865. ])
  1866. imageBroadcast.layer.cornerRadius = 10.0
  1867. imageBroadcast.clipsToBounds = true
  1868. if fileType != BroadcastViewController.FILE_TYPE_DOCUMENT {
  1869. imageBroadcast.contentMode = .scaleAspectFill
  1870. imageBroadcast.setImage(name: thumb)
  1871. if fileType == BroadcastViewController.FILE_TYPE_VIDEO {
  1872. let imagePlay = UIImageView(image: UIImage(systemName: "play.circle.fill"))
  1873. imageBroadcast.addSubview(imagePlay)
  1874. imagePlay.clipsToBounds = true
  1875. imagePlay.translatesAutoresizingMaskIntoConstraints = false
  1876. imagePlay.centerYAnchor.constraint(equalTo: imageBroadcast.centerYAnchor).isActive = true
  1877. imagePlay.centerXAnchor.constraint(equalTo: imageBroadcast.centerXAnchor).isActive = true
  1878. imagePlay.widthAnchor.constraint(equalToConstant: 60).isActive = true
  1879. imagePlay.heightAnchor.constraint(equalToConstant: 60).isActive = true
  1880. imagePlay.tintColor = .gray.withAlphaComponent(0.5)
  1881. }
  1882. } else {
  1883. imageBroadcast.image = UIImage(systemName: "doc.fill")
  1884. imageBroadcast.tintColor = .mainColor
  1885. imageBroadcast.contentMode = .scaleAspectFit
  1886. }
  1887. imageBroadcast.actionHandle(controlEvents: .touchUpInside,
  1888. ForAction:{() -> Void in
  1889. let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
  1890. let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
  1891. let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
  1892. if fileType == BroadcastViewController.FILE_TYPE_IMAGE {
  1893. if let dirPath = paths.first {
  1894. let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(image)
  1895. if FileManager.default.fileExists(atPath: imageURL.path) {
  1896. let image = UIImage(contentsOfFile: imageURL.path)
  1897. let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
  1898. previewImageVC.image = image
  1899. previewImageVC.isHiddenTextField = true
  1900. previewImageVC.modalPresentationStyle = .overFullScreen
  1901. previewImageVC.modalTransitionStyle = .crossDissolve
  1902. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1903. UIApplication.shared.visibleViewController?.navigationController?.present(previewImageVC, animated: true, completion: nil)
  1904. } else {
  1905. UIApplication.shared.visibleViewController?.present(previewImageVC, animated: true, completion: nil)
  1906. }
  1907. } else {
  1908. Download().startHTTP(forKey: image) { (name, progress) in
  1909. guard progress == 100 else {
  1910. return
  1911. }
  1912. DispatchQueue.main.async {
  1913. let image = UIImage(contentsOfFile: imageURL.path)
  1914. let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
  1915. previewImageVC.image = image
  1916. previewImageVC.isHiddenTextField = true
  1917. previewImageVC.modalPresentationStyle = .overFullScreen
  1918. previewImageVC.modalTransitionStyle = .crossDissolve
  1919. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1920. UIApplication.shared.visibleViewController?.navigationController?.present(previewImageVC, animated: true, completion: nil)
  1921. } else {
  1922. UIApplication.shared.visibleViewController?.present(previewImageVC, animated: true, completion: nil)
  1923. }
  1924. }
  1925. }
  1926. }
  1927. }
  1928. } else if fileType == BroadcastViewController.FILE_TYPE_VIDEO {
  1929. //https://qmera.io/filepalio/image/
  1930. let player = AVPlayer(url: URL(string: "https://newuniverse.io/get_file?account=\(Nexilis.sAPIKey)&image=\(video)")!)
  1931. let playerVC = AVPlayerViewController()
  1932. playerVC.player = player
  1933. playerVC.modalPresentationStyle = .custom
  1934. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1935. UIApplication.shared.visibleViewController?.navigationController?.present(playerVC, animated: true, completion: nil)
  1936. } else {
  1937. UIApplication.shared.visibleViewController?.present(playerVC, animated: true, completion: nil)
  1938. }
  1939. } else if fileType == BroadcastViewController.FILE_TYPE_DOCUMENT {
  1940. if let dirPath = paths.first {
  1941. let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(file)
  1942. if FileManager.default.fileExists(atPath: fileURL.path) {
  1943. previewItem = fileURL as NSURL
  1944. let previewController = QLPreviewController()
  1945. let rightBarButton = UIBarButtonItem()
  1946. previewController.navigationItem.rightBarButtonItem = rightBarButton
  1947. previewController.dataSource = self
  1948. previewController.modalPresentationStyle = .overFullScreen
  1949. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1950. UIApplication.shared.visibleViewController?.navigationController?.present(previewController, animated: true, completion: nil)
  1951. } else {
  1952. UIApplication.shared.visibleViewController?.present(previewController, animated: true, completion: nil)
  1953. }
  1954. } else {
  1955. Download().startHTTP(forKey: file) { (name, progress) in
  1956. DispatchQueue.main.async {
  1957. guard progress == 100 else {
  1958. return
  1959. }
  1960. previewItem = fileURL as NSURL
  1961. let previewController = QLPreviewController()
  1962. let rightBarButton = UIBarButtonItem()
  1963. previewController.navigationItem.rightBarButtonItem = rightBarButton
  1964. previewController.dataSource = self
  1965. previewController.modalPresentationStyle = .overFullScreen
  1966. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1967. UIApplication.shared.visibleViewController?.navigationController?.present(previewController, animated: true, completion: nil)
  1968. } else {
  1969. UIApplication.shared.visibleViewController?.present(previewController, animated: true, completion: nil)
  1970. }
  1971. }
  1972. }
  1973. }
  1974. }
  1975. }
  1976. })
  1977. }
  1978. broadcastVC.modalTransitionStyle = .crossDissolve
  1979. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1980. UIApplication.shared.visibleViewController?.navigationController?.present(broadcastVC, animated: true, completion: nil)
  1981. } else {
  1982. UIApplication.shared.visibleViewController?.present(broadcastVC, animated: true, completion: nil)
  1983. }
  1984. }
  1985. }
  1986. public func onReceive(message: TMessage) {
  1987. var dataMessage: [AnyHashable : Any] = [:]
  1988. dataMessage["message"] = message
  1989. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerReceiveChat), object: nil, userInfo: dataMessage)
  1990. if message.getCode() == CoreMessage_TMessageCode.PUSH_CALL_CENTER {
  1991. if User.getDataCanNil(pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)) == nil {
  1992. Nexilis.addFriendSilent(fpin: message.getBody(key: CoreMessage_TMessageKey.L_PIN))
  1993. sleep(1)
  1994. }
  1995. DispatchQueue.main.async {
  1996. if Nexilis.onGoingPushCC.isEmpty {
  1997. var data: [String: String] = [:]
  1998. data["channel"] = message.getBody(key: CoreMessage_TMessageKey.CHANNEL)
  1999. data["l_pin"] = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2000. data["f_display_name"] = message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME)
  2001. Nexilis.onGoingPushCC = data
  2002. } else if Nexilis.onGoingPushCC["f_display_name"] == message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME) {
  2003. return
  2004. }
  2005. let alert = LibAlertController(title: "", message: "\n\n\n\n\n\n\n\n\n\n".localized(), preferredStyle: .alert)
  2006. let newWidth = UIScreen.main.bounds.width * 0.90 - 270
  2007. // update width constraint value for main view
  2008. if let viewWidthConstraint = alert.view.constraints.filter({ return $0.firstAttribute == .width }).first{
  2009. viewWidthConstraint.constant = newWidth
  2010. }
  2011. // update width constraint value for container view
  2012. if let containerViewWidthConstraint = alert.view.subviews.first?.constraints.filter({ return $0.firstAttribute == .width }).first {
  2013. containerViewWidthConstraint.constant = newWidth
  2014. }
  2015. let titleFont = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18), NSAttributedString.Key.foregroundColor: UIColor.black]
  2016. let titleAttrString = NSMutableAttributedString(string: "Call Center".localized(), attributes: titleFont)
  2017. alert.setValue(titleAttrString, forKey: "attributedTitle")
  2018. alert.view.subviews.first?.subviews.first?.subviews.first?.backgroundColor = .lightGray
  2019. alert.view.tintColor = .black
  2020. let rejectAction = UIAlertAction(title: "Pass to other representative".localized(), style: .destructive, handler: {(_) in
  2021. DispatchQueue.global().async {
  2022. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2023. }
  2024. Nexilis.onGoingPushCC.removeAll()
  2025. alert.dismiss(animated: true, completion: nil)
  2026. })
  2027. let acceptAction = UIAlertAction(title: "I'll handle the customer".localized(), style: .default, handler: {(_) in
  2028. let goAudioCall = Nexilis.checkMicPermission()
  2029. if !goAudioCall && message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  2030. let alert = LibAlertController(title: "Attention!".localized(), message: "Please allow microphone permission in your settings".localized(), preferredStyle: .alert)
  2031. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2032. if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
  2033. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  2034. }
  2035. }))
  2036. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2037. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  2038. } else {
  2039. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  2040. }
  2041. DispatchQueue.global().async {
  2042. DispatchQueue.global().async {
  2043. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2044. }
  2045. }
  2046. Nexilis.onGoingPushCC.removeAll()
  2047. return
  2048. }
  2049. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  2050. var permissionCheck = -1
  2051. if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
  2052. permissionCheck = 1
  2053. } else if AVCaptureDevice.authorizationStatus(for: .video) == .denied {
  2054. permissionCheck = 0
  2055. } else {
  2056. AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) -> Void in
  2057. if granted == true {
  2058. permissionCheck = 1
  2059. } else {
  2060. permissionCheck = 0
  2061. }
  2062. })
  2063. }
  2064. while permissionCheck == -1 {
  2065. sleep(1)
  2066. }
  2067. if permissionCheck == 0 {
  2068. let alert = LibAlertController(title: "Attention!".localized(), message: "Please allow camera permission in your settings".localized(), preferredStyle: .alert)
  2069. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2070. if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
  2071. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  2072. }
  2073. }))
  2074. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2075. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  2076. } else {
  2077. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  2078. }
  2079. DispatchQueue.global().async {
  2080. DispatchQueue.global().async {
  2081. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2082. }
  2083. }
  2084. Nexilis.onGoingPushCC.removeAll()
  2085. return
  2086. }
  2087. }
  2088. if UIApplication.shared.visibleViewController is UINavigationController {
  2089. let nc = UIApplication.shared.visibleViewController as! UINavigationController
  2090. if nc.visibleViewController is QmeraStreamingViewController {
  2091. let vc = nc.visibleViewController as! QmeraStreamingViewController
  2092. var alert = LibAlertController(title: "", message: "Are you sure you want to end Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  2093. if !vc.isLive {
  2094. alert = LibAlertController(title: "", message: "Are you sure you want to leave Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  2095. }
  2096. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2097. DispatchQueue.global().async {
  2098. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2099. }
  2100. Nexilis.onGoingPushCC.removeAll()
  2101. alert.dismiss(animated: true, completion: nil)
  2102. }))
  2103. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2104. DispatchQueue.global().async {
  2105. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  2106. vc.sendLeft()
  2107. }
  2108. vc.dismiss(animated: true, completion: {
  2109. acceptCC()
  2110. })
  2111. }))
  2112. nc.present(alert, animated: true, completion: nil)
  2113. // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "isRunningStreaming"), object: nil, userInfo: dataMessage)
  2114. } else if nc.visibleViewController is SeminarViewController {
  2115. let vc = nc.visibleViewController as! SeminarViewController
  2116. var alert = LibAlertController(title: "", message: "Are you sure you want to end Seminar, and open notification?".localized(), preferredStyle: .alert)
  2117. if !vc.isLive {
  2118. alert = LibAlertController(title: "", message: "Are you sure you want to leave Seminar, and open notification?".localized(), preferredStyle: .alert)
  2119. }
  2120. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2121. DispatchQueue.global().async {
  2122. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2123. }
  2124. Nexilis.onGoingPushCC.removeAll()
  2125. alert.dismiss(animated: true, completion: nil)
  2126. }))
  2127. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2128. DispatchQueue.global().async {
  2129. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  2130. vc.sendLeft()
  2131. }
  2132. vc.dismiss(animated: true, completion: {
  2133. acceptCC()
  2134. })
  2135. }))
  2136. nc.present(alert, animated: true, completion: nil)
  2137. // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "isRunningStreaming"), object: nil, userInfo: dataMessage)
  2138. } else {
  2139. acceptCC()
  2140. }
  2141. } else {
  2142. acceptCC()
  2143. }
  2144. func acceptCC() {
  2145. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.acceptRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN), complaint_id: message.getBody(key: CoreMessage_TMessageKey.DATA))) {
  2146. if (response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "00") {
  2147. Nexilis.onGoingPushCC.removeAll()
  2148. let complaintId = response.getBody(key: CoreMessage_TMessageKey.DATA, default_value: "")
  2149. if !complaintId.isEmpty {
  2150. alert.dismiss(animated: true, completion: nil)
  2151. let idMe = UserDefaults.standard.string(forKey: "me")!
  2152. UserDefaults.standard.set("\(message.getBody(key: CoreMessage_TMessageKey.L_PIN)),\(idMe),\(complaintId)", forKey: "onGoingCC")
  2153. UserDefaults.standard.set("\(message.getBody(key: CoreMessage_TMessageKey.L_PIN))", forKey: "membersCC")
  2154. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "0" {
  2155. let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  2156. editorPersonalVC.isContactCenter = true
  2157. editorPersonalVC.isRequestContactCenter = false
  2158. editorPersonalVC.unique_l_pin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2159. editorPersonalVC.complaintId = complaintId
  2160. editorPersonalVC.channelContactCenter = message.getBody(key: CoreMessage_TMessageKey.CHANNEL)
  2161. editorPersonalVC.fPinContacCenter = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2162. let navigationController = UINavigationController(rootViewController: editorPersonalVC)
  2163. navigationController.modalPresentationStyle = .fullScreen
  2164. navigationController.navigationBar.tintColor = .white
  2165. navigationController.navigationBar.barTintColor = .mainColor
  2166. navigationController.navigationBar.isTranslucent = false
  2167. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  2168. navigationController.navigationBar.barStyle = .black
  2169. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  2170. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  2171. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  2172. navigationController.navigationBar.titleTextAttributes = textAttributes
  2173. navigationController.view.backgroundColor = .mainColor
  2174. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2175. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2176. } else {
  2177. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2178. }
  2179. } else {
  2180. UserDefaults.standard.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
  2181. DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
  2182. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  2183. let pin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2184. let controller = QmeraAudioViewController()
  2185. controller.user = User.getData(pin: pin)
  2186. controller.isOutgoing = true
  2187. controller.ticketId = complaintId
  2188. controller.modalPresentationStyle = .overCurrentContext
  2189. let navigationController = UINavigationController(rootViewController: controller)
  2190. navigationController.modalPresentationStyle = .fullScreen
  2191. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2192. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2193. } else {
  2194. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2195. }
  2196. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  2197. let videoVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
  2198. videoVC.fPin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2199. videoVC.users.append(User.getData(pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN))!)
  2200. videoVC.ticketId = complaintId
  2201. let navigationController = UINavigationController(rootViewController: videoVC)
  2202. navigationController.modalPresentationStyle = .fullScreen
  2203. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2204. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2205. } else {
  2206. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2207. }
  2208. }
  2209. })
  2210. }
  2211. }
  2212. }
  2213. }
  2214. }
  2215. })
  2216. alert.addAction(acceptAction)
  2217. alert.addAction(rejectAction)
  2218. let containerView = UIView(frame: CGRect(x: 20, y: 60, width: alert.view.bounds.size.width * 0.9 - 40, height: 150))
  2219. alert.view.addSubview(containerView)
  2220. containerView.layer.cornerRadius = 10.0
  2221. containerView.clipsToBounds = true
  2222. containerView.backgroundColor = .secondaryColor.withAlphaComponent(0.5)
  2223. let imageProfile = UIImageView()
  2224. containerView.addSubview(imageProfile)
  2225. imageProfile.translatesAutoresizingMaskIntoConstraints = false
  2226. NSLayoutConstraint.activate([
  2227. imageProfile.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 10),
  2228. imageProfile.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -10),
  2229. imageProfile.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 10),
  2230. imageProfile.widthAnchor.constraint(equalToConstant: 100)
  2231. ])
  2232. imageProfile.layer.cornerRadius = 10.0
  2233. imageProfile.clipsToBounds = true
  2234. imageProfile.backgroundColor = .lightGray.withAlphaComponent(0.3)
  2235. imageProfile.tintColor = .secondaryColor
  2236. imageProfile.image = UIImage(systemName: "person")
  2237. if message.getBody(key: CoreMessage_TMessageKey.THUMB_ID) != "" {
  2238. imageProfile.setImage(name: message.getBody(key: CoreMessage_TMessageKey.THUMB_ID))
  2239. imageProfile.contentMode = .scaleAspectFill
  2240. }
  2241. let labelName = UILabel()
  2242. containerView.addSubview(labelName)
  2243. labelName.translatesAutoresizingMaskIntoConstraints = false
  2244. NSLayoutConstraint.activate([
  2245. labelName.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 15),
  2246. labelName.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2247. ])
  2248. labelName.font = UIFont.systemFont(ofSize: 12)
  2249. labelName.text = "Name".localized()
  2250. labelName.textColor = .mainColor
  2251. let valueName = UILabel()
  2252. containerView.addSubview(valueName)
  2253. valueName.translatesAutoresizingMaskIntoConstraints = false
  2254. NSLayoutConstraint.activate([
  2255. valueName.topAnchor.constraint(equalTo: labelName.bottomAnchor),
  2256. valueName.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2257. ])
  2258. valueName.font = UIFont.systemFont(ofSize: 12)
  2259. valueName.text = message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME)
  2260. valueName.textColor = .mainColor
  2261. let labelType = UILabel()
  2262. containerView.addSubview(labelType)
  2263. labelType.translatesAutoresizingMaskIntoConstraints = false
  2264. NSLayoutConstraint.activate([
  2265. labelType.topAnchor.constraint(equalTo: valueName.bottomAnchor, constant: 5),
  2266. labelType.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2267. ])
  2268. labelType.font = UIFont.systemFont(ofSize: 12)
  2269. labelType.text = "Request Type".localized()
  2270. labelType.textColor = .mainColor
  2271. let valueType = UILabel()
  2272. containerView.addSubview(valueType)
  2273. valueType.translatesAutoresizingMaskIntoConstraints = false
  2274. NSLayoutConstraint.activate([
  2275. valueType.topAnchor.constraint(equalTo: labelType.bottomAnchor),
  2276. valueType.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2277. ])
  2278. valueType.font = UIFont.systemFont(ofSize: 12)
  2279. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "0" {
  2280. valueType.text = "Chat".localized()
  2281. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  2282. valueType.text = "Audio Call".localized()
  2283. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  2284. valueType.text = "Video Call".localized()
  2285. } else {
  2286. valueType.text = "Email".localized()
  2287. }
  2288. valueType.textColor = .mainColor
  2289. let labelIdentity = UILabel()
  2290. containerView.addSubview(labelIdentity)
  2291. labelIdentity.translatesAutoresizingMaskIntoConstraints = false
  2292. NSLayoutConstraint.activate([
  2293. labelIdentity.topAnchor.constraint(equalTo: valueType.bottomAnchor, constant: 5),
  2294. labelIdentity.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2295. ])
  2296. labelIdentity.font = UIFont.systemFont(ofSize: 12)
  2297. labelIdentity.text = "Complaint ID".localized()
  2298. labelIdentity.textColor = .mainColor
  2299. let valueIdentity = UILabel()
  2300. containerView.addSubview(valueIdentity)
  2301. valueIdentity.translatesAutoresizingMaskIntoConstraints = false
  2302. NSLayoutConstraint.activate([
  2303. valueIdentity.topAnchor.constraint(equalTo: labelIdentity.bottomAnchor),
  2304. valueIdentity.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5),
  2305. valueIdentity.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
  2306. ])
  2307. valueIdentity.font = UIFont.systemFont(ofSize: 12)
  2308. valueIdentity.text = message.getBody(key: CoreMessage_TMessageKey.DATA)
  2309. valueIdentity.numberOfLines = 0
  2310. valueIdentity.textColor = .mainColor
  2311. var isShowAlert: Int?
  2312. let canShow = UIApplication.shared.visibleViewController
  2313. if canShow != nil && !(canShow is UINavigationController) {
  2314. if !(canShow is EditorPersonal) && !(canShow is QmeraAudioViewController) && !(canShow is QmeraVideoViewController) {
  2315. isShowAlert = 0
  2316. } else {
  2317. isShowAlert = 3
  2318. }
  2319. } else if canShow != nil {
  2320. if canShow is UINavigationController {
  2321. let canShowNC = canShow as! UINavigationController
  2322. if !(canShowNC.visibleViewController is EditorPersonal) && !(canShowNC.visibleViewController is QmeraAudioViewController) && !(canShowNC.visibleViewController is QmeraVideoViewController) {
  2323. isShowAlert = 0
  2324. } else {
  2325. isShowAlert = 3
  2326. }
  2327. } else {
  2328. isShowAlert = 0
  2329. }
  2330. }
  2331. DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(isShowAlert!), execute: {
  2332. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2333. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  2334. } else {
  2335. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  2336. }
  2337. })
  2338. }
  2339. } else if message.getCode() == CoreMessage_TMessageCode.ACCEPT_CALL_CENTER {
  2340. let fPinContacCenter = message.getBody(key: CoreMessage_TMessageKey.F_PIN)
  2341. let requester = message.getBody(key: CoreMessage_TMessageKey.UPLINE_PIN)
  2342. let complaintId = message.getBody(key: CoreMessage_TMessageKey.DATA)
  2343. if !requester.isEmpty {
  2344. UserDefaults.standard.set("\(requester),\(fPinContacCenter),\(complaintId)", forKey: "onGoingCC")
  2345. UserDefaults.standard.set("\(fPinContacCenter)", forKey: "membersCC")
  2346. }
  2347. } else if message.getCode() == CoreMessage_TMessageCode.INVITE_TO_ROOM_CONTACT_CENTER {
  2348. if listCCIdInv.contains(message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)) {
  2349. return
  2350. }
  2351. listCCIdInv.append(message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))
  2352. DispatchQueue.main.async {
  2353. let alert = LibAlertController(title: "", message: "\n\n\n\n\n\n\n\n\n\n".localized(), preferredStyle: .alert)
  2354. let newWidth = UIScreen.main.bounds.width * 0.90 - 270
  2355. // update width constraint value for main view
  2356. if let viewWidthConstraint = alert.view.constraints.filter({ return $0.firstAttribute == .width }).first{
  2357. viewWidthConstraint.constant = newWidth
  2358. }
  2359. // update width constraint value for container view
  2360. if let containerViewWidthConstraint = alert.view.subviews.first?.constraints.filter({ return $0.firstAttribute == .width }).first {
  2361. containerViewWidthConstraint.constant = newWidth
  2362. }
  2363. let titleFont = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18), NSAttributedString.Key.foregroundColor: UIColor.black]
  2364. let titleAttrString = NSMutableAttributedString(string: "You're invited to\nCall Center".localized(), attributes: titleFont)
  2365. alert.setValue(titleAttrString, forKey: "attributedTitle")
  2366. alert.view.subviews.first?.subviews.first?.subviews.first?.backgroundColor = .lightGray
  2367. alert.view.tintColor = .black
  2368. let rejectAction = UIAlertAction(title: "Reject".localized(), style: .destructive, handler: {(_) in
  2369. listCCIdInv.removeAll(where: {$0 == message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)})
  2370. DispatchQueue.global().async {
  2371. if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.acceptCCRoomInvite(l_pin: message.getPIN(), type: 0, ticket_id: message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))) {
  2372. if result.isOk() {
  2373. return
  2374. }
  2375. }
  2376. }
  2377. alert.dismiss(animated: true, completion: nil)
  2378. })
  2379. let acceptAction = UIAlertAction(title: "Accept".localized(), style: .default, handler: {(_) in
  2380. listCCIdInv.removeAll(where: {$0 == message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)})
  2381. let goAudioCall = Nexilis.checkMicPermission()
  2382. if !goAudioCall && message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  2383. let alert = LibAlertController(title: "Attention!".localized(), message: "Please allow microphone permission in your settings".localized(), preferredStyle: .alert)
  2384. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2385. if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
  2386. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  2387. }
  2388. }))
  2389. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2390. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  2391. } else {
  2392. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  2393. }
  2394. DispatchQueue.global().async {
  2395. if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.acceptCCRoomInvite(l_pin: message.getPIN(), type: 0, ticket_id: message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))) {
  2396. if result.isOk() {
  2397. return
  2398. }
  2399. }
  2400. }
  2401. return
  2402. }
  2403. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  2404. var permissionCheck = -1
  2405. if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
  2406. permissionCheck = 1
  2407. } else if AVCaptureDevice.authorizationStatus(for: .video) == .denied {
  2408. permissionCheck = 0
  2409. } else {
  2410. AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) -> Void in
  2411. if granted == true {
  2412. permissionCheck = 1
  2413. } else {
  2414. permissionCheck = 0
  2415. }
  2416. })
  2417. }
  2418. while permissionCheck == -1 {
  2419. sleep(1)
  2420. }
  2421. if permissionCheck == 0 {
  2422. let alert = LibAlertController(title: "Attention!".localized(), message: "Please allow camera permission in your settings".localized(), preferredStyle: .alert)
  2423. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2424. if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
  2425. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  2426. }
  2427. }))
  2428. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2429. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  2430. } else {
  2431. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  2432. }
  2433. DispatchQueue.global().async {
  2434. if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.acceptCCRoomInvite(l_pin: message.getPIN(), type: 0, ticket_id: message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))) {
  2435. if result.isOk() {
  2436. return
  2437. }
  2438. }
  2439. }
  2440. return
  2441. }
  2442. }
  2443. if UIApplication.shared.visibleViewController is UINavigationController {
  2444. let nc = UIApplication.shared.visibleViewController as! UINavigationController
  2445. if nc.visibleViewController is QmeraStreamingViewController {
  2446. let vc = nc.visibleViewController as! QmeraStreamingViewController
  2447. var alert = LibAlertController(title: "", message: "Are you sure you want to end Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  2448. if !vc.isLive {
  2449. alert = LibAlertController(title: "", message: "Are you sure you want to leave Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  2450. }
  2451. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2452. DispatchQueue.global().async {
  2453. if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.acceptCCRoomInvite(l_pin: message.getPIN(), type: 0, ticket_id: message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))) {
  2454. if result.isOk() {
  2455. return
  2456. }
  2457. }
  2458. }
  2459. alert.dismiss(animated: true, completion: nil)
  2460. }))
  2461. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2462. DispatchQueue.global().async {
  2463. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  2464. vc.sendLeft()
  2465. }
  2466. vc.dismiss(animated: true, completion: {
  2467. acceptCC()
  2468. })
  2469. }))
  2470. nc.present(alert, animated: true, completion: nil)
  2471. } else if nc.visibleViewController is SeminarViewController {
  2472. let vc = nc.visibleViewController as! SeminarViewController
  2473. var alert = LibAlertController(title: "", message: "Are you sure you want to end Seminar, and open notification?".localized(), preferredStyle: .alert)
  2474. if !vc.isLive {
  2475. alert = LibAlertController(title: "", message: "Are you sure you want to leave Seminar, and open notification?".localized(), preferredStyle: .alert)
  2476. }
  2477. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2478. DispatchQueue.global().async {
  2479. if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.acceptCCRoomInvite(l_pin: message.getPIN(), type: 0, ticket_id: message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))) {
  2480. if result.isOk() {
  2481. return
  2482. }
  2483. }
  2484. }
  2485. alert.dismiss(animated: true, completion: nil)
  2486. }))
  2487. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2488. DispatchQueue.global().async {
  2489. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  2490. vc.sendLeft()
  2491. }
  2492. vc.dismiss(animated: true, completion: {
  2493. acceptCC()
  2494. })
  2495. }))
  2496. nc.present(alert, animated: true, completion: nil)
  2497. } else {
  2498. acceptCC()
  2499. }
  2500. } else {
  2501. acceptCC()
  2502. }
  2503. func acceptCC() {
  2504. if let result = Nexilis.writeSync(message: CoreMessage_TMessageBank.acceptCCRoomInvite(l_pin: message.getPIN(), type: 1, ticket_id: message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))) {
  2505. if result.isOk() {
  2506. let requester = result.getBody(key: CoreMessage_TMessageKey.UPLINE_PIN)
  2507. let officer = result.getBody(key: CoreMessage_TMessageKey.FRIEND_FPIN)
  2508. let data = result.getBody(key: CoreMessage_TMessageKey.DATA)
  2509. let complaintId = message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)
  2510. UserDefaults.standard.set("\(requester),\(officer),\(complaintId)", forKey: "onGoingCC")
  2511. UserDefaults.standard.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
  2512. if !data.isEmpty {
  2513. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  2514. var members = ""
  2515. var user : [User] = []
  2516. let idMe = UserDefaults.standard.string(forKey: "me")!
  2517. for json in jsonArray {
  2518. if "\(json)" != idMe {
  2519. if members.isEmpty {
  2520. members = "\(json)"
  2521. } else {
  2522. members += ",\(json)"
  2523. }
  2524. if let userData = User.getData(pin: "\(json)") {
  2525. user.append(userData)
  2526. } else {
  2527. Nexilis.addFriendSilent(fpin: "\(json)")
  2528. DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
  2529. if let userData = User.getData(pin: "\(json)") {
  2530. user.append(userData)
  2531. }
  2532. })
  2533. }
  2534. }
  2535. }
  2536. UserDefaults.standard.set("\(members)", forKey: "membersCC")
  2537. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "0" {
  2538. let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  2539. editorPersonalVC.hidesBottomBarWhenPushed = true
  2540. editorPersonalVC.unique_l_pin = officer
  2541. editorPersonalVC.fromNotification = true
  2542. editorPersonalVC.isContactCenter = true
  2543. editorPersonalVC.fPinContacCenter = members
  2544. editorPersonalVC.complaintId = complaintId
  2545. editorPersonalVC.onGoingCC = true
  2546. editorPersonalVC.isRequestContactCenter = false
  2547. editorPersonalVC.users = user
  2548. let navigationController = UINavigationController(rootViewController: editorPersonalVC)
  2549. navigationController.modalPresentationStyle = .fullScreen
  2550. navigationController.navigationBar.tintColor = .white
  2551. navigationController.navigationBar.barTintColor = .mainColor
  2552. navigationController.navigationBar.isTranslucent = false
  2553. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  2554. navigationController.navigationBar.barStyle = .black
  2555. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  2556. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  2557. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  2558. navigationController.navigationBar.titleTextAttributes = textAttributes
  2559. navigationController.view.backgroundColor = .mainColor
  2560. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2561. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2562. } else {
  2563. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2564. }
  2565. } else {
  2566. UserDefaults.standard.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
  2567. DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
  2568. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  2569. let pin = officer
  2570. let controller = QmeraAudioViewController()
  2571. controller.user = User.getData(pin: pin)
  2572. controller.isOutgoing = false
  2573. controller.ticketId = complaintId
  2574. controller.modalPresentationStyle = .overCurrentContext
  2575. let navigationController = UINavigationController(rootViewController: controller)
  2576. navigationController.modalPresentationStyle = .fullScreen
  2577. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2578. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2579. } else {
  2580. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2581. }
  2582. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  2583. let videoVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
  2584. videoVC.fPin = officer
  2585. videoVC.users.append(User.getData(pin: officer)!)
  2586. videoVC.ticketId = complaintId
  2587. videoVC.isInisiator = false
  2588. videoVC.isAutoAccept = true
  2589. let navigationController = UINavigationController(rootViewController: videoVC)
  2590. navigationController.modalPresentationStyle = .fullScreen
  2591. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2592. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2593. } else {
  2594. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2595. }
  2596. }
  2597. })
  2598. }
  2599. }
  2600. }
  2601. } else {
  2602. let imageView = UIImageView(image: UIImage(systemName: "info.circle"))
  2603. imageView.tintColor = .white
  2604. let banner = FloatingNotificationBanner(title: "Call Center Session has ended".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)
  2605. banner.show()
  2606. }
  2607. }
  2608. }
  2609. })
  2610. alert.addAction(rejectAction)
  2611. alert.addAction(acceptAction)
  2612. let containerView = UIView(frame: CGRect(x: 50, y: 80, width: alert.view.bounds.size.width * 0.9 - 100, height: 150))
  2613. alert.view.addSubview(containerView)
  2614. containerView.layer.cornerRadius = 10.0
  2615. containerView.clipsToBounds = true
  2616. containerView.backgroundColor = .secondaryColor.withAlphaComponent(0.5)
  2617. let userData = User.getData(pin: message.getPIN())
  2618. let imageProfile = UIImageView()
  2619. containerView.addSubview(imageProfile)
  2620. imageProfile.translatesAutoresizingMaskIntoConstraints = false
  2621. NSLayoutConstraint.activate([
  2622. imageProfile.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 10),
  2623. imageProfile.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -10),
  2624. imageProfile.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 10),
  2625. imageProfile.widthAnchor.constraint(equalToConstant: 100)
  2626. ])
  2627. imageProfile.layer.cornerRadius = 10.0
  2628. imageProfile.clipsToBounds = true
  2629. imageProfile.backgroundColor = .lightGray.withAlphaComponent(0.3)
  2630. imageProfile.tintColor = .secondaryColor
  2631. imageProfile.image = UIImage(systemName: "person")
  2632. if userData!.thumb != "" {
  2633. imageProfile.setImage(name: userData!.thumb)
  2634. imageProfile.contentMode = .scaleAspectFill
  2635. }
  2636. let labelName = UILabel()
  2637. containerView.addSubview(labelName)
  2638. labelName.translatesAutoresizingMaskIntoConstraints = false
  2639. NSLayoutConstraint.activate([
  2640. labelName.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 15),
  2641. labelName.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2642. ])
  2643. labelName.font = UIFont.systemFont(ofSize: 12)
  2644. labelName.text = "Name".localized()
  2645. labelName.textColor = .mainColor
  2646. let valueName = UILabel()
  2647. containerView.addSubview(valueName)
  2648. valueName.translatesAutoresizingMaskIntoConstraints = false
  2649. NSLayoutConstraint.activate([
  2650. valueName.topAnchor.constraint(equalTo: labelName.bottomAnchor),
  2651. valueName.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2652. ])
  2653. valueName.font = UIFont.systemFont(ofSize: 12)
  2654. valueName.text = userData!.fullName
  2655. valueName.textColor = .mainColor
  2656. let labelType = UILabel()
  2657. containerView.addSubview(labelType)
  2658. labelType.translatesAutoresizingMaskIntoConstraints = false
  2659. NSLayoutConstraint.activate([
  2660. labelType.topAnchor.constraint(equalTo: valueName.bottomAnchor, constant: 5),
  2661. labelType.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2662. ])
  2663. labelType.font = UIFont.systemFont(ofSize: 12)
  2664. labelType.text = "Request Type".localized()
  2665. labelType.textColor = .mainColor
  2666. let valueType = UILabel()
  2667. containerView.addSubview(valueType)
  2668. valueType.translatesAutoresizingMaskIntoConstraints = false
  2669. NSLayoutConstraint.activate([
  2670. valueType.topAnchor.constraint(equalTo: labelType.bottomAnchor),
  2671. valueType.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2672. ])
  2673. valueType.font = UIFont.systemFont(ofSize: 12)
  2674. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "0" {
  2675. valueType.text = "Chat".localized()
  2676. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  2677. valueType.text = "Audio Call".localized()
  2678. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  2679. valueType.text = "Video Call".localized()
  2680. } else {
  2681. valueType.text = "Email".localized()
  2682. }
  2683. valueType.textColor = .mainColor
  2684. let labelIdentity = UILabel()
  2685. containerView.addSubview(labelIdentity)
  2686. labelIdentity.translatesAutoresizingMaskIntoConstraints = false
  2687. NSLayoutConstraint.activate([
  2688. labelIdentity.topAnchor.constraint(equalTo: valueType.bottomAnchor, constant: 5),
  2689. labelIdentity.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2690. ])
  2691. labelIdentity.font = UIFont.systemFont(ofSize: 12)
  2692. labelIdentity.text = "Complaint ID".localized()
  2693. labelIdentity.textColor = .mainColor
  2694. let valueIdentity = UILabel()
  2695. containerView.addSubview(valueIdentity)
  2696. valueIdentity.translatesAutoresizingMaskIntoConstraints = false
  2697. NSLayoutConstraint.activate([
  2698. valueIdentity.topAnchor.constraint(equalTo: labelIdentity.bottomAnchor),
  2699. valueIdentity.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5),
  2700. valueIdentity.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
  2701. ])
  2702. valueIdentity.font = UIFont.systemFont(ofSize: 12)
  2703. valueIdentity.text = message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)
  2704. valueIdentity.numberOfLines = 0
  2705. valueIdentity.textColor = .mainColor
  2706. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2707. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  2708. } else {
  2709. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  2710. }
  2711. }
  2712. } else if message.getCode() != CoreMessage_TMessageCode.PUSH_CALL_CENTER && message.getCode() != CoreMessage_TMessageCode.ACCEPT_CALL_CENTER && message.getCode() != CoreMessage_TMessageCode.END_CALL_CENTER && message.getCode() != CoreMessage_TMessageCode.TIMEOUT_CONTACT_CENTER && message.getCode() != CoreMessage_TMessageCode.ACCEPT_CONTACT_CENTER && message.getCode() != CoreMessage_TMessageCode.PUSH_MEMBER_ROOM_CONTACT_CENTER && message.getCode() != CoreMessage_TMessageCode.INVITE_END_CONTACT_CENTER && message.getCode() != CoreMessage_TMessageCode.INVITE_EXIT_CONTACT_CENTER || message.mBodies["MERNAM"] != nil {
  2713. let m = message.mBodies
  2714. if message.mBodies["MERNAM"] != nil {
  2715. DispatchQueue.main.async {
  2716. if !Nexilis.broadcastList.isEmpty {
  2717. Nexilis.broadcastList.append(m)
  2718. } else {
  2719. Nexilis.broadcastList.append(m)
  2720. Nexilis.shared.showBroadcastMessage(m: m)
  2721. }
  2722. }
  2723. return
  2724. }
  2725. if !Nexilis.showLibraryNotification {
  2726. return
  2727. }
  2728. let sender = m[CoreMessage_TMessageKey.F_PIN]!
  2729. let me = UserDefaults.standard.string(forKey: "me")!
  2730. if(sender != me) {
  2731. let inEditorPersonal = UserDefaults.standard.string(forKey: "inEditorPersonal")
  2732. let inEditorGroup = UserDefaults.standard.stringArray(forKey: "inEditorGroup")
  2733. var text = m["A07"]!
  2734. if (m.keys.contains("A57") && !((m["A57"]!).isEmpty)) {
  2735. text = "Sent Image 📷"
  2736. } else if (m.keys.contains("A149")) && (m["A149"]!) == "11" {
  2737. text = "Sent Sticker ❤️"
  2738. } else if (m.keys.contains("A47") && !((m["A47"]!).isEmpty)) {
  2739. text = "Sent Video 📹"
  2740. } else if (m.keys.contains("BN") && !((m["BN"]!).isEmpty)) {
  2741. if m["A06"]! == "18" {
  2742. text = "Sent Form 📄"
  2743. } else {
  2744. text = "Sent File 📄"
  2745. }
  2746. } else if (m.keys.contains("A63") && !((m["A63"]!).isEmpty)) {
  2747. text = "Sent Audio 🎵"
  2748. } else if ((m["A07"]!).contains("Share%20location%20")) {
  2749. text = "Sent Location 📌"
  2750. } else if (m.keys.contains("A149")) && (m["A149"]!) == "27" {
  2751. text = "Sent Live Streaming"
  2752. } else if (m.keys.contains("A149")) && (m["A149"]!) == "26" {
  2753. text = "Sent Seminar"
  2754. } else if (m.keys.contains("A149")) && (m["A149"]!) == "25" {
  2755. text = "Sent Video Conference Room"
  2756. } else if (m.keys.contains("A149")) && (m["A149"]!) == "24" {
  2757. text = "Sent Quiz"
  2758. } else if (m.keys.contains("A118")) && (m["A118"]!) == "1" {
  2759. text = "Sent Confidential Message"
  2760. }
  2761. var nameUser: String?
  2762. var profile = ""
  2763. var threadIdentifier = sender
  2764. let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
  2765. if !onGoingCC.isEmpty {
  2766. return
  2767. }
  2768. if Utils.inTabChats{
  2769. return
  2770. }
  2771. if(m["A06"]! == "3" || m["A06"]! == "18" || m["A06"]! == "5") {
  2772. if inEditorPersonal == sender || (inEditorPersonal != nil && inEditorPersonal!.contains(",")) {
  2773. return
  2774. }
  2775. if(nameUser == nil) {
  2776. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  2777. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name, image_id FROM BUDDY WHERE f_pin='\(String(describing: sender))'") {
  2778. while cursor.next() {
  2779. let first_name = cursor.string(forColumnIndex: 0)!
  2780. let last_name = cursor.string(forColumnIndex: 1)!
  2781. nameUser = "\(first_name) \(last_name)".trimmingCharacters(in: .whitespaces)
  2782. profile = cursor.string(forColumnIndex: 2)!
  2783. }
  2784. cursor.close()
  2785. }
  2786. })
  2787. }
  2788. } else {
  2789. let idGroup = m["A01"]!
  2790. var topicGroup: String?
  2791. var idTopic: String?
  2792. if (m.keys.contains("BA")) {
  2793. idTopic = m["BA"]
  2794. }
  2795. if (idTopic == nil) {
  2796. idTopic = "Lounge"
  2797. topicGroup = "Lounge"
  2798. } else {
  2799. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  2800. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT title FROM DISCUSSION_FORUM WHERE chat_id='\(idTopic!)'") {
  2801. while cursor.next() {
  2802. let title = cursor.string(forColumnIndex: 0)
  2803. topicGroup = title
  2804. }
  2805. cursor.close()
  2806. }
  2807. })
  2808. }
  2809. if (inEditorGroup != nil) {
  2810. let editorIdGroup = inEditorGroup![0]
  2811. let editorIdTopic = inEditorGroup![1]
  2812. var idTempTopic = idTopic
  2813. if (idTempTopic == "Lounge") {
  2814. idTempTopic = ""
  2815. }
  2816. if (editorIdGroup == idGroup && editorIdTopic == idTempTopic) {
  2817. return
  2818. }
  2819. }
  2820. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  2821. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_name, image_id FROM GROUPZ WHERE group_id='\(idGroup)'") {
  2822. while cursor.next() {
  2823. let f_name = cursor.string(forColumnIndex: 0)
  2824. var senderName = m["BR"]
  2825. if senderName == nil {
  2826. senderName = "Bot"
  2827. }
  2828. nameUser =
  2829. "\(senderName!) \u{2022} \(f_name!)(\(topicGroup!))"
  2830. profile = cursor.string(forColumnIndex: 1)!
  2831. }
  2832. cursor.close()
  2833. }
  2834. })
  2835. if idTopic == "Lounge" {
  2836. threadIdentifier = idGroup
  2837. } else {
  2838. threadIdentifier = idTopic!
  2839. }
  2840. }
  2841. if nameUser == nil && threadIdentifier == "-999" {
  2842. nameUser = "Bot"
  2843. }
  2844. DispatchQueue.main.async { [self] in
  2845. let container = UIView()
  2846. container.backgroundColor = .gray
  2847. let profileImage = UIImageView()
  2848. profileImage.frame.size = CGSize(width: 60, height: 60)
  2849. container.addSubview(profileImage)
  2850. profileImage.translatesAutoresizingMaskIntoConstraints = false
  2851. NSLayoutConstraint.activate([
  2852. profileImage.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 8.0),
  2853. profileImage.centerYAnchor.constraint(equalTo: container.centerYAnchor),
  2854. profileImage.widthAnchor.constraint(equalToConstant: 60),
  2855. profileImage.heightAnchor.constraint(equalToConstant: 60),
  2856. ])
  2857. let title = UILabel()
  2858. container.addSubview(title)
  2859. title.translatesAutoresizingMaskIntoConstraints = false
  2860. NSLayoutConstraint.activate([
  2861. title.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 8.0),
  2862. title.topAnchor.constraint(equalTo: container.topAnchor, constant: 20.0),
  2863. ])
  2864. title.font = UIFont.systemFont(ofSize: 14)
  2865. title.text = nameUser ?? "Unknown"
  2866. title.textColor = .white
  2867. let subtitle = UILabel()
  2868. container.addSubview(subtitle)
  2869. subtitle.translatesAutoresizingMaskIntoConstraints = false
  2870. NSLayoutConstraint.activate([
  2871. subtitle.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 8.0),
  2872. subtitle.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -15.0),
  2873. subtitle.topAnchor.constraint(equalTo: title.bottomAnchor),
  2874. ])
  2875. subtitle.font = UIFont.systemFont(ofSize: 12)
  2876. subtitle.attributedText = text.richText()
  2877. subtitle.textColor = .white
  2878. if floating != nil {
  2879. floating.dismiss()
  2880. }
  2881. floating = FloatingNotificationBanner(customView: container)
  2882. floating.bannerHeight = 100.0
  2883. floating.transparency = 0.9
  2884. if threadIdentifier == "-999" {
  2885. if !Utils.getIconDock().isEmpty {
  2886. let dataImage = try? Data(contentsOf: URL(string: Utils.getUrlDock()!)!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
  2887. if dataImage != nil {
  2888. profileImage.image = UIImage(data: dataImage!)
  2889. }
  2890. } else {
  2891. profileImage.image = UIImage(named: "pb_button", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
  2892. }
  2893. } else if profile != "" {
  2894. profileImage.circle()
  2895. do {
  2896. let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  2897. let file = documentDir.appendingPathComponent(profile)
  2898. if FileManager().fileExists(atPath: file.path) {
  2899. profileImage.image = UIImage(contentsOfFile: file.path)
  2900. profileImage.backgroundColor = .clear
  2901. } else {
  2902. Download().startHTTP(forKey: profile) { (name, progress) in
  2903. guard progress == 100 else {
  2904. return
  2905. }
  2906. DispatchQueue.main.async { [self] in
  2907. profileImage.image = UIImage(contentsOfFile: file.path)
  2908. profileImage.backgroundColor = .clear
  2909. if !onGoingCC.isEmpty {
  2910. floating.autoDismiss = false
  2911. }
  2912. floating.show(queuePosition: .front, bannerPosition: .top, queue: NotificationBannerQueue(maxBannersOnScreenSimultaneously: 1), on: nil, edgeInsets: UIEdgeInsets(top: 8.0, left: 8.0, bottom: 0, right: 8.0), cornerRadius: 8.0, shadowColor: .clear, shadowOpacity: .zero, shadowBlurRadius: .zero, shadowCornerRadius: .zero, shadowOffset: .zero, shadowEdgeInsets: nil)
  2913. floating.onTap = {
  2914. showNotif()
  2915. }
  2916. }
  2917. }
  2918. return
  2919. }
  2920. } catch {}
  2921. profileImage.contentMode = .scaleAspectFill
  2922. } else {
  2923. profileImage.circle()
  2924. if m["A06"]! == "3" {
  2925. profileImage.image = UIImage(systemName: "person")
  2926. } else {
  2927. profileImage.image = UIImage(systemName: "person.3")
  2928. }
  2929. profileImage.contentMode = .scaleAspectFit
  2930. profileImage.backgroundColor = .lightGray
  2931. profileImage.tintColor = .white
  2932. }
  2933. floating.show(queuePosition: .front, bannerPosition: .top, queue: NotificationBannerQueue(maxBannersOnScreenSimultaneously: 1), on: nil, edgeInsets: UIEdgeInsets(top: 8.0, left: 8.0, bottom: 0, right: 8.0), cornerRadius: 8.0, shadowColor: .clear, shadowOpacity: .zero, shadowBlurRadius: .zero, shadowCornerRadius: .zero, shadowOffset: .zero, shadowEdgeInsets: nil)
  2934. let vibrateMode = UserDefaults.standard.bool(forKey: "vibrateMode")
  2935. var soundId = UserDefaults.standard.string(forKey: "notifSoundPersonal") ?? ""
  2936. if message.getBody(key: CoreMessage_TMessageKey.MESSAGE_SCOPE_ID) == "4" {
  2937. soundId = UserDefaults.standard.string(forKey: "notifSoundGroup") ?? ""
  2938. }
  2939. var systemSoundID: SystemSoundID!
  2940. if soundId.isEmpty {
  2941. systemSoundID = 1007
  2942. } else {
  2943. systemSoundID = SystemSoundID(Int(soundId.components(separatedBy: ":")[0])!)
  2944. }
  2945. if vibrateMode {
  2946. AudioServicesPlaySystemSound(systemSoundID)
  2947. } else {
  2948. var nameSound = "sms-received1"
  2949. if systemSoundID != 1007 {
  2950. nameSound = soundId.components(separatedBy: ":")[1]
  2951. }
  2952. let url = URL(fileURLWithPath: "/System/Library/Audio/UISounds/\(nameSound).caf")
  2953. AudioServicesCreateSystemSoundID(url as CFURL, &systemSoundID)
  2954. AudioServicesPlaySystemSound(systemSoundID)
  2955. }
  2956. if !onGoingCC.isEmpty {
  2957. floating.autoDismiss = false
  2958. }
  2959. floating.onTap = {
  2960. showNotif()
  2961. }
  2962. func showNotif() {
  2963. if !onGoingCC.isEmpty {
  2964. floating.dismiss()
  2965. }
  2966. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  2967. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name FROM BUDDY where f_pin = '\(UserDefaults.standard.string(forKey: "me")!)'"), cursorData.next() {
  2968. if (cursorData.string(forColumnIndex: 0)! + " " + cursorData.string(forColumnIndex: 1)!).trimmingCharacters(in: .whitespaces) == "USR\(UserDefaults.standard.string(forKey: "me")!)" {
  2969. let alert = LibAlertController(title: "Change Profile".localized(), message: "You must change your name to use this feature".localized(), preferredStyle: .alert)
  2970. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  2971. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  2972. controller.forceLogin = true
  2973. let navigationController = UINavigationController(rootViewController: controller)
  2974. navigationController.modalPresentationStyle = .fullScreen
  2975. navigationController.navigationBar.tintColor = .white
  2976. navigationController.navigationBar.barTintColor = .mainColor
  2977. navigationController.navigationBar.isTranslucent = false
  2978. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  2979. navigationController.navigationBar.barStyle = .black
  2980. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  2981. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  2982. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  2983. navigationController.navigationBar.titleTextAttributes = textAttributes
  2984. navigationController.view.backgroundColor = .mainColor
  2985. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2986. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2987. } else {
  2988. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2989. }
  2990. }))
  2991. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2992. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  2993. } else {
  2994. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  2995. }
  2996. }
  2997. cursorData.close()
  2998. return
  2999. }
  3000. })
  3001. if(m["A06"]! == "3" || m["A06"]! == "5" || m["A06"]! == "18") {
  3002. func openEditor() {
  3003. let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  3004. editorPersonalVC.hidesBottomBarWhenPushed = true
  3005. editorPersonalVC.unique_l_pin = threadIdentifier
  3006. editorPersonalVC.fromNotification = true
  3007. if !onGoingCC.isEmpty {
  3008. let compalintId = onGoingCC.components(separatedBy: ",")[2]
  3009. let fPinCC = onGoingCC.isEmpty ? "" : onGoingCC.components(separatedBy: ",")[1]
  3010. editorPersonalVC.isContactCenter = true
  3011. editorPersonalVC.fPinContacCenter = fPinCC
  3012. editorPersonalVC.complaintId = compalintId
  3013. editorPersonalVC.onGoingCC = true
  3014. editorPersonalVC.isRequestContactCenter = false
  3015. }
  3016. let navigationController = UINavigationController(rootViewController: editorPersonalVC)
  3017. navigationController.modalPresentationStyle = .fullScreen
  3018. navigationController.navigationBar.tintColor = .white
  3019. navigationController.navigationBar.barTintColor = .mainColor
  3020. navigationController.navigationBar.isTranslucent = false
  3021. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  3022. navigationController.navigationBar.barStyle = .black
  3023. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  3024. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  3025. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  3026. navigationController.navigationBar.titleTextAttributes = textAttributes
  3027. navigationController.view.backgroundColor = .mainColor
  3028. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3029. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  3030. } else {
  3031. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  3032. }
  3033. }
  3034. if UIApplication.shared.visibleViewController is UINavigationController {
  3035. let nc = UIApplication.shared.visibleViewController as! UINavigationController
  3036. if nc.visibleViewController is QmeraStreamingViewController {
  3037. let vc = nc.visibleViewController as! QmeraStreamingViewController
  3038. var alert = LibAlertController(title: "", message: "Are you sure you want to end Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  3039. if !vc.isLive {
  3040. alert = LibAlertController(title: "", message: "Are you sure you want to leave Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  3041. }
  3042. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: nil))
  3043. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3044. DispatchQueue.global().async {
  3045. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  3046. vc.sendLeft()
  3047. }
  3048. vc.dismiss(animated: true, completion: {
  3049. openEditor()
  3050. })
  3051. }))
  3052. nc.present(alert, animated: true, completion: nil)
  3053. // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "isRunningStreaming"), object: nil, userInfo: dataMessage)
  3054. } else if nc.visibleViewController is SeminarViewController {
  3055. let vc = nc.visibleViewController as! SeminarViewController
  3056. var alert = LibAlertController(title: "", message: "Are you sure you want to end Seminar, and open notification?".localized(), preferredStyle: .alert)
  3057. if !vc.isLive {
  3058. alert = LibAlertController(title: "", message: "Are you sure you want to leave Seminar, and open notification?".localized(), preferredStyle: .alert)
  3059. }
  3060. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: nil))
  3061. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3062. DispatchQueue.global().async {
  3063. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  3064. vc.sendLeft()
  3065. }
  3066. vc.dismiss(animated: true, completion: {
  3067. openEditor()
  3068. })
  3069. }))
  3070. nc.present(alert, animated: true, completion: nil)
  3071. // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "isRunningStreaming"), object: nil, userInfo: dataMessage)
  3072. } else if nc.visibleViewController is EditorPersonal {
  3073. let vc = nc.visibleViewController as! EditorPersonal
  3074. if vc.fromNotification {
  3075. vc.dismiss(animated: true, completion: {
  3076. openEditor()
  3077. })
  3078. } else {
  3079. vc.navigationController?.popViewController(animated: true)
  3080. openEditor()
  3081. }
  3082. } else {
  3083. openEditor()
  3084. }
  3085. } else if UIApplication.shared.visibleViewController is EditorPersonal {
  3086. let vc = UIApplication.shared.visibleViewController as! EditorPersonal
  3087. if vc.fromNotification{
  3088. vc.dismiss(animated: true, completion: {
  3089. openEditor()
  3090. })
  3091. } else {
  3092. vc.navigationController?.popViewController(animated: true)
  3093. openEditor()
  3094. }
  3095. } else if UIApplication.shared.visibleViewController is UIAlertController {
  3096. let vc = UIApplication.shared.visibleViewController as! UIAlertController
  3097. vc.dismiss(animated: true, completion: {
  3098. openEditor()
  3099. })
  3100. } else {
  3101. openEditor()
  3102. }
  3103. } else {
  3104. func openEditor() {
  3105. let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "editorGroupVC") as! EditorGroup
  3106. editorGroupVC.hidesBottomBarWhenPushed = true
  3107. editorGroupVC.unique_l_pin = threadIdentifier
  3108. editorGroupVC.fromNotification = true
  3109. let navigationController = UINavigationController(rootViewController: editorGroupVC)
  3110. navigationController.modalPresentationStyle = .fullScreen
  3111. navigationController.navigationBar.tintColor = .white
  3112. navigationController.navigationBar.barTintColor = .mainColor
  3113. navigationController.navigationBar.isTranslucent = false
  3114. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  3115. navigationController.navigationBar.barStyle = .black
  3116. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  3117. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  3118. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  3119. navigationController.navigationBar.titleTextAttributes = textAttributes
  3120. navigationController.view.backgroundColor = .mainColor
  3121. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3122. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  3123. } else {
  3124. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  3125. }
  3126. }
  3127. if UIApplication.shared.visibleViewController is UINavigationController {
  3128. let nc = UIApplication.shared.visibleViewController as! UINavigationController
  3129. if nc.visibleViewController is QmeraStreamingViewController {
  3130. let vc = nc.visibleViewController as! QmeraStreamingViewController
  3131. var alert = LibAlertController(title: "", message: "Are you sure you want to end Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  3132. if !vc.isLive {
  3133. alert = LibAlertController(title: "", message: "Are you sure you want to leave Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  3134. }
  3135. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: nil))
  3136. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3137. DispatchQueue.global().async {
  3138. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  3139. vc.sendLeft()
  3140. }
  3141. vc.dismiss(animated: true, completion: {
  3142. openEditor()
  3143. })
  3144. }))
  3145. nc.present(alert, animated: true, completion: nil)
  3146. // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "isRunningStreaming"), object: nil, userInfo: dataMessage)
  3147. } else if nc.visibleViewController is SeminarViewController {
  3148. let vc = nc.visibleViewController as! SeminarViewController
  3149. var alert = LibAlertController(title: "", message: "Are you sure you want to end Seminar, and open notification?".localized(), preferredStyle: .alert)
  3150. if !vc.isLive {
  3151. alert = LibAlertController(title: "", message: "Are you sure you want to leave Seminar, and open notification?".localized(), preferredStyle: .alert)
  3152. }
  3153. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: nil))
  3154. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3155. DispatchQueue.global().async {
  3156. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  3157. vc.sendLeft()
  3158. }
  3159. vc.dismiss(animated: true, completion: {
  3160. openEditor()
  3161. })
  3162. }))
  3163. nc.present(alert, animated: true, completion: nil)
  3164. // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "isRunningStreaming"), object: nil, userInfo: dataMessage)
  3165. } else if nc.visibleViewController is EditorGroup {
  3166. let vc = nc.visibleViewController as! EditorGroup
  3167. if vc.fromNotification {
  3168. vc.dismiss(animated: true, completion: {
  3169. openEditor()
  3170. })
  3171. } else {
  3172. vc.navigationController?.popViewController(animated: true)
  3173. openEditor()
  3174. }
  3175. } else {
  3176. openEditor()
  3177. }
  3178. } else if UIApplication.shared.visibleViewController is EditorGroup {
  3179. let vc = UIApplication.shared.visibleViewController as! EditorGroup
  3180. if vc.fromNotification {
  3181. vc.dismiss(animated: true, completion: {
  3182. openEditor()
  3183. })
  3184. } else {
  3185. vc.navigationController?.popViewController(animated: true)
  3186. openEditor()
  3187. }
  3188. } else if UIApplication.shared.visibleViewController is UIAlertController {
  3189. let vc = UIApplication.shared.visibleViewController as! UIAlertController
  3190. vc.dismiss(animated: true, completion: {
  3191. openEditor()
  3192. })
  3193. } else {
  3194. openEditor()
  3195. }
  3196. }
  3197. }
  3198. }
  3199. }
  3200. }
  3201. }
  3202. public static func addFriend(fpin: String, completion: @escaping (Bool) -> ()) {
  3203. DispatchQueue.global().async {
  3204. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddFriendQRCode(fpin: fpin)), response.isOk() {
  3205. completion(true)
  3206. } else {
  3207. completion(false)
  3208. }
  3209. }
  3210. }
  3211. public static func addFriendSilent(fpin: String) {
  3212. DispatchQueue.global().async {
  3213. _ = Nexilis.write(message: CoreMessage_TMessageBank.getAddFriendQRCodeSilent(fpin: fpin))
  3214. }
  3215. }
  3216. public func onReceive(message: [AnyHashable : Any?]) {
  3217. var dataMessage: [AnyHashable : Any] = [:]
  3218. dataMessage["message"] = message
  3219. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerReceiveChat), object: nil, userInfo: dataMessage)
  3220. }
  3221. public func onMessage(message: TMessage) {
  3222. var dataMessage: [AnyHashable : Any] = [:]
  3223. dataMessage["message"] = message
  3224. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerStatusChat), object: nil, userInfo: dataMessage)
  3225. }
  3226. public func onUpload(name: String, progress: Double) {
  3227. var dataMessage: [AnyHashable : Any] = [:]
  3228. dataMessage["name"] = name
  3229. dataMessage["progress"] = progress
  3230. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onUploadChat"), object: nil, userInfo: dataMessage)
  3231. }
  3232. public func onTyping(message: TMessage) {
  3233. var dataMessage: [AnyHashable : Any] = [:]
  3234. dataMessage["message"] = message
  3235. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerTypingChat), object: nil, userInfo: dataMessage)
  3236. }
  3237. // public static func faceDetect(fd: FaceDetector?,image: UIImage, completion: ((Bool) -> ())?){
  3238. // //print("enter vision")
  3239. // let visionImage = VisionImage(image: image)
  3240. // //print("exit vision")
  3241. // var retval = false
  3242. // visionImage.orientation = image.imageOrientation
  3243. // var fd1 : FaceDetector?
  3244. // if(fd == nil){
  3245. // fd1 = FaceDetector.faceDetector()
  3246. // }
  3247. // else {
  3248. // fd1 = fd
  3249. // }
  3250. //
  3251. // // [START detect_faces]
  3252. // fd1?.process(visionImage) {faces, error in
  3253. // guard error == nil, let faces = faces, !faces.isEmpty else {
  3254. // //print("faces empty")
  3255. // completion?(false)
  3256. // return
  3257. // }
  3258. // if(faces.count > 0){
  3259. // //print("face count: \(faces.count)")
  3260. // retval = true
  3261. // }
  3262. // completion?(retval)
  3263. // }
  3264. //
  3265. // }
  3266. }
  3267. extension Nexilis: GroupDelegate {
  3268. public func onGroup(code: String, f_pin: String, groupId: String) {
  3269. var data: [AnyHashable : Any] = [:]
  3270. data["code"] = code
  3271. data["f_pin"] = f_pin
  3272. data["groupId"] = groupId
  3273. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onGroup"), object: nil, userInfo: data)
  3274. }
  3275. public func onTopic(code: String, f_pin: String, topicId: String) {
  3276. var data: [AnyHashable : Any] = [:]
  3277. data["code"] = code
  3278. data["f_pin"] = f_pin
  3279. data["topicId"] = topicId
  3280. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onTopic"), object: nil, userInfo: data)
  3281. }
  3282. public func onMember(code: String, f_pin: String, groupId: String, member: String) {
  3283. var data: [AnyHashable : Any] = [:]
  3284. data["code"] = code
  3285. data["f_pin"] = f_pin
  3286. data["groupId"] = groupId
  3287. data["member"] = member
  3288. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onMember"), object: nil, userInfo: data)
  3289. }
  3290. }
  3291. extension Nexilis: PersonInfoDelegate {
  3292. public func onUpdatePersonInfo(state: Int, message: String) {
  3293. var data: [AnyHashable : Any] = [:]
  3294. data["state"] = state
  3295. data["message"] = message
  3296. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onUpdatePersonInfo"), object: nil, userInfo: data)
  3297. }
  3298. }
  3299. extension Nexilis: QLPreviewControllerDataSource {
  3300. public func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
  3301. return 1
  3302. }
  3303. public func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
  3304. return previewItem!
  3305. }
  3306. }