Nexilis.swift 256 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470
  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. import SDWebImage
  17. import CryptoKit
  18. public class Nexilis: NSObject {
  19. public static var sAPIKey = ""
  20. public static var ADDRESS = ""
  21. // static let ADDRESS_33 = "192.168.0.33"
  22. // static let ADDRESS_RELEASE = "202.158.33.26" //CBN
  23. // static let ADDRESS_RELEASE = "108.137.84.148" //AWS
  24. // static let PORT = 45328
  25. // static let PORT = 65328 // 33
  26. static var PORT = PORT_RELEASE
  27. static let PORT_33 = 62328
  28. static let PORT_RELEASE = 42328
  29. static var nSessionMode: Int! = 1
  30. static var dispatch: DispatchGroup?
  31. public static var showFB = false
  32. public static var fromMAB = false
  33. let callManager = CallManager()
  34. var providerDelegate: CallProviderDelegate?
  35. public static let shared = Nexilis()
  36. // public static var broadcastTimer = Timer()
  37. public static var broadcastList = [[String: String]]()
  38. public static var onGoingPushCC: [String: String] = [:]
  39. public static var openBroadcast = false
  40. public static var loadingAlert = LibAlertController()
  41. public static var floatingButton = FloatingButton()
  42. public static var defaultFloatingButton: [Int] = []
  43. public static var showButtonFB = false
  44. public static var isShowForceSignIn = true
  45. public static var afterConnect = true
  46. public static var imageCache = NSCache<NSString, UIImage>()
  47. public static let listenerReceiveChat = "onReceiveChatLibLite"
  48. public static let listenerStatusChat = "onMessageChatLibLite"
  49. public static let listenerTypingChat = "onTypingChatLibLite"
  50. public static let listenerStatusCall = "onStatusCallLibLite"
  51. public static let callFCM = "onCallFCM"
  52. public static let failedSendMessage = "onFailedSendMessage"
  53. public static var showLibraryNotification = true
  54. public static let STREAMING_SEMINAR_ENDED = 88
  55. public static let VIDEO_CALL_END = 38
  56. public static let VIDEO_CALL_MUTE_UNMUTE = 36
  57. public static let VIDEO_CALL_ZOOM = 35
  58. public static let VIDEO_CAMERA_PARAMS_CHANED = 34
  59. public static let VIDEO_CALL_RINGING = 33
  60. public static let VIDEO_CALL_OFFHOOK = 32
  61. public static let VIDEO_CALL_INCOMING = 31
  62. public static let AUDIO_CALL_END = 28
  63. public static let AUDIO_CALL_RINGING = 23
  64. public static let AUDIO_CALL_OFFHOOK = 22
  65. public static let AUDIO_CALL_INCOMING = 21
  66. public static let AUDIO_VIDEO_CALL_MUTED = 26
  67. public static let VIDEO_RINGING = 11
  68. public static let ENDED = 8
  69. public static let INITIATING = 4
  70. public static let AUDIO_RINGING = 1
  71. public static let OUTGOING_CALL = 0
  72. public static let OFFLINE = -3
  73. public static let BUSY = -4
  74. public static let IDX_QUEUE_SYSTEM = 2
  75. public static let IDX_NOTIF_CENTER = 3
  76. public static let IDX_CC_STREAM = 4
  77. public static let IDX_CHAT = 6
  78. public static let IDX_CALL = 7
  79. public static let IDX_STREAM = 8
  80. public static let IDX_CC = 9
  81. public static let IDX_CALL_AUDIO = 11
  82. public static let IDX_CALL_VIDEO = 12
  83. public static let IDX_WHITEBOARD = 13
  84. public static let IDX_SCREENSHARING = 14
  85. public static let IDX_WB_SS = 15
  86. public static let IDX_BROADCAST_FORM = 16
  87. public static let IDX_CONVERSATION = 17
  88. public static let IDX_FAVORITEMESSAGE = 18
  89. public static let IDX_CONFERENCE_ROOM_FORM = 19
  90. public static let IDX_EMAIL_CONFIGURATION = 20
  91. public static let IDX_CREATE_GROUP = 21
  92. public static let IDX_ADDFRIEND = 22
  93. public static let IDX_SIGNUP_OR_IN_PAGE = 23
  94. public static let IDX_SECURE_FOLDER = 29
  95. public static let IDX_SETTING = 32
  96. public static let IDX_POST = 99
  97. public static let IDX_SELF_ACT = 100
  98. public static let IDX_SOCIAL_COMMERCE = 101
  99. public static let IDX_NEWS = 102
  100. public static let IDX_SECURE_BROWSER = 105
  101. public static var callAPNActivated = false
  102. private static var ringtonePlayer: AVAudioPlayer?
  103. private static var ringbacktonePlayer: AVAudioPlayer?
  104. private static var busyPlayer: AVAudioPlayer?
  105. static var sharedAudioPlayer: AVAudioPlayer?
  106. private func createDelegate() {
  107. //print("createDelegate...")
  108. callDelegate = self
  109. messageDelegate = self
  110. groupDelegate = self
  111. personInfoDelegate = self
  112. providerDelegate = CallProviderDelegate(callManager: callManager)
  113. }
  114. public static func connect(apiKey: String, delegate: ConnectDelegate, showButton: Bool = true, fromMAB: Bool = false) {
  115. showFB = showButton
  116. Nexilis.fromMAB = fromMAB
  117. Nexilis.shared.createDelegate()
  118. Nexilis.sAPIKey = apiKey
  119. Nexilis.showButtonFB = showButton
  120. do {
  121. try MasterKeyUtil.shared.generateAndStoreMasterKey()
  122. try MasterKeyUtil.shared.generateAndStorePrefsKey()
  123. if Utils.getCertificatePinningWebview().isEmpty {
  124. let cert: [String: String] = ["nexilis.io": Utils.decrypt(str: "7^reFspLRnRz3NaVjeI2AUQ0l5JFQbf0bZZ3dfYaBMqnL"), "newuniverse.io": Utils.decrypt(str: "6]umyRKg9l6D2N?2wVaejmtPrWNtVKpjqt0mqyA68XwFi")]
  125. if let jsonData = try? JSONSerialization.data(withJSONObject: cert, options: []),
  126. let jsonString = String(data: jsonData, encoding: .utf8) {
  127. Utils.setCertificatePinningWebview(value: jsonString)
  128. }
  129. }
  130. } catch {
  131. }
  132. IncomingThread.default.run()
  133. imageCache.countLimit = 100
  134. imageCache.totalCostLimit = 1024 * 1024 * 200
  135. UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum)
  136. DispatchQueue.global().async {
  137. do {
  138. if Utils.getFinishInitPrefsr() {
  139. Utils.setFinishInitPrefs(value: false)
  140. }
  141. let address = Nexilis.getAddressNew(apiKey:apiKey)
  142. if address.isEmpty {
  143. return
  144. }
  145. // print("HUHU>> \(API.sGetVersion())")
  146. var id = Utils.getConnectionID()
  147. Nexilis.ADDRESS = address.components(separatedBy: ":")[0]
  148. Nexilis.PORT = Int(address.components(separatedBy: ":")[1]) ?? 0
  149. if id.isEmpty {
  150. let sDID = UIDevice.current.identifierForVendor?.uuidString ?? "UNK-DEVICE"
  151. id = String(sDID[sDID.index(sDID.endIndex, offsetBy: -5)...])
  152. Utils.setConnectionID(value: id)
  153. }
  154. try API.initConnection(sAPIK: apiKey, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: id, sStartWH: "09:00")
  155. while (API.nGetCLXConnState() == 0) {
  156. Thread.sleep(forTimeInterval: 0.5)
  157. }
  158. if(User.getMyPin() == nil) {
  159. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignUpApi(api: apiKey, p_pin: id), timeout: 30 * 1000){
  160. id = response.getBody(key: CoreMessage_TMessageKey.F_PIN, default_value: "")
  161. let enable_signup = (response.getBody(key: CoreMessage_TMessageKey.IS_ENABLED_ANONYMOUS, default_value: "0")) == "1"
  162. Utils.setForceAnonymous(value: enable_signup)
  163. if(!id.isEmpty) {
  164. SecureUserDefaults.shared.set(id, forKey: "me")
  165. }
  166. }
  167. }
  168. let api: String? = SecureUserDefaults.shared.value(forKey: "apiKey") ?? nil
  169. if api == nil {
  170. SecureUserDefaults.shared.set(apiKey, forKey: "apiKey")
  171. }
  172. getPullPrefs()
  173. getFeatureAccess()
  174. if let me = User.getMyPin() {
  175. if Utils.getSetProfile() {
  176. _ = Database.shared.openDatabase()
  177. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  178. do {
  179. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT * FROM BUDDY where f_pin = '\(me)' ") {
  180. if !cursorData.next() {
  181. _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: me))
  182. }
  183. cursorData.close()
  184. }
  185. } catch {
  186. rollback.pointee = true
  187. print("Access database error: \(error.localizedDescription)")
  188. }
  189. })
  190. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  191. do {
  192. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT image_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorData.next() {
  193. do {
  194. let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  195. let file = documentDir.appendingPathComponent(cursorData.string(forColumnIndex: 0)!)
  196. if !FileManager().fileExists(atPath: file.path) {
  197. Download().startHTTP(forKey: cursorData.string(forColumnIndex: 0)!) { (name, progress) in}
  198. }
  199. } catch {}
  200. cursorData.close()
  201. }
  202. } catch {
  203. rollback.pointee = true
  204. print("Access database error: \(error.localizedDescription)")
  205. }
  206. })
  207. } else if isShowForceSignIn && !Utils.getForceAnonymous() && !Utils.getSetProfile() {
  208. DispatchQueue.main.async {
  209. showForceSignIn()
  210. }
  211. }
  212. getServiceBank()
  213. getPullWorkingArea()
  214. getPullGroupNoMember()
  215. delegate.onSuccess(userId: me)
  216. DispatchQueue.main.async {
  217. var viewController = UIApplication.shared.windows.first?.rootViewController
  218. var notNull = false
  219. while !notNull {
  220. viewController = UIApplication.shared.windows.first?.rootViewController
  221. if viewController != nil && Utils.getFinishInitPrefsr() {
  222. notNull = true
  223. }
  224. }
  225. if showButton {
  226. addFB(viewController: viewController!, fromMAB: fromMAB)
  227. }
  228. if let rootViewController = viewController {
  229. let isDarkMode = rootViewController.traitCollection.userInterfaceStyle == .dark
  230. if isDarkMode {
  231. UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
  232. let cancelButtonAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  233. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes , for: .normal)
  234. } else {
  235. UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.black]
  236. let cancelButtonAttributes = [NSAttributedString.Key.foregroundColor: UIColor.black, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  237. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes , for: .normal)
  238. }
  239. }
  240. }
  241. if (Utils.getSetProfile() && !Utils.getFinishInitPrefsr()) || (!Utils.getForceAnonymous() && !Utils.getFinishInitPrefsr()) {
  242. Utils.setFinishInitPrefs(value: true)
  243. }
  244. Nexilis.destroyAll()
  245. if !Utils.getLoginMultipleFPin().isEmpty {
  246. let dialog = DialogUnableAccess()
  247. dialog.modalTransitionStyle = .crossDissolve
  248. dialog.modalPresentationStyle = .overCurrentContext
  249. UIApplication.shared.visibleViewController?.present(dialog, animated: true)
  250. }
  251. }
  252. } catch {
  253. delegate.onFailed(error: "99:Something went wrong")
  254. }
  255. }
  256. NetworkMonitor.shared.startMonitoring()
  257. OutgoingThread.default.run()
  258. InquiryThread.default.run()
  259. if UIFont.systemFont(ofSize: 12).familyName == ".AppleSystemUIFont" {
  260. UIFont.libOverrideInitialize()
  261. }
  262. _ = LocationManager()
  263. FileEncryption.shared.wipeFolderOldSecure()
  264. }
  265. private static var ringtoneID: SystemSoundID = 0
  266. public static func playRingtoneCall() {
  267. var ringtonePath = Bundle.resourceBundle(for: Nexilis.self).url(forResource: "pb_call_in_ios", withExtension: "mp3")
  268. if ringtonePath == nil {
  269. ringtonePath = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: "pb_call_in_ios", withExtension: "mp3")
  270. }
  271. if let a = ringtonePath {
  272. // AudioServicesCreateSystemSoundID(a as CFURL, &ringtoneID)
  273. // AudioServicesPlaySystemSound(ringtoneID)
  274. do {
  275. Nexilis.sharedAudioPlayer = try AVAudioPlayer(contentsOf: a)
  276. Nexilis.sharedAudioPlayer?.prepareToPlay()
  277. Nexilis.sharedAudioPlayer?.numberOfLoops = -1
  278. Nexilis.sharedAudioPlayer?.play()
  279. } catch {
  280. }
  281. }
  282. }
  283. public static func stopRingtoneCall() {
  284. // AudioServicesDisposeSystemSoundID(ringtoneID)
  285. Nexilis.sharedAudioPlayer?.stop()
  286. }
  287. private static var ringBackToneID: SystemSoundID = 0
  288. public static func playRingbacktoneCall() {
  289. var ringbacktonePath = Bundle.resourceBundle(for: Nexilis.self).url(forResource: "pb_call_out_ios", withExtension: "mp3")
  290. if ringbacktonePath == nil {
  291. ringbacktonePath = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: "pb_call_out_ios", withExtension: "mp3")
  292. }
  293. if let a = ringbacktonePath {
  294. // AudioServicesCreateSystemSoundID(a as CFURL, &ringBackToneID)
  295. // AudioServicesPlaySystemSound(ringBackToneID)
  296. do {
  297. Nexilis.sharedAudioPlayer = try AVAudioPlayer(contentsOf: a)
  298. Nexilis.sharedAudioPlayer?.prepareToPlay()
  299. Nexilis.sharedAudioPlayer?.numberOfLoops = -1
  300. Nexilis.sharedAudioPlayer?.play()
  301. } catch {
  302. }
  303. }
  304. }
  305. public static func stopRingbacktoneCall() {
  306. // AudioServicesDisposeSystemSoundID(ringBackToneID)
  307. Nexilis.sharedAudioPlayer?.stop()
  308. }
  309. private static var busyToneID: SystemSoundID = 0
  310. public static func playBusyCall() {
  311. var busyPath = Bundle.resourceBundle(for: Nexilis.self).url(forResource: "pb_call_busy", withExtension: "mp3")
  312. if busyPath == nil {
  313. busyPath = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: "pb_call_busy", withExtension: "mp3")
  314. }
  315. if let a = busyPath {
  316. // AudioServicesCreateSystemSoundID(a as CFURL, &busyToneID)
  317. // AudioServicesPlaySystemSound(busyToneID)
  318. do {
  319. Nexilis.sharedAudioPlayer = try AVAudioPlayer(contentsOf: a)
  320. Nexilis.sharedAudioPlayer?.prepareToPlay()
  321. Nexilis.sharedAudioPlayer?.numberOfLoops = -1
  322. Nexilis.sharedAudioPlayer?.play()
  323. } catch {
  324. }
  325. }
  326. }
  327. public static func stopBusyCall() {
  328. // AudioServicesDisposeSystemSoundID(busyToneID)
  329. Nexilis.sharedAudioPlayer?.stop()
  330. }
  331. public static func addFB(viewController: UIViewController, fromMAB: Bool) {
  332. if let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) {
  333. keyWindow.addSubview(floatingButton)
  334. }
  335. if fromMAB {
  336. var vc = viewController
  337. if viewController is UINavigationController {
  338. vc = (viewController as! UINavigationController).rootViewController!
  339. }
  340. floatingButton.mySettingDelegate = vc as? any SettingMABDelegate
  341. }
  342. }
  343. private static func getPullPrefs() {
  344. DispatchQueue.global().async {
  345. let urlString = Utils.getBEId().isEmpty ? Utils.getDomainOpr() + "nexilis/logics/get_baseurl_new?key=\(Nexilis.sAPIKey)" : Utils.getDomainOpr() + "nexilis/logics/get_prefs?be=\(Utils.getBEId())&appId=\(APIS.getAppNm())"
  346. Utils.fetchDataWithCookiesAndUserAgent(from: URL(string: urlString)!) { data, response, error in
  347. if let data = data, let responseString = String(data: data, encoding: .utf8) {
  348. if let json = try? JSONSerialization.jsonObject(with: responseString.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [String: Any?] {
  349. do {
  350. if Utils.getBEId().isEmpty {
  351. Utils.setBEId(value: "\(json["be_id"] as? Int ?? 0)")
  352. getPullPrefs()
  353. } else {
  354. let dataArray: [[String: Any?]] = [json]
  355. if !dataArray.isEmpty && !Utils.getIsLoadThemeFromOther() {
  356. if let jsonData = try? JSONSerialization.data(withJSONObject: dataArray, options: .prettyPrinted) {
  357. // Convert to JSON String
  358. let jsonString = String(data: jsonData, encoding: .utf8)
  359. Utils.setPrefTheme(value: jsonString ?? "")
  360. Utils.setValueInitialApp(data: jsonString ?? "")
  361. }
  362. }
  363. }
  364. } catch {
  365. }
  366. }
  367. }
  368. }
  369. }
  370. }
  371. private static func getPullGroupNoMember() {
  372. while Nexilis.isProcessWriteSync {
  373. Thread.sleep(forTimeInterval: 0.5)
  374. }
  375. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.pullGroupNoMember(), timeout: 30 * 1000), response.isOk() {
  376. let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
  377. if !data.isEmpty {
  378. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  379. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  380. do {
  381. for json in jsonArray {
  382. let group_id = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.GROUP_ID)
  383. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "GROUP_NM", cvalues: [
  384. "group_id" : group_id,
  385. "f_name" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.GROUP_NAME),
  386. "scope_id" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.MESSAGE_SCOPE_ID),
  387. "image_id": CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.THUMB_ID),
  388. "quote": CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.QUOTE),
  389. "last_update" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LAST_UPDATE),
  390. "created_by" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.CREATED_BY),
  391. "created_date" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.CREATED_DATE),
  392. "ex_block" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.BLOCK),
  393. "folder_id" : "",
  394. "chat_modifier" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.CHAT_MODIFIER),
  395. "group_type" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.IS_ORGANIZATION),
  396. "parent" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.PARENT_ID),
  397. "level" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LEVEL),
  398. "is_open" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.IS_OPEN),
  399. "official" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.OFFICIAL_ACCOUNT),
  400. "level_edu" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LEVEL_EDU),
  401. "materi_edu" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.MATERI_EDU),
  402. "is_education" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.IS_EDUCATION)
  403. ], replace: true)
  404. }
  405. } catch {
  406. rollback.pointee = true
  407. print("Access database error: \(error.localizedDescription)")
  408. }
  409. })
  410. }
  411. }
  412. }
  413. }
  414. private static func getServiceBank() {
  415. DispatchQueue.global().async {
  416. _ = Nexilis.write(message: CoreMessage_TMessageBank.getServiceBank())
  417. }
  418. }
  419. public static func sendStateToServer(s: String) {
  420. DispatchQueue.global().async {
  421. let parameter: [String : Any] = [
  422. "f_pin": User.getMyPin() ?? "",
  423. "state": s
  424. ]
  425. Utils.postDataWithCookiesAndUserAgent(from: URL(string: Utils.getDomainOpr() + "logging")!, parameter: parameter) { data, response, error in
  426. print("\(response)")
  427. }
  428. }
  429. }
  430. private static func getFeatureAccess() {
  431. DispatchQueue.global().async {
  432. Utils.postDataWithCookiesAndUserAgent(from: URL(string: Utils.getDomainOpr() + "get_feature_access_new")!) { data, response, error in
  433. let response = response as? HTTPURLResponse
  434. if response?.statusCode != 200 || error != nil {
  435. return
  436. }
  437. if let data = data, let responseString = String(data: data, encoding: .utf8) {
  438. if let jsonArray = try? JSONSerialization.jsonObject(with: responseString.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  439. do {
  440. var jsonFA: [String: Any] = [:]
  441. for jsonData in jsonArray {
  442. var tmp = jsonData as! [String: Any]
  443. tmp.removeValue(forKey: "action")
  444. tmp.removeValue(forKey: "alert_title")
  445. tmp.removeValue(forKey: "alert_message")
  446. jsonFA[Array(tmp.keys)[0]] = Array(tmp.values)[0]
  447. if jsonData["upload_max_retry"]! != nil {
  448. let umr = jsonData["upload_max_retry"] as! String
  449. Utils.setMaxRetryUpload(value: umr)
  450. jsonFA[Array(tmp.keys)[0]] = Array(tmp.values)[0]
  451. }
  452. if jsonData["upload_max_time"]! != nil {
  453. let umt = jsonData["upload_max_time"] as! String
  454. Utils.setMaxRetryTimeUpload(value: umt)
  455. jsonFA[Array(tmp.keys)[0]] = Array(tmp.values)[0]
  456. }
  457. if jsonData["default_fb"]! != nil {
  458. if !Utils.getAfterConfigFB() {
  459. Utils.setConfigModeFB(value: jsonData["default_fb"] as! String)
  460. }
  461. jsonFA[Array(tmp.keys)[0]] = Array(tmp.values)[0]
  462. }
  463. if jsonData["authentication_duration"]! != nil {
  464. let ad = jsonData["authentication_duration"] as! String
  465. Utils.setAuthenticationDuration(value: ad)
  466. }
  467. if jsonData["secure_folder_encrypt_key"]! != nil {
  468. if let dataKey = Data(base64Encoded: jsonData["secure_folder_encrypt_key"] as! String, options: .ignoreUnknownCharacters) {
  469. FileEncryption.shared.aesKey = SymmetricKey(data: dataKey)
  470. Utils.setSecureFolderEncrypt(value: jsonData["secure_folder_encrypt_key"] as! String)
  471. }
  472. }
  473. if jsonData["secure_folder_encrypt_key_iv"]! != nil {
  474. if let dataKey = Data(base64Encoded: jsonData["secure_folder_encrypt_key_iv"] as! String, options: .ignoreUnknownCharacters) {
  475. FileEncryption.shared.aesIV = dataKey
  476. Utils.setSecureFolderEncryptIv(value: jsonData["secure_folder_encrypt_key_iv"] as! String)
  477. }
  478. }
  479. if jsonData["chatbot_greetings"]! != nil {
  480. if let greeting = jsonData["chatbot_greetings"] as? String {
  481. print("Chatbot greeting: \(greeting)")
  482. Utils.setChatbotGreetings(value: greeting)
  483. }
  484. }
  485. }
  486. if let convertJsonFA = try? JSONSerialization.data(withJSONObject: jsonFA, options: .prettyPrinted) {
  487. if let jsonFAString = String(data: convertJsonFA, encoding: .utf8) {
  488. Utils.setFeatureAccess(value: jsonFAString)
  489. }
  490. }
  491. } catch {
  492. }
  493. }
  494. }
  495. }
  496. }
  497. }
  498. public static func checkingAccess(key: String) -> Bool {
  499. let dataAccess = Utils.getFeatureAccess()
  500. if dataAccess.isEmpty {
  501. if key == "sms" || key == "email" || key == "whatsapp" || key == "battery_optimization_force" || key == "backup_restore" || key == "check_sim_swap" || key == "admin_features" || key == "can_config_fb" || key == "friend_request_approval" {
  502. return false
  503. } else {
  504. return true
  505. }
  506. } else if let jsonArray = try? JSONSerialization.jsonObject(with: dataAccess.data(using: String.Encoding.utf8)!, options: []) as? [String: Any] {
  507. if jsonArray[key] != nil {
  508. return jsonArray[key] as! String == "1"
  509. } else {
  510. if key == "sms" || key == "email" || key == "whatsapp" || key == "battery_optimization_force" || key == "backup_restore" || key == "check_sim_swap" || key == "admin_features" || key == "can_config_fb" || key == "friend_request_approval" {
  511. return false
  512. } else {
  513. return true
  514. }
  515. }
  516. }
  517. return false
  518. }
  519. private static func getPullWorkingArea() {
  520. while Nexilis.isProcessWriteSync {
  521. Thread.sleep(forTimeInterval: 0.5)
  522. }
  523. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getWorkingAreaContactCenter(), timeout: 30 * 1000), response.isOk() {
  524. let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
  525. if !data.isEmpty {
  526. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  527. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  528. do {
  529. for json in jsonArray {
  530. var parent = CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.PARENT_ID)
  531. if parent.isEmpty {
  532. parent = "-99"
  533. }
  534. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "WORKING_AREA", cvalues: [
  535. "area_id" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.WORKING_AREA),
  536. "name" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.NAME),
  537. "parent" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.PARENT_ID),
  538. "level" : CoreMessage_TMessageUtil.getString(json: json, key: CoreMessage_TMessageKey.LEVEL)
  539. ], replace: true)
  540. }
  541. } catch {
  542. rollback.pointee = true
  543. print("Access database error: \(error.localizedDescription)")
  544. }
  545. })
  546. }
  547. }
  548. }
  549. }
  550. public static func showForceSignIn() {
  551. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "changeDevice") as! ChangeDeviceViewController
  552. controller.forceLogin = true
  553. let navigationController = CustomNavigationController(rootViewController: controller)
  554. navigationController.modalPresentationStyle = .fullScreen
  555. navigationController.navigationBar.tintColor = .white
  556. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  557. navigationController.navigationBar.isTranslucent = false
  558. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  559. navigationController.navigationBar.barStyle = .black
  560. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  561. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  562. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  563. navigationController.navigationBar.titleTextAttributes = textAttributes
  564. navigationController.modalPresentationStyle = .fullScreen
  565. navigationController.modalTransitionStyle = .crossDissolve
  566. UIApplication.shared.visibleViewController?.present(navigationController, animated: true)
  567. }
  568. public static func destroyAll() {
  569. let onGoingCC: String = SecureUserDefaults.shared.value(forKey: "onGoingCC") ?? ""
  570. if !onGoingCC.isEmpty {
  571. let requester = onGoingCC.components(separatedBy: ",")[0]
  572. let officer = onGoingCC.isEmpty ? "" : onGoingCC.components(separatedBy: ",")[1]
  573. let complaintId = onGoingCC.isEmpty ? "" : onGoingCC.components(separatedBy: ",")[2]
  574. let idMe = User.getMyPin()!
  575. let startTimeCC: String = SecureUserDefaults.shared.value(forKey: "startTimeCC") ?? ""
  576. let date = "\(Date().currentTimeMillis())"
  577. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  578. do {
  579. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "CALL_CENTER_HISTORY", cvalues: [
  580. "type" : "0",
  581. "title" : "Contact Center".localized(),
  582. "time" : startTimeCC,
  583. "f_pin" : officer,
  584. "data" : complaintId,
  585. "time_end" : date,
  586. "complaint_id" : complaintId,
  587. "members" : "",
  588. "requester": requester
  589. ], replace: true)
  590. } catch {
  591. rollback.pointee = true
  592. print("Access database error: \(error.localizedDescription)")
  593. }
  594. })
  595. if officer == idMe {
  596. _ = Nexilis.write(message: CoreMessage_TMessageBank.endCallCenter(complaint_id: complaintId, l_pin: requester))
  597. } else {
  598. if requester == idMe {
  599. _ = Nexilis.write(message: CoreMessage_TMessageBank.endCallCenter(complaint_id: complaintId, l_pin: officer))
  600. } else {
  601. _ = Nexilis.write(message: CoreMessage_TMessageBank.leaveCCRoomInvite(ticket_id: complaintId))
  602. }
  603. }
  604. SecureUserDefaults.shared.removeValue(forKey: "onGoingCC")
  605. SecureUserDefaults.shared.removeValue(forKey: "membersCC")
  606. SecureUserDefaults.shared.removeValue(forKey: "startTimeCC")
  607. DispatchQueue.main.async {
  608. if UIApplication.shared.applicationState == .active {
  609. let imageView = UIImageView(image: UIImage(systemName: "info.circle"))
  610. imageView.tintColor = .white
  611. 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)
  612. banner.show()
  613. }
  614. }
  615. }
  616. if !Nexilis.onGoingPushCC.isEmpty {
  617. DispatchQueue.global().async {
  618. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: Nexilis.onGoingPushCC["channel"]!, l_pin: Nexilis.onGoingPushCC["l_pin"]!))
  619. }
  620. }
  621. SecureUserDefaults.shared.removeValue(forKey: "inEditorPersonal")
  622. SecureUserDefaults.shared.removeValue(forKey: "inEditorGroup")
  623. SecureUserDefaults.shared.removeValue(forKey: "waitingRequestCC")
  624. }
  625. // public static func changeUser(f_pin: String){
  626. // do {
  627. // //print("change user to fpin")
  628. // Nexilis.dispatch = DispatchGroup()
  629. // Nexilis.dispatch?.enter()
  630. //
  631. // try API.switchUser(cbiI: Callback(), sUserID: f_pin)
  632. //
  633. // // wait until connection true
  634. // Nexilis.dispatch?.wait()
  635. // Nexilis.dispatch = nil
  636. // //print("success change user to fpin")
  637. //// _ = Nexilis.write(message: CoreMessage_TMessageBank.getChangeConnectionID(p_pin: f_pin))
  638. // } catch{
  639. // //print(error)
  640. // }
  641. // }
  642. public static func apiSendChat(destination: String, message: String, isGroup: Bool, thumbnailName: String = "", imageName: String = "", videoName: String = "", fileName: String = "", audioName: String = "", replyMessageId : String = "") -> String {
  643. let message = CoreMessage_TMessageBank.sendMessage(l_pin: destination, message_scope_id: isGroup ? MessageScope.GROUP : MessageScope.WHISPER, 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() ?? "")
  644. addQueueMessage(message: message)
  645. return message.getBody(key: CoreMessage_TMessageKey.MESSAGE_ID)
  646. }
  647. public static func apiInitiateAudioCall(destination: String) {
  648. API.initiateCCall(sParty: destination)
  649. }
  650. public static func apiReceiveAudioCall(destination: String) {
  651. API.receiveCCall(sParty: destination)
  652. }
  653. public static func apiInitiateVideoCall(destination: String, backCamera: Bool = false, listRemoteViews: [UIImageView], localView: UIImageView, remoteViewSpeaker: UIImageView) {
  654. API.initiateCCall(sParty: destination, nCamIdx: backCamera ? 0 : 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViews, ivLocalView: localView, ivRemoteZ: remoteViewSpeaker)
  655. }
  656. public static func apiReceiveVideoCall(destination: String, backCamera: Bool = false, listRemoteViews: [UIImageView], localView: UIImageView, remoteViewSpeaker: UIImageView) {
  657. API.receiveCCall(sParty: destination, nCamIdx: backCamera ? 0 : 1, nResIdx: 2, nVQuality: 4, ivRemoteView: listRemoteViews, ivLocalView: localView, ivRemoteZ: remoteViewSpeaker)
  658. }
  659. public static func apiInitiateStreaming(localView: UIImageView, titleStream: String = "", backCamera: Bool = false) {
  660. API.initiateBC(sTitle: titleStream, nCamIdx: backCamera ? 0 : 1, nResIdx: 2, nVQuality: 4, ivLocalView: localView)
  661. }
  662. public static func apiJoinStreaming(streamerId: String, remoteView: UIImageView) {
  663. API.joinBC(sBroadcasterID: streamerId, ivRemoteView: remoteView)
  664. }
  665. public static func apiTerminateStreaming(streamerId: String?) {
  666. API.terminateBC(sBroadcasterID: streamerId)
  667. }
  668. public static func apiEndAllCall() {
  669. API.terminateCall(sParty: nil)
  670. }
  671. public static func addQueueMessage(message: TMessage, isEditMessage: Bool = false) {
  672. // OutgoingThread.default.addQueue(message: message)
  673. if isEditMessage {
  674. OutgoingThread.default.addQueue(message: message)
  675. } else {
  676. InquiryThread.default.addQueue(message: message)
  677. }
  678. }
  679. public static func deleteQueueMessage(message: TMessage) {
  680. OutgoingThread.default.addQueue(message: message)
  681. }
  682. private static var wbDelegate: WhiteboardDelegate?
  683. private static var wbReceiver: WhiteboardReceiver?
  684. public static func setWhiteboardDelegate(delegate: WhiteboardDelegate?){
  685. Nexilis.wbDelegate = delegate
  686. }
  687. public static func getWhiteboardDelegate() -> WhiteboardDelegate? {
  688. return Nexilis.wbDelegate
  689. }
  690. public static func setWhiteboardReceiver(receiver: WhiteboardReceiver?){
  691. Nexilis.wbReceiver = receiver
  692. }
  693. public static func getWhiteboardReceiver() -> WhiteboardReceiver? {
  694. return Nexilis.wbReceiver
  695. }
  696. public static func getEditorPersonal() -> EditorPersonal {
  697. return AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  698. }
  699. public static func getEditorGroup() -> EditorGroup {
  700. return AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
  701. }
  702. public static func getEditorStarMessage() -> EditorStarMessages {
  703. return AppStoryBoard.Palio.instance.instantiateViewController(identifier: "staredVC") as! EditorStarMessages
  704. }
  705. static func getAddress(apiKey: String) -> [String] {
  706. var result = [String]()
  707. let url = URL(string: "https://nexilis.io/dipp/NuN1v3rs3/Qm3r4i0/get_ip?account=\(apiKey)")!
  708. let urlConfig = URLSessionConfiguration.default
  709. let sessionDelegate = SelfSignedURLSessionDelegate()
  710. urlConfig.requestCachePolicy = .returnCacheDataElseLoad
  711. urlConfig.timeoutIntervalForRequest = 10.0
  712. urlConfig.timeoutIntervalForResource = 10.0
  713. let semaphore = DispatchSemaphore(value: 0)
  714. let task = URLSession(configuration: urlConfig, delegate: sessionDelegate, delegateQueue: nil).dataTask(with: url) {(data, response, error) in
  715. guard let data = data else {
  716. semaphore.signal()
  717. return
  718. }
  719. let html = String(data: data, encoding: .utf8)!
  720. let base64Address = html.components(separatedBy: "<body>")[1].components(separatedBy: "</body>")[0].trimmingCharacters(in: .whitespacesAndNewlines)
  721. if let addressData = Data(base64Encoded: base64Address), let decodeAddress = String(data: addressData, encoding: .utf8) {
  722. let rows = decodeAddress.trimmingCharacters(in: CharacterSet.newlines).split(separator: ",")
  723. for r in rows {
  724. let _address = r.split(separator: ":")
  725. var ip:String = ""
  726. let _data = _address[0].split(separator: ".", maxSplits: 4, omittingEmptySubsequences: false)
  727. ip.append(String(_data[3]))
  728. ip.append(".")
  729. ip.append(String(_data[1]))
  730. ip.append(".")
  731. ip.append(String(_data[0]))
  732. ip.append(".")
  733. ip.append(String(_data[2]))
  734. result.append(ip + ":" + _address[2])
  735. }
  736. }
  737. semaphore.signal()
  738. }
  739. task.resume()
  740. _ = semaphore.wait(timeout: .distantFuture)
  741. //print("[App] getAddress:", result)
  742. return result
  743. }
  744. static func getAddressNew(apiKey: String) -> String {
  745. var result = ""
  746. if !Utils.getHarcodedIp().isEmpty {
  747. result = Utils.getHarcodedIp()
  748. return result
  749. }
  750. let url = URL(string: "\(Utils.getDomainOpr())dipp/NuN1v3rs3/Qm3r4i0/get_ip_domain?account=\(apiKey)")!
  751. let urlConfig = URLSessionConfiguration.default
  752. let sessionDelegate = SelfSignedURLSessionDelegate()
  753. urlConfig.requestCachePolicy = .returnCacheDataElseLoad
  754. urlConfig.timeoutIntervalForRequest = 10.0
  755. urlConfig.timeoutIntervalForResource = 10.0
  756. let semaphore = DispatchSemaphore(value: 0)
  757. let task = URLSession(configuration: urlConfig, delegate: sessionDelegate, delegateQueue: nil).dataTask(with: url) {(data, response, error) in
  758. guard let data = data,
  759. let url = response?.url,
  760. let httpResponse = response as? HTTPURLResponse,
  761. let fields = httpResponse.allHeaderFields as? [String: String] else {
  762. print("MASUK SINI0 \(url)")
  763. semaphore.signal()
  764. return
  765. }
  766. let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: url)
  767. //print("MASUK SINI1 \(cookies)")
  768. Utils.setCookiesMobileForStorage(value: convertCookiesToJSONString(cookies: cookies) ?? "")
  769. HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL: nil)
  770. if let cookieHeader = HTTPCookie.requestHeaderFields(with: cookies)["Cookie"] {
  771. Utils.setCookiesMobile(value: cookieHeader.replacingOccurrences(of: "; ", with: ";"))
  772. }
  773. let dataEncode = String(data: data, encoding: .utf8)!
  774. // print("dataEncode \(dataEncode.trimmingCharacters(in: .whitespacesAndNewlines))")
  775. // //print("decrypt \(Utils.decrypt(str: "4=sm<wmpm1ir==>wtxxl"))")
  776. if !dataEncode.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
  777. let dataDecodeBase64 = String(data: Data(base64Encoded: dataEncode)!, encoding: .utf8)!
  778. let dataRealDecode = Utils.decrypt(str: dataDecodeBase64)
  779. // print("dataRealDecode \(dataRealDecode)")
  780. do {
  781. if let jsonData = dataRealDecode.data(using: .utf8), let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
  782. var newDomain = jsonObject["domain"] as! String
  783. let jsonAddress = jsonObject["address"] as! [[String: Any]]
  784. let newIp = jsonAddress[0]["ip"] as! String
  785. let newPort = jsonAddress[0]["portI"] as! String
  786. if newDomain.substring(from: newDomain.count-1, to: nil) != "/" {
  787. newDomain += "/"
  788. }
  789. if (newIp+":"+newPort) != Utils.getIpOpr() || newDomain != Utils.getDomainOpr() {
  790. //check new domain
  791. if checkNewDomain(newDomain) {
  792. Utils.setDomainOpr(value: newDomain)
  793. Utils.setIpPortOpr(value: (newIp+":"+newPort))
  794. }
  795. }
  796. }
  797. } catch {
  798. }
  799. }
  800. semaphore.signal()
  801. }
  802. task.resume()
  803. _ = semaphore.wait(timeout: .distantFuture)
  804. result = Utils.getIpOpr()
  805. if HTTPCookieStorage.shared.cookies(for: URL(string: Utils.getDomainOpr())!)!.count == 0 && !Utils.getCookiesMobileForStorage().isEmpty {
  806. HTTPCookieStorage.shared.setCookies(convertJSONStringToCookies(jsonString: Utils.getCookiesMobileForStorage()), for: url, mainDocumentURL: nil)
  807. }
  808. // print("[App] getAddress:", result)
  809. return result
  810. }
  811. private static func convertCookiesToJSONString(cookies: [HTTPCookie]) -> String? {
  812. let cookiesArray = cookies.map { cookie -> [String: Any] in
  813. return [
  814. "name": cookie.name,
  815. "value": cookie.value,
  816. "domain": cookie.domain,
  817. "path": cookie.path,
  818. "expiresDate": cookie.expiresDate?.timeIntervalSince1970 ?? NSNull(),
  819. "isSecure": cookie.isSecure,
  820. "isHTTPOnly": cookie.isHTTPOnly
  821. ]
  822. }
  823. if let jsonData = try? JSONSerialization.data(withJSONObject: cookiesArray, options: .prettyPrinted) {
  824. return String(data: jsonData, encoding: .utf8)
  825. }
  826. return nil
  827. }
  828. private static func convertJSONStringToCookies(jsonString: String) -> [HTTPCookie] {
  829. guard let jsonData = jsonString.data(using: .utf8),
  830. let jsonArray = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [[String: Any]] else {
  831. return []
  832. }
  833. var cookies: [HTTPCookie] = []
  834. for cookieDict in jsonArray {
  835. var properties: [HTTPCookiePropertyKey: Any] = [
  836. .name: cookieDict["name"] as? String ?? "",
  837. .value: cookieDict["value"] as? String ?? "",
  838. .domain: cookieDict["domain"] as? String ?? "",
  839. .path: cookieDict["path"] as? String ?? "/",
  840. .secure: cookieDict["isSecure"] as? Bool ?? false
  841. ]
  842. if let expiresTimeInterval = cookieDict["expiresDate"] as? TimeInterval {
  843. properties[.expires] = Date(timeIntervalSince1970: expiresTimeInterval)
  844. }
  845. if let cookie = HTTPCookie(properties: properties) {
  846. cookies.append(cookie)
  847. }
  848. }
  849. return cookies
  850. }
  851. private static func checkNewDomain(_ newDomain: String) -> Bool {
  852. var result = false
  853. let url = URL(string: "\(newDomain)dipp/NuN1v3rs3/Qm3r4i0/get_ip_domain?account=\(Nexilis.sAPIKey)")!
  854. let urlConfig = URLSessionConfiguration.default
  855. let sessionDelegate = SelfSignedURLSessionDelegate()
  856. urlConfig.requestCachePolicy = .returnCacheDataElseLoad
  857. urlConfig.timeoutIntervalForRequest = 10.0
  858. urlConfig.timeoutIntervalForResource = 10.0
  859. let semaphore = DispatchSemaphore(value: 0)
  860. let task = URLSession(configuration: urlConfig, delegate: sessionDelegate, delegateQueue: nil).dataTask(with: url) {(data, response, error) in
  861. if let httpResponse = response as? HTTPURLResponse {
  862. if httpResponse.statusCode == 200 {
  863. guard let url = response?.url,
  864. let fields = httpResponse.allHeaderFields as? [String: String] else {
  865. semaphore.signal()
  866. return
  867. }
  868. let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: url)
  869. HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL: nil)
  870. Utils.setCookiesMobileForStorage(value: convertCookiesToJSONString(cookies: cookies) ?? "")
  871. if let cookieHeader = HTTPCookie.requestHeaderFields(with: cookies)["Cookie"] {
  872. Utils.setCookiesMobile(value: cookieHeader.replacingOccurrences(of: "; ", with: ";"))
  873. }
  874. result = true
  875. }
  876. }
  877. semaphore.signal()
  878. }
  879. task.resume()
  880. _ = semaphore.wait(timeout: .distantFuture)
  881. return result
  882. }
  883. static func getCLMUserId() -> String {
  884. guard let me = User.getMyPin() else {
  885. return ""
  886. }
  887. return me
  888. }
  889. public static var isProcessWriteSync = false
  890. public static func writeSync(message: TMessage, timeout: Int = 15 * 1000) -> TMessage? {
  891. isProcessWriteSync = true
  892. do {
  893. // print(">> SENDING MESSAGE >> ", message.toLogString())
  894. if let data = try API.sGetResponse(sRequest: message.pack(), lTimeout: timeout, bKeepTOResp: true) {
  895. let response = TMessage(data: data)
  896. // print(">> RESPONSE WRITESYNC >> ")
  897. // print("<< RESPONSE MESSAGE << ", response.toLogString())
  898. isProcessWriteSync = false
  899. return response
  900. }
  901. } catch {
  902. //print(error)
  903. }
  904. return nil
  905. }
  906. public static func write(message: TMessage, timeout: Int = 15 * 1000) -> String? {
  907. do {
  908. if API.nGetCLXConnState() == 0 {
  909. return nil
  910. }
  911. //print(">> SENDING MESSAGE >> ", message.toLogString())
  912. if message.getMedia().count == 0 {
  913. if let data = try API.sSend(sData: message.pack(), nPriority: 1, lTimeout: timeout) {
  914. //print("<< RESPONSE MESSAGE << ", data)
  915. return data
  916. }
  917. }
  918. // media
  919. if let data = try API.sSend(abData: message.toBytes(), nPriority: 2, lTimeout: timeout) {
  920. //print("<< RESPONSE MESSAGE << ", data)
  921. return data
  922. }
  923. } catch {
  924. //print(error)
  925. }
  926. return nil
  927. }
  928. public static func writeDraw(data: String, timeout: Int = 15 * 1000) -> String? {
  929. do {
  930. if !API.bInetConnAvailable() {
  931. return nil
  932. }
  933. //print(">> SENDING MESSAGE >> ", data)
  934. if let data = try API.sSend(sData: data, nPriority: 1, lTimeout: timeout) {
  935. //print("<< RESPONSE MESSAGE << ", data)
  936. return data
  937. }
  938. } catch {
  939. //print(error)
  940. }
  941. return nil
  942. }
  943. public static func response(packetId: String, message: TMessage, timeout: Int = 15 * 1000) -> String? {
  944. var result: String? = nil
  945. do {
  946. if !API.bInetConnAvailable() {
  947. return nil
  948. }
  949. //print(">> RESPONSE >> " + packetId + " " + message.toLogString());
  950. result = try API.sSendResponse(sRequestID: packetId, sResponse: message.pack(), lTimeout: timeout)
  951. } catch {
  952. //print(error)
  953. }
  954. return result
  955. }
  956. public static func responseString(packetId: String, message: String, timeout: Int = 15 * 1000) -> String? {
  957. var result: String? = nil
  958. do {
  959. if !API.bInetConnAvailable() {
  960. return nil
  961. }
  962. //print(">> RESPONSE >> " + packetId + " " + message);
  963. result = try API.sSendResponse(sRequestID: packetId, sResponse: message, lTimeout: timeout)
  964. } catch {
  965. //print(error)
  966. }
  967. return result
  968. }
  969. public static func setSpeaker(_ isEnabled: Bool, isVideo: Bool = false) {
  970. do {
  971. API.adjustVolume(fValue: isEnabled ? 10.0: isVideo ? 0.0 : 3.0)
  972. } catch {
  973. }
  974. }
  975. public static func buttonClicked(index: Int, id: String = "") {
  976. //print("BTNCLICK \(index) \(id)")
  977. if index == IDX_QUEUE_SYSTEM || index == IDX_NEWS || index == IDX_SOCIAL_COMMERCE {
  978. if id == "fb\(index)"{
  979. APIS.openUrl(url: "https://google.com/")
  980. } else {
  981. APIS.openUrl(url: id)
  982. }
  983. } else if index == IDX_NOTIF_CENTER {
  984. APIS.openNotificationCenter()
  985. } else if index == IDX_CHAT {
  986. APIS.openChat()
  987. } else if index == IDX_CALL {
  988. APIS.openCall()
  989. } else if index == IDX_STREAM {
  990. APIS.openStreaming()
  991. } else if index == IDX_CC {
  992. APIS.openContactCenter()
  993. } else if index == IDX_ADDFRIEND {
  994. APIS.openAddFriend()
  995. } else if index == IDX_WB_SS {
  996. APIS.openWhiteboardAndScreenSharing()
  997. } else if index == IDX_WHITEBOARD {
  998. APIS.openWhiteboard()
  999. } else if index == IDX_SCREENSHARING {
  1000. APIS.openWhiteboardAndScreenSharing()
  1001. } else if index == IDX_POST {
  1002. } else if index == IDX_CONVERSATION {
  1003. APIS.openConversation()
  1004. } else if index == IDX_FAVORITEMESSAGE {
  1005. APIS.openFavoriteMessage()
  1006. } else if index == IDX_SECURE_FOLDER {
  1007. APIS.openSecureFolder()
  1008. } else if index == IDX_SECURE_BROWSER {
  1009. APIS.openSecureBrowser()
  1010. } else if index == IDX_CONFERENCE_ROOM_FORM {
  1011. APIS.openConference()
  1012. } else if index == IDX_SETTING {
  1013. if Nexilis.floatingButton.mySettingDelegate != nil {
  1014. Nexilis.floatingButton.mySettingDelegate?.settingDelegate()
  1015. } else {
  1016. APIS.openSetting()
  1017. }
  1018. } else if index == IDX_SELF_ACT {
  1019. openApp(id: id)
  1020. }
  1021. }
  1022. public static func openApp(id: String) {
  1023. //print("openApp itms-apps://apple.com/app/\(id)")
  1024. let isChangeProfile = Utils.getSetProfile()
  1025. if !isChangeProfile {
  1026. let alert = LibAlertController(title: "Set Profile".localized(), message: "You must set your profile to use this feature".localized(), preferredStyle: .alert)
  1027. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  1028. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  1029. controller.forceLogin = true
  1030. let navigationController = CustomNavigationController(rootViewController: controller)
  1031. navigationController.modalPresentationStyle = .fullScreen
  1032. navigationController.navigationBar.tintColor = .white
  1033. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  1034. navigationController.navigationBar.isTranslucent = false
  1035. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  1036. navigationController.navigationBar.barStyle = .black
  1037. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  1038. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  1039. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  1040. navigationController.navigationBar.titleTextAttributes = textAttributes
  1041. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1042. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  1043. } else {
  1044. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  1045. }
  1046. }))
  1047. if UIApplication.shared.visibleViewController?.navigationController != nil {
  1048. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  1049. } else {
  1050. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  1051. }
  1052. return
  1053. }
  1054. if id == nil {
  1055. return
  1056. }
  1057. if let url = URL(string: "itms-apps://apple.com/app/\(id)") {
  1058. UIApplication.shared.open(url)
  1059. }
  1060. }
  1061. static func openmailAction(subject: String = "", body: String = "", to: String = "") {
  1062. let subjectEncoded = subject.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
  1063. let bodyEncoded = body.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
  1064. let toEmail = to
  1065. let gmailUrl = URL(string: "googlegmail://co?to=\(toEmail)&subject=\(subjectEncoded)&body=\(bodyEncoded)")!
  1066. let outlookUrl = URL(string: "ms-outlook://compose?to=\(toEmail)&subject=\(subjectEncoded)&body=\(bodyEncoded)")!
  1067. let yahooMail = URL(string: "ymail://mail/compose?to=\(toEmail)&subject=\(subjectEncoded)&body=\(bodyEncoded)")!
  1068. let sparkUrl = URL(string: "readdle-spark://compose?recipient=\(toEmail)&subject=\(subjectEncoded)&body=\(bodyEncoded)")!
  1069. let defaultUrl = URL(string: "mailto:\(toEmail)?subject=\(subjectEncoded)&body=\(bodyEncoded)")!
  1070. if UIApplication.shared.canOpenURL(gmailUrl as URL) {
  1071. openMail(gmailUrl)
  1072. } else if UIApplication.shared.canOpenURL(outlookUrl as URL) {
  1073. openMail(outlookUrl)
  1074. } else if UIApplication.shared.canOpenURL(yahooMail as URL) {
  1075. openMail(yahooMail)
  1076. } else if UIApplication.shared.canOpenURL(sparkUrl as URL) {
  1077. openMail(sparkUrl)
  1078. } else if UIApplication.shared.canOpenURL(defaultUrl as URL) {
  1079. openMail(defaultUrl)
  1080. }
  1081. }
  1082. private static func openMail(_ url: URL) {
  1083. UIApplication.shared.open(url as URL, options: [:], completionHandler: nil)
  1084. }
  1085. static var alertChangeProfile = LibAlertController()
  1086. public static func checkIsChangePerson() -> Bool {
  1087. let isChangeProfile = Utils.getSetProfile()
  1088. if !isChangeProfile {
  1089. alertChangeProfile.dismiss(animated: false)
  1090. alertChangeProfile = LibAlertController(title: "Set Profile".localized(), message: "You must set your profile to use this feature".localized(), preferredStyle: .alert)
  1091. alertChangeProfile.addAction(UIAlertAction(title: "Cancel".localized(), style: .destructive, handler: nil))
  1092. alertChangeProfile.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  1093. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  1094. controller.forceLogin = true
  1095. let navigationController = CustomNavigationController(rootViewController: controller)
  1096. navigationController.modalPresentationStyle = .fullScreen
  1097. navigationController.navigationBar.tintColor = .white
  1098. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  1099. navigationController.navigationBar.isTranslucent = false
  1100. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  1101. navigationController.navigationBar.barStyle = .black
  1102. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  1103. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  1104. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  1105. navigationController.navigationBar.titleTextAttributes = textAttributes
  1106. let rootVC = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController
  1107. if rootVC?.presentedViewController == nil {
  1108. rootVC?.present(navigationController, animated: true, completion: nil)
  1109. } else {
  1110. rootVC?.presentedViewController?.present(navigationController, animated: true, completion: nil)
  1111. }
  1112. }))
  1113. let rootVC = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController
  1114. if rootVC?.presentedViewController == nil {
  1115. rootVC?.present(alertChangeProfile, animated: true, completion: nil)
  1116. } else {
  1117. rootVC?.presentedViewController?.present(alertChangeProfile, animated: true, completion: nil)
  1118. }
  1119. return false
  1120. }
  1121. return true
  1122. }
  1123. public static func showLoader() {
  1124. loadingAlert = LibAlertController(title: nil, message: "Please wait...".localized(), preferredStyle: .alert)
  1125. let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
  1126. loadingIndicator.hidesWhenStopped = true
  1127. loadingIndicator.style = .medium
  1128. loadingIndicator.startAnimating()
  1129. loadingAlert.view.addSubview(loadingIndicator)
  1130. UIApplication.shared.visibleViewController?.present(loadingAlert, animated: true, completion: nil)
  1131. }
  1132. public static func hideLoader(completion: @escaping () -> ()) {
  1133. loadingAlert.dismiss(animated: true, completion: completion)
  1134. }
  1135. private static var groupWait = DispatchGroup()
  1136. private static var waitQueue = [String: TMessage]()
  1137. private static var onDispatchGroupLeave = ""
  1138. public static func writeAndWait(message: TMessage, timeout: Int = 15 * 1000) -> TMessage? {
  1139. groupWait.enter()
  1140. _ = write(message: message, timeout: timeout)
  1141. waitQueue[message.getStatus()] = message
  1142. if groupWait.wait(timeout: .now() + 15) == .timedOut {
  1143. waitQueue.removeValue(forKey: message.getStatus())
  1144. groupWait.leave()
  1145. return nil
  1146. }
  1147. return waitQueue.removeValue(forKey: message.getStatus())
  1148. }
  1149. static func incomingData(packetId: String, data: AnyObject) {
  1150. let message = TMessage()
  1151. if data is String {
  1152. let d = data as! String
  1153. guard message.unpack(data: d) else {
  1154. //print("UNKNOWN DATA STRING...", data)
  1155. if(data.hasPrefix("WB")){
  1156. let dataWB = data.components(separatedBy: "/")
  1157. if(dataWB[1] == "1"){
  1158. let x = dataWB[2]
  1159. let y = dataWB[3]
  1160. let w = dataWB[4]
  1161. let h = dataWB[5]
  1162. let fc = dataWB[6]
  1163. let sw = dataWB[7]
  1164. let xo = dataWB[8]
  1165. let yo = dataWB[9]
  1166. if(Nexilis.getWhiteboardDelegate() != nil){
  1167. Nexilis.getWhiteboardDelegate()!.draw(x: x, y: y, w: w, h: h, fc: fc, sw: sw, xo: xo, yo: yo, data: "")
  1168. }
  1169. } else if(dataWB[1] == "3") {
  1170. if(Nexilis.getWhiteboardDelegate() != nil){
  1171. Nexilis.getWhiteboardDelegate()!.clear()
  1172. }
  1173. } else if(dataWB[1] == "2"){
  1174. if(Nexilis.getWhiteboardReceiver() != nil){
  1175. Nexilis.getWhiteboardReceiver()!.incomingWB(roomId: dataWB[2])
  1176. }
  1177. } else if(dataWB[1] == "22"){
  1178. } else if(dataWB[1] == "88"){
  1179. if(Nexilis.getWhiteboardReceiver() != nil){
  1180. Nexilis.getWhiteboardReceiver()!.cancel(roomId: dataWB[2])
  1181. }
  1182. }
  1183. }
  1184. return
  1185. }
  1186. } else if data is [UInt8] {
  1187. let d = data as! [UInt8]
  1188. guard message.unpack(bytes_data: d) else {
  1189. //print("UNKNOWN DATA BYTES...", data)
  1190. return
  1191. }
  1192. }
  1193. message.mBodies[CoreMessage_TMessageKey.PACKET_ID] = packetId
  1194. if let _ = waitQueue[message.getStatus()] {
  1195. //print("MESSAGE INCOMING DATA \(message.toLogString())")
  1196. if message.mBodies.keys.contains(CoreMessage_TMessageKey.ERRCOD) {
  1197. if onDispatchGroupLeave != message.getStatus() {
  1198. onDispatchGroupLeave = message.getStatus()
  1199. //print("LEAVE GROUP INCOMING DATA")
  1200. waitQueue[message.getStatus()] = message
  1201. groupWait.leave()
  1202. return
  1203. }
  1204. }
  1205. }
  1206. IncomingThread.default.addQueue(message: message)
  1207. }
  1208. static func saveMessage(message: TMessage, withStatus: Bool = true, fromAPNS: Bool = false) {
  1209. // print("save message \(message.toLogString())")
  1210. guard let me = User.getMyPin() else {
  1211. return
  1212. }
  1213. let message_id = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_ID, default_value : "")
  1214. guard !message_id.isEmpty else {
  1215. if message.getBody(key: CoreMessage_TMessageKey.ATTACHMENT_FLAG) == "61" {
  1216. let nameReq = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_TEXT)
  1217. let nameFpin = message.getBody(key: CoreMessage_TMessageKey.F_PIN)
  1218. var messageExist = false
  1219. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1220. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where attachment_flag = '61' and blog_id = '\(nameFpin)'"), cursor.next() {
  1221. messageExist = true
  1222. cursor.close()
  1223. }
  1224. })
  1225. if !messageExist {
  1226. Nexilis.saveMessageBot(textMessage: "*\(nameReq.trimmingCharacters(in: .whitespaces))*" + " " + "has requested to be your friend", blog_id: nameFpin, attachment_type: "61")
  1227. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
  1228. }
  1229. }
  1230. return
  1231. }
  1232. let f_pin = message.getBody(key : CoreMessage_TMessageKey.F_PIN, default_value : "")
  1233. guard !f_pin.isEmpty else {
  1234. return
  1235. }
  1236. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1237. do {
  1238. var messageExist = false
  1239. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select message_id from MESSAGE where message_id = '\(message_id)'"), cursor.next() {
  1240. messageExist = true
  1241. cursor.close()
  1242. }
  1243. let l_pin = message.getBody(key : CoreMessage_TMessageKey.L_PIN, default_value : "")
  1244. let scope = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_SCOPE_ID, default_value : MessageScope.WHISPER)
  1245. let status = message.getBody(key : CoreMessage_TMessageKey.STATUS, default_value : "")
  1246. let chat_id = message.getBody(key : CoreMessage_TMessageKey.CHAT_ID, default_value : "")
  1247. let broadcast_flag = message.getBody(key: CoreMessage_TMessageKey.BROADCAST_FLAG, default_value: "0")
  1248. let is_call_center = message.getBody(key: CoreMessage_TMessageKey.IS_CALL_CENTER, default_value: "0")
  1249. let call_center_id = message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID, default_value: "")
  1250. let last_edited = message.getBodyAsLong(key: CoreMessage_TMessageKey.LAST_EDIT, default_value: 0)
  1251. let is_secret = message.getBodyAsLong(key: CoreMessage_TMessageKey.IS_SECRET, default_value: 0)
  1252. let is_delete_retention = message.getBodyAsLong(key: CoreMessage_TMessageKey.IS_DELETED_RETENTION, default_value: 0)
  1253. let is_forwarded_message = message.getBodyAsLong(key: CoreMessage_TMessageKey.IS_FORWARDED_MESSAGE, default_value: 0)
  1254. let opposite_pin = message.getBody(key: CoreMessage_TMessageKey.OPPOSITE_PIN, default_value: "")
  1255. //print("prepare save db")
  1256. do {
  1257. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
  1258. "message_id" : message_id,
  1259. "f_pin" : f_pin,
  1260. "f_display_name" : message.getBody(key : CoreMessage_TMessageKey.F_DISPLAY_NAME, default_value : ""),
  1261. "l_pin" : l_pin,
  1262. "l_user_id" : message.getBody(key : CoreMessage_TMessageKey.L_USER_ID, default_value : ""),
  1263. "message_scope_id" : scope,
  1264. "server_date" : message.getBody(key: CoreMessage_TMessageKey.SERVER_DATE, default_value : String(Date().currentTimeMillis())),
  1265. "status" : status,
  1266. "message_text" : message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString(),
  1267. "audio_id" : message.getBody(key : CoreMessage_TMessageKey.AUDIO_ID, default_value : ""),
  1268. "video_id" : message.getBody(key : CoreMessage_TMessageKey.VIDEO_ID, default_value : ""),
  1269. "image_id" : message.getBody(key : CoreMessage_TMessageKey.IMAGE_ID, default_value : ""),
  1270. "file_id" : message.getBody(key : CoreMessage_TMessageKey.FILE_ID, default_value : ""),
  1271. "gif_id" : message.getBody(key : CoreMessage_TMessageKey.GIF_ID, default_value : ""),
  1272. "thumb_id" : message.getBody(key : CoreMessage_TMessageKey.THUMB_ID, default_value : ""),
  1273. "opposite_pin" : message.getBody(key : CoreMessage_TMessageKey.OPPOSITE_PIN, default_value : ""),
  1274. "format" : message.getBody(key : CoreMessage_TMessageKey.FORMAT, default_value : ""),
  1275. "blog_id" : message.getBody(key : CoreMessage_TMessageKey.BLOG_ID, default_value : ""),
  1276. "read_receipts" : message.getBody(key: CoreMessage_TMessageKey.READ_RECEIPTS, default_value: "0"),
  1277. "chat_id" : chat_id,
  1278. "account_type" : message.getBody(key : CoreMessage_TMessageKey.BUSINESS_CATEGORY, default_value : "1"),
  1279. "credential" : message.getBody(key : CoreMessage_TMessageKey.CREDENTIAL, default_value : ""),
  1280. "reff_id" : message.getBody(key : CoreMessage_TMessageKey.REF_ID, default_value : ""),
  1281. "message_large_text" : message.getBody(key : CoreMessage_TMessageKey.BODY, default_value : "").toNormalString(),
  1282. "attachment_flag" : message.getBody(key: CoreMessage_TMessageKey.ATTACHMENT_FLAG, default_value: "0"),
  1283. "local_timestamp" : message.getBody(key: CoreMessage_TMessageKey.LOCAL_TIMESTAMP, default_value : String(Date().currentTimeMillis())),
  1284. "broadcast_flag" : broadcast_flag,
  1285. "is_call_center" : is_call_center,
  1286. "call_center_id" : call_center_id,
  1287. "last_edited" : last_edited,
  1288. "is_secret" : is_secret,
  1289. "is_deleted_retention" : is_delete_retention,
  1290. "is_forwarded_message" : is_forwarded_message
  1291. ], replace: true)
  1292. } catch {
  1293. rollback.pointee = true
  1294. //print(error)
  1295. }
  1296. if withStatus {
  1297. do {
  1298. if scope == MessageScope.GROUP {
  1299. for pin in getGroupMembers(fmdb: fmdb, l_pin: l_pin) {
  1300. if f_pin == pin { continue }
  1301. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1302. "message_id" : message_id,
  1303. "status" : status,
  1304. "f_pin" : pin,
  1305. "last_update" : Date().currentTimeMillis()
  1306. ], replace: true)
  1307. }
  1308. } else {
  1309. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1310. "message_id" : message_id,
  1311. "status" : status,
  1312. "f_pin" : l_pin,
  1313. "last_update" : Date().currentTimeMillis()
  1314. ], replace: true)
  1315. }
  1316. } catch {
  1317. rollback.pointee = true
  1318. //print(error)
  1319. }
  1320. }
  1321. var pin = opposite_pin
  1322. if pin.isEmpty {
  1323. if scope == MessageScope.GROUP {
  1324. pin = chat_id.isEmpty ? l_pin : chat_id
  1325. } else {
  1326. pin = f_pin
  1327. }
  1328. }
  1329. if pin == me {
  1330. pin = l_pin
  1331. }
  1332. var counter : Int? = nil
  1333. if !withStatus {
  1334. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
  1335. counter = Int(cursor.int(forColumnIndex: 0))
  1336. if last_edited == 0 && !messageExist {
  1337. counter! += 1
  1338. }
  1339. cursor.close()
  1340. //print("select db message summary")
  1341. }
  1342. if counter == nil {
  1343. counter = 1
  1344. //print("set counter message summary")
  1345. }
  1346. }
  1347. if is_call_center == "0" {
  1348. do {
  1349. var queryGetLastMessageId = "SELECT message_id FROM MESSAGE where (f_pin = '\(pin)' OR l_pin = '\(pin)') AND message_scope_id = '\(MessageScope.WHISPER)' order by server_date desc LIMIT 1"
  1350. if scope == "4" {
  1351. queryGetLastMessageId = "SELECT message_id FROM MESSAGE where l_pin = '\(chat_id.isEmpty ? pin : l_pin)' AND chat_id = '\(chat_id)' AND message_scope_id = '\(MessageScope.GROUP)' order by server_date desc LIMIT 1"
  1352. }
  1353. var messageId = ""
  1354. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: queryGetLastMessageId), cursorData.next() {
  1355. messageId = cursorData.string(forColumnIndex: 0) ?? ""
  1356. cursorData.close()
  1357. }
  1358. if !messageId.isEmpty {
  1359. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
  1360. "l_pin" : pin,
  1361. "message_id" : messageId,
  1362. "counter" : counter ?? 0
  1363. ], replace: true)
  1364. }
  1365. } catch {
  1366. rollback.pointee = true
  1367. //print(error)
  1368. }
  1369. }
  1370. if !withStatus && !fromAPNS && (!messageExist || last_edited != 0) {
  1371. DispatchQueue.main.async {
  1372. if let delegate = Nexilis.shared.messageDelegate, Utils.getSetProfile() {
  1373. message.mBodies[CoreMessage_TMessageKey.MESSAGE_TEXT] = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_TEXT, default_value : "").toNormalString()
  1374. delegate.onReceive(message: message)
  1375. }
  1376. }
  1377. }
  1378. //print("insert db message summary \(message_id)")
  1379. } catch {
  1380. rollback.pointee = true
  1381. print("Access database error: \(error.localizedDescription)")
  1382. }
  1383. })
  1384. }
  1385. public static func saveMessageBot(textMessage: String, blog_id: String, attachment_type:String)->Void{
  1386. guard let me = User.getMyPin() else {
  1387. return
  1388. }
  1389. var user_id:String? = ""
  1390. let message_id = me + CoreMessage_TMessageUtil.getTID()
  1391. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1392. do {
  1393. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select user_id from BUDDY where f_pin = '\(me)'"), cursor.next() {
  1394. user_id = cursor.string(forColumnIndex: 0)
  1395. cursor.close()
  1396. }
  1397. } catch {
  1398. rollback.pointee = true
  1399. print("Access database error: \(error.localizedDescription)")
  1400. }
  1401. })
  1402. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1403. do {
  1404. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
  1405. "message_id" : message_id ,
  1406. "f_pin" : "-999",
  1407. "f_display_name" : "Bot",
  1408. "l_pin" : me,
  1409. "l_user_id" : String(user_id!),
  1410. "message_scope_id" : MessageScope.WHISPER,
  1411. "server_date" : String(Date().currentTimeMillis()),
  1412. "status" : "3",
  1413. "message_text" : textMessage,
  1414. "audio_id" : "",
  1415. "video_id" : "",
  1416. "image_id" : "",
  1417. "file_id" : "",
  1418. "thumb_id" : "",
  1419. "opposite_pin" : "",
  1420. "format" : "",
  1421. "blog_id" : blog_id,
  1422. "read_receipts" : "0",
  1423. "chat_id" : "",
  1424. "account_type" : "1",
  1425. "credential" :"",
  1426. "reff_id" : "",
  1427. "message_large_text" : "",
  1428. "attachment_flag" : attachment_type,
  1429. "local_timestamp" : String(Date().currentTimeMillis())
  1430. ], replace: true)
  1431. } catch {
  1432. rollback.pointee = true
  1433. print("Access database error: \(error.localizedDescription)")
  1434. }
  1435. })
  1436. let pin = "-999"
  1437. var counter : Int? = nil
  1438. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1439. do {
  1440. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select counter from MESSAGE_SUMMARY where l_pin = '\(pin)'"), cursor.next() {
  1441. counter = Int(cursor.int(forColumnIndex: 0))
  1442. counter! += 1
  1443. cursor.close()
  1444. //print("select db message summary")
  1445. }
  1446. } catch {
  1447. rollback.pointee = true
  1448. print("Access database error: \(error.localizedDescription)")
  1449. }
  1450. })
  1451. if counter == nil {
  1452. counter = 1
  1453. //print("set counter message summary")
  1454. }
  1455. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1456. do {
  1457. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
  1458. "l_pin" : pin,
  1459. "message_id" : message_id,
  1460. "counter" : counter!
  1461. ], replace: true)
  1462. } catch {
  1463. rollback.pointee = true
  1464. print("Access database error: \(error.localizedDescription)")
  1465. }
  1466. })
  1467. //print("insert db message summary \(message_id)")
  1468. }
  1469. public static func saveMessageCall(idCall: String, textMessage: String, fPin: String, lPin: String, timeCall: String, attachment_type:String) {
  1470. guard let me = User.getMyPin() else {
  1471. return
  1472. }
  1473. let dataFpin = User.getDataCanNil(pin: fPin)
  1474. let dataLpin = User.getDataCanNil(pin: lPin)
  1475. var messageExist = false
  1476. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1477. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select server_date from MESSAGE where server_date = '\(timeCall)'"), cursor.next() {
  1478. messageExist = true
  1479. cursor.close()
  1480. }
  1481. })
  1482. if messageExist {
  1483. return
  1484. }
  1485. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1486. do {
  1487. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
  1488. "message_id" : idCall ,
  1489. "f_pin" : fPin,
  1490. "f_display_name" : dataFpin != nil ? dataFpin!.fullName : "",
  1491. "l_pin" : lPin,
  1492. "l_user_id" : dataLpin != nil ? dataLpin!.pin : "",
  1493. "message_scope_id" : attachment_type,
  1494. "server_date" : timeCall,
  1495. "status" : "3",
  1496. "message_text" : textMessage,
  1497. "audio_id" : "",
  1498. "video_id" : "",
  1499. "image_id" : "",
  1500. "file_id" : "",
  1501. "thumb_id" : "",
  1502. "opposite_pin" : "",
  1503. "format" : "",
  1504. "blog_id" : "",
  1505. "read_receipts" : "0",
  1506. "chat_id" : "",
  1507. "account_type" : "1",
  1508. "credential" :"",
  1509. "reff_id" : "",
  1510. "message_large_text" : "",
  1511. "attachment_flag" : attachment_type,
  1512. "local_timestamp" : timeCall
  1513. ], replace: true)
  1514. } catch {
  1515. rollback.pointee = true
  1516. print("Access database error: \(error.localizedDescription)")
  1517. }
  1518. })
  1519. let pin = lPin == me ? fPin : lPin
  1520. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1521. do {
  1522. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", cvalues: [
  1523. "l_pin" : pin,
  1524. "message_id" : idCall,
  1525. "counter" : 0
  1526. ], replace: true)
  1527. } catch {
  1528. rollback.pointee = true
  1529. print("Access database error: \(error.localizedDescription)")
  1530. }
  1531. })
  1532. var dataMessage: [AnyHashable : Any] = [:]
  1533. dataMessage["message_id"] = idCall
  1534. dataMessage["pin"] = pin
  1535. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "refreshCallLog"), object: nil, userInfo: dataMessage)
  1536. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTabChats"), object: nil, userInfo: nil)
  1537. }
  1538. static func updateMessageStatus(message: TMessage) -> Void {
  1539. let message_id = message.getBody(key : CoreMessage_TMessageKey.MESSAGE_ID, default_value : "")
  1540. guard !message_id.isEmpty else {
  1541. return
  1542. }
  1543. let status = message.getBody(key : CoreMessage_TMessageKey.STATUS, default_value : "")
  1544. let latitude = message.getBody(key : CoreMessage_TMessageKey.LATITUDE, default_value : "")
  1545. let longitude = message.getBody(key : CoreMessage_TMessageKey.LONGITUDE, default_value : "")
  1546. let desc = message.getBody(key : CoreMessage_TMessageKey.DESCRIPTION, default_value : "")
  1547. guard !status.isEmpty else {
  1548. return
  1549. }
  1550. let l_pin = message.getBody(key : CoreMessage_TMessageKey.L_PIN, default_value : "")
  1551. guard !l_pin.isEmpty else {
  1552. return
  1553. }
  1554. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1555. do {
  1556. if message_id.starts(with: "-1") || message_id.starts(with: "-2") {
  1557. for s in message_id.split(separator: ",") {
  1558. let t = s.trimmingCharacters(in: .whitespaces)
  1559. if t == "-1" || t == "-2" {
  1560. continue
  1561. }
  1562. if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS where message_id = '\(t)'"), cursorStatus.next() {
  1563. let lastStatus = cursorStatus.int(forColumnIndex: 0)
  1564. if lastStatus < Int(status)! {
  1565. if status == "3" {
  1566. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1567. "status" : status,
  1568. "longitude" : longitude,
  1569. "latitude" : latitude,
  1570. "location" : desc,
  1571. "time_delivered" : String(Date().currentTimeMillis()),
  1572. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
  1573. } else if status == "4" {
  1574. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1575. "status" : status,
  1576. "time_read" : String(Date().currentTimeMillis()),
  1577. "longitude" : longitude,
  1578. "latitude" : latitude,
  1579. "location" : desc,
  1580. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
  1581. } else if status == "8" {
  1582. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1583. "status" : status,
  1584. "time_ack" : String(Date().currentTimeMillis()),
  1585. "longitude" : longitude,
  1586. "latitude" : latitude,
  1587. "location" : desc,
  1588. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
  1589. } else {
  1590. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1591. "status" : status,
  1592. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(t)' and f_pin = '\(l_pin)'")
  1593. }
  1594. }
  1595. cursorStatus.close()
  1596. }
  1597. }
  1598. } else {
  1599. if let cursorStatus = Database.shared.getRecords(fmdb: fmdb, query: "SELECT status FROM MESSAGE_STATUS where message_id = '\(message_id)'"), cursorStatus.next() {
  1600. let lastStatus = cursorStatus.int(forColumnIndex: 0)
  1601. if lastStatus < Int(status)! {
  1602. if status == "3" {
  1603. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1604. "status" : status,
  1605. "time_delivered" : String(Date().currentTimeMillis()),
  1606. "longitude" : longitude,
  1607. "latitude" : latitude,
  1608. "location" : desc,
  1609. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
  1610. } else if status == "4" {
  1611. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1612. "status" : status,
  1613. "time_read" : String(Date().currentTimeMillis()),
  1614. "longitude" : longitude,
  1615. "latitude" : latitude,
  1616. "location" : desc,
  1617. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
  1618. } else if status == "8" {
  1619. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1620. "status" : status,
  1621. "time_ack" : String(Date().currentTimeMillis()),
  1622. "longitude" : longitude,
  1623. "latitude" : latitude,
  1624. "location" : desc,
  1625. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
  1626. } else {
  1627. _ = Database.shared.updateRecord(fmdb: fmdb, table: "MESSAGE_STATUS", cvalues: [
  1628. "status" : status,
  1629. "longitude" : longitude,
  1630. "latitude" : latitude,
  1631. "location" : desc,
  1632. "last_update" : String(Date().currentTimeMillis())], _where: "message_id = '\(message_id)' and f_pin = '\(l_pin)'")
  1633. }
  1634. }
  1635. cursorStatus.close()
  1636. }
  1637. }
  1638. } catch {
  1639. rollback.pointee = true
  1640. print("Access database error: \(error.localizedDescription)")
  1641. }
  1642. })
  1643. }
  1644. static func getGroupMembers(fmdb: FMDatabase, l_pin: String) -> [String] {
  1645. var result = [String]()
  1646. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin from GROUPZ_MEMBER where group_id = '\(l_pin)'") {
  1647. while cursor.next() {
  1648. if let value = cursor.string(forColumnIndex: 0) {
  1649. result.append(value)
  1650. }
  1651. }
  1652. cursor.close()
  1653. }
  1654. return result
  1655. }
  1656. static func getVideoThumbnail(name: String, completion: @escaping (Bool)->()) {
  1657. DispatchQueue.global().async {
  1658. do {
  1659. let fileManager = FileManager.default
  1660. let documentDir = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  1661. let fileDir = documentDir.appendingPathComponent(name)
  1662. let path = fileDir.path
  1663. if FileManager.default.fileExists(atPath: path) {
  1664. let asset = AVAsset(url: URL(fileURLWithPath: path))
  1665. let avAssetImageGenerator = AVAssetImageGenerator(asset: asset)
  1666. avAssetImageGenerator.appliesPreferredTrackTransform = true
  1667. let thumnailTime = CMTimeMake(value: 2, timescale: 1)
  1668. let thumbImage = UIImage(cgImage: try avAssetImageGenerator.copyCGImage(at: thumnailTime, actualTime: nil))
  1669. guard let data = thumbImage.jpegData(compressionQuality: 1.0) else {
  1670. completion(false)
  1671. return
  1672. }
  1673. let thumbFileDir = documentDir.appendingPathComponent("THUMB_" + name)
  1674. try data.write(to: thumbFileDir)
  1675. completion(true)
  1676. } else {
  1677. completion(false)
  1678. }
  1679. } catch {
  1680. //print(error)
  1681. }
  1682. }
  1683. }
  1684. static func resizedImage(at url: URL, for size: CGSize) -> UIImage? {
  1685. var image : UIImage?
  1686. if FileManager.default.fileExists(atPath: url.path){
  1687. image = UIImage(contentsOfFile: url.path)
  1688. }
  1689. else if FileEncryption.shared.isSecureExists(filename: url.lastPathComponent) {
  1690. do {
  1691. if var imageData = try FileEncryption.shared.readSecure(filename: url.lastPathComponent) {
  1692. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
  1693. if dataDecrypt != nil {
  1694. imageData = dataDecrypt!
  1695. }
  1696. image = UIImage(data: imageData)
  1697. }
  1698. }
  1699. catch {
  1700. }
  1701. }
  1702. if image == nil {
  1703. return nil
  1704. }
  1705. let renderer = UIGraphicsImageRenderer(size: size)
  1706. return renderer.image { (context) in
  1707. image!.draw(in: CGRect(origin: .zero, size: size))
  1708. }
  1709. }
  1710. static func initFollowing() -> Void {
  1711. if let me = User.getMyPin() {
  1712. if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getListFollowing(l_pin: me)) {
  1713. let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
  1714. if !data.isEmpty {
  1715. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  1716. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  1717. do {
  1718. for json in jsonArray {
  1719. _ = try Database.shared.insertRecord(fmdb: fmdb, table: "FOLLOW", cvalues: [
  1720. "f_pin" : CoreMessage_TMessageUtil.getString(json: json, key: "pin")
  1721. ], replace: true)
  1722. }
  1723. } catch {
  1724. rollback.pointee = true
  1725. print("Access database error: \(error.localizedDescription)")
  1726. }
  1727. })
  1728. }
  1729. }
  1730. }
  1731. }
  1732. }
  1733. // do {
  1734. // _ = try Database.shared.insertRecord(fmdb: fmdb, table: "CALL_CENTER_HISTORY", cvalues: [
  1735. // "type" : "1",
  1736. // "title" : displayName,
  1737. // "time" : timeStart,
  1738. // "f_pin" : f_pin,
  1739. // "data" : dataCC,
  1740. // "time_end" : date,
  1741. // "complaint_id" : complaint_id.isEmpty ? "C\(date)" : complaint_id,
  1742. // "members" : "",
  1743. // "requester": ""
  1744. // ], replace: true)
  1745. // _ = try Database.shared.insertRecord(fmdb: fmdb, table: "PREFS", cvalues: [
  1746. // "key" : "CC:\(f_pin)",
  1747. // "value" : status,
  1748. // ], replace: true)
  1749. // ret = true
  1750. // } catch {
  1751. // rollback.pointee = true
  1752. // //print(error)
  1753. // }
  1754. private static var uploadQueue = DispatchQueue(label: "UPLOAD_DICT", attributes: .concurrent)
  1755. private static var UPLOAD_DICT = [String: Network]()
  1756. static func removeUploadFile(forKey: String) -> Network? {
  1757. var _result: Network? = nil
  1758. uploadQueue.sync {
  1759. _result = self.UPLOAD_DICT.removeValue(forKey: forKey)
  1760. }
  1761. return _result
  1762. }
  1763. static func putUploadFile(forKey: String, uploader: Network) {
  1764. uploadQueue.async (flags: .barrier) {
  1765. self.UPLOAD_DICT[forKey] = uploader
  1766. }
  1767. }
  1768. static func getUploadFile(forKey: String) -> Network? {
  1769. var _result: Network? = nil
  1770. uploadQueue.sync {
  1771. _result = self.UPLOAD_DICT[forKey]
  1772. }
  1773. return _result
  1774. }
  1775. private static var downloadQueue = DispatchQueue(label: "DOWNLOAD_DICT", attributes: .concurrent)
  1776. private static var DOWNLOAD_DICT = [String:Download]()
  1777. static func addDownload(forKey : String, download: Download){
  1778. downloadQueue.async (flags: .barrier) {
  1779. self.DOWNLOAD_DICT[forKey] = download
  1780. }
  1781. }
  1782. static func getDownload(forKey: String) -> Download? {
  1783. var _result: Download? = nil
  1784. downloadQueue.sync {
  1785. _result = self.DOWNLOAD_DICT[forKey]
  1786. }
  1787. return _result
  1788. }
  1789. static func removeDownload(forKey: String) -> Download? {
  1790. var _result: Download? = nil
  1791. downloadQueue.sync {
  1792. _result = self.DOWNLOAD_DICT.removeValue(forKey: forKey)
  1793. }
  1794. return _result
  1795. }
  1796. static func writeImageToFile(data: Data, fileName: String){
  1797. guard let directory = FileManager.default.urls(for: .picturesDirectory, in: .userDomainMask).last else {
  1798. return
  1799. }
  1800. let fileURL = directory.appendingPathComponent("\(fileName)")
  1801. if FileManager.default.fileExists(atPath: fileURL.path) {
  1802. if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
  1803. fileHandle.seekToEndOfFile()
  1804. fileHandle.write(data)
  1805. fileHandle.closeFile()
  1806. } else {
  1807. //print("Can't open file to write")
  1808. }
  1809. } else {
  1810. do {
  1811. try data.write(to: fileURL, options: .atomic)
  1812. } catch {
  1813. //print("Unable to write in new file")
  1814. }
  1815. }
  1816. }
  1817. static func writeVideoToFile(data: Data, fileName: String){
  1818. guard let directory = FileManager.default.urls(for: .moviesDirectory, in: .userDomainMask).last else {
  1819. return
  1820. }
  1821. let fileURL = directory.appendingPathComponent("\(fileName)")
  1822. if FileManager.default.fileExists(atPath: fileURL.path) {
  1823. if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
  1824. fileHandle.seekToEndOfFile()
  1825. fileHandle.write(data)
  1826. fileHandle.closeFile()
  1827. } else {
  1828. //print("Can't open file to write")
  1829. }
  1830. } else {
  1831. do {
  1832. try data.write(to: fileURL, options: .atomic)
  1833. } catch {
  1834. //print("Unable to write in new file")
  1835. }
  1836. }
  1837. }
  1838. static func writeDocumentsToFile(data: Data, fileName: String){
  1839. guard let directory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last else {
  1840. return
  1841. }
  1842. let fileURL = directory.appendingPathComponent("\(fileName)")
  1843. if FileManager.default.fileExists(atPath: fileURL.path) {
  1844. if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
  1845. fileHandle.seekToEndOfFile()
  1846. fileHandle.write(data)
  1847. fileHandle.closeFile()
  1848. } else {
  1849. //print("Can't open file to write")
  1850. }
  1851. } else {
  1852. do {
  1853. try data.write(to: fileURL, options: .atomic)
  1854. } catch {
  1855. //print("Unable to write in new file")
  1856. }
  1857. }
  1858. }
  1859. public static func checkMicPermission() -> Bool {
  1860. var permissionCheck: Bool = false
  1861. switch AVAudioSession.sharedInstance().recordPermission {
  1862. case .granted:
  1863. permissionCheck = true
  1864. case .denied:
  1865. permissionCheck = false
  1866. case .undetermined:
  1867. Nexilis.dispatch = DispatchGroup()
  1868. Nexilis.dispatch?.enter()
  1869. AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
  1870. if granted {
  1871. permissionCheck = true
  1872. } else {
  1873. permissionCheck = false
  1874. }
  1875. if let dispatch = Nexilis.dispatch {
  1876. dispatch.leave()
  1877. }
  1878. })
  1879. Nexilis.dispatch?.wait()
  1880. Nexilis.dispatch = nil
  1881. default:
  1882. break
  1883. }
  1884. return permissionCheck
  1885. }
  1886. public static func checkCameraPermission() -> Int {
  1887. var permissionCheck: Int = -1
  1888. if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
  1889. permissionCheck = 1
  1890. } else if AVCaptureDevice.authorizationStatus(for: .video) == .denied {
  1891. permissionCheck = 0
  1892. } else {
  1893. AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) -> Void in
  1894. })
  1895. }
  1896. return permissionCheck
  1897. }
  1898. // public static func startTimer(){
  1899. // broadcastTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: {_ in
  1900. // if(!openBroadcast && !broadcastList.isEmpty){
  1901. // openBroadcast = true
  1902. // let m = broadcastList.removeFirst()
  1903. // //print("broadcast show: \(m)")
  1904. // DispatchQueue.main.async {
  1905. // Nexilis.shared.showBroadcastMessage(m: m)
  1906. // }
  1907. // }
  1908. // })
  1909. // }
  1910. public static func debugBroadcast(){
  1911. if(Utils.getDebugBC() != nil) {
  1912. let m = Utils.getDebugBC()
  1913. Nexilis.shared.showBroadcastMessage(m: m!)
  1914. }
  1915. }
  1916. /*
  1917. * Delegate
  1918. */
  1919. weak open var loginDelegate: LoginDelegate?
  1920. weak open var messageDelegate: MessageDelegate?
  1921. weak open var groupDelegate: GroupDelegate?
  1922. weak open var callDelegate: CallDelegate?
  1923. weak open var streamingDelagate: LiveStreamingDelegate?
  1924. weak open var seminarDelegate: SeminarDelegate?
  1925. weak open var personInfoDelegate: PersonInfoDelegate?
  1926. weak open var screenSharingDelegate: ScreenSharingDelegate?
  1927. weak open var commentDelegate: CommentDelegate?
  1928. weak open var uploadDelegate: UploadDelegate?
  1929. weak open var timelineDelegate: TimelineDelegate?
  1930. weak open var connectionDelegate: ConnectionDelegate?
  1931. var floating: FloatingNotificationBanner!
  1932. var stateUnfriend = ""
  1933. }
  1934. struct LibFontName {
  1935. static let regular = "Poppins-Regular"
  1936. static let bold = "Poppins-SemiBold"
  1937. static let italic = "Poppins-Italic"
  1938. static let medium = "Poppins-Medium"
  1939. static let boldItalic = "Poppins-SemiBoldItalic"
  1940. }
  1941. extension UIFontDescriptor.AttributeName {
  1942. static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
  1943. }
  1944. extension UIFont {
  1945. static var isOverrided: Bool = false
  1946. static let FONT_SELECT = 0
  1947. @objc class func libSystemFont(ofSize size: CGFloat) -> UIFont? {
  1948. if UIFont(name: LibFontName.regular, size: size) == nil {
  1949. jbs_registerFont(withFilenameString: LibFontName.regular)
  1950. }
  1951. return UIFont(name: LibFontName.regular, size: size)
  1952. }
  1953. @objc class func libSystemFontWeight(ofSize size: CGFloat, weight: UIFont.Weight) -> UIFont? {
  1954. if weight == .medium {
  1955. if UIFont(name: LibFontName.medium, size: size) == nil {
  1956. jbs_registerFont(withFilenameString: LibFontName.medium)
  1957. }
  1958. return UIFont(name: LibFontName.medium, size: size)
  1959. } else if weight == .semibold {
  1960. if UIFont(name: LibFontName.boldItalic, size: size) == nil {
  1961. jbs_registerFont(withFilenameString: LibFontName.boldItalic)
  1962. }
  1963. return UIFont(name: LibFontName.boldItalic, size: size)
  1964. }
  1965. return UIFont(name: LibFontName.regular, size: size)
  1966. }
  1967. @objc class func libBoldSystemFont(ofSize size: CGFloat) -> UIFont? {
  1968. if UIFont(name: LibFontName.bold, size: size) == nil {
  1969. jbs_registerFont(withFilenameString: LibFontName.bold)
  1970. }
  1971. return UIFont(name: LibFontName.bold, size: size)
  1972. }
  1973. @objc class func libItalicSystemFont(ofSize size: CGFloat) -> UIFont? {
  1974. if UIFont(name: LibFontName.italic, size: size) == nil {
  1975. jbs_registerFont(withFilenameString: LibFontName.italic)
  1976. }
  1977. return UIFont(name: LibFontName.italic, size: size)
  1978. }
  1979. @objc convenience init(myCoder aDecoder: NSCoder) {
  1980. guard
  1981. let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
  1982. let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
  1983. self.init(myCoder: aDecoder)
  1984. return
  1985. }
  1986. var fontName = ""
  1987. switch fontAttribute {
  1988. case "CTFontRegularUsage":
  1989. fontName = LibFontName.regular
  1990. case "CTFontEmphasizedUsage", "CTFontBoldUsage":
  1991. fontName = LibFontName.bold
  1992. case "CTFontObliqueUsage":
  1993. fontName = LibFontName.italic
  1994. default:
  1995. fontName = LibFontName.regular
  1996. }
  1997. self.init(name: fontName, size: fontDescriptor.pointSize)!
  1998. }
  1999. class func libOverrideInitialize() {
  2000. guard self == UIFont.self, !isOverrided, FONT_SELECT == 0 else { return }
  2001. // Avoid method swizzling run twice and revert to original initialize function
  2002. isOverrided = true
  2003. if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
  2004. let mySystemFontMethod = class_getClassMethod(self, #selector(libSystemFont(ofSize:))) {
  2005. method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
  2006. }
  2007. if let systemFontWeightMethod = class_getClassMethod(self, #selector(systemFont(ofSize:weight:))),
  2008. let mySystemFontWeightMethod = class_getClassMethod(self, #selector(libSystemFontWeight(ofSize:weight:))) {
  2009. method_exchangeImplementations(systemFontWeightMethod, mySystemFontWeightMethod)
  2010. }
  2011. if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
  2012. let myBoldSystemFontMethod = class_getClassMethod(self, #selector(libBoldSystemFont(ofSize:))) {
  2013. method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
  2014. }
  2015. if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
  2016. let myItalicSystemFontMethod = class_getClassMethod(self, #selector(libItalicSystemFont(ofSize:))) {
  2017. method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
  2018. }
  2019. if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))), // Trick to get over the lack of UIFont.init(coder:))
  2020. let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) {
  2021. method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
  2022. }
  2023. }
  2024. class func jbs_registerFont(withFilenameString filenameString: String) {
  2025. // guard let pathForResourceString = Bundle.resourceBundle(for: Nexilis.self).path(forResource: filenameString, ofType: "otf") else { //resourcesMediaBundle
  2026. // //print("UIFont+: Failed to register font - path for resource not found.")
  2027. // return
  2028. // }
  2029. var pathForResourceURL = Bundle.resourceBundle(for: Nexilis.self).url(forResource: filenameString, withExtension: "otf")
  2030. if pathForResourceURL == nil {
  2031. pathForResourceURL = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: filenameString, withExtension: "otf")
  2032. }
  2033. // guard let pathForResourceURL = Bundle.resourceBundle(for: Nexilis.self).url(forResource: filenameString, withExtension: "otf") else { //resourcesMediaBundle
  2034. // //print("UIFont+: Failed to register font - path for resource not found.")
  2035. // return
  2036. // }
  2037. var errorRef: Unmanaged<CFError>? = nil
  2038. CTFontManagerRegisterFontsForURL(pathForResourceURL! as CFURL, .process, &errorRef)
  2039. // guard let fontData = NSData(contentsOfFile: pathForResourceString) else {
  2040. // //print("UIFont+: Failed to register font - font data could not be loaded.")
  2041. // return
  2042. // }
  2043. //
  2044. // guard let dataProvider = CGDataProvider(data: fontData) else {
  2045. // //print("UIFont+: Failed to register font - data provider could not be loaded.")
  2046. // return
  2047. // }
  2048. //
  2049. // guard let font = CGFont(dataProvider) else {
  2050. // //print("UIFont+: Failed to register font - font could not be loaded.")
  2051. // return
  2052. // }
  2053. //
  2054. // var errorRef: Unmanaged<CFError>? = nil
  2055. // if (CTFontManagerRegisterGraphicsFont(font, &errorRef) == false) {
  2056. // }
  2057. }
  2058. }
  2059. public protocol LoginDelegate: NSObjectProtocol {
  2060. func onProgress(code: String, progress: Int)
  2061. func onProcess(message: String, status: String)
  2062. }
  2063. public protocol MessageDelegate: NSObjectProtocol {
  2064. func onReceive(message: TMessage)
  2065. func onReceiveComment(message: TMessage)
  2066. func onReceive(message: [AnyHashable: Any?])
  2067. func onMessage(message: TMessage)
  2068. func onUpload(name: String, progress: Double)
  2069. func onTyping(message: TMessage)
  2070. }
  2071. public protocol GroupDelegate: NSObjectProtocol {
  2072. func onGroup(code: String, f_pin: String, groupId: String)
  2073. func onTopic(code: String, f_pin: String, topicId: String)
  2074. func onMember(code: String, f_pin: String, groupId: String, member: String)
  2075. }
  2076. public protocol DownloadDelegate: NSObjectProtocol {
  2077. func onDownloadProgress(fileName: String, progress: Double)
  2078. }
  2079. public protocol CallDelegate: NSObjectProtocol {
  2080. func onIncomingCall(state: Int, message: String)
  2081. func onStatusCall(state: Int, message: String)
  2082. }
  2083. public protocol LiveStreamingDelegate: NSObjectProtocol {
  2084. func onStartLS(state: Int, message: String)
  2085. func onJoinLS(state: Int, message: String)
  2086. }
  2087. public protocol SeminarDelegate: NSObjectProtocol {
  2088. func onStartSeminar(state: Int, message: String)
  2089. func onJoinSeminar(state: Int, message: String)
  2090. }
  2091. public protocol VideoCallDelegate: NSObjectProtocol {
  2092. func onInitiateVideoCall(destination:String,state: Int, message: String)
  2093. func onAcceptVideoCall(originator:String,state: Int, message: String)
  2094. func onVideoCallReceiverTerminate(originator:String,state: Int, message: String)
  2095. }
  2096. public protocol PersonInfoDelegate: NSObjectProtocol {
  2097. func onUpdatePersonInfo(state: Int, message: String)
  2098. }
  2099. public protocol ScreenSharingDelegate: NSObjectProtocol {
  2100. func onStartScreenSharing(state:Int,message:String)
  2101. func onJoinScreenSharing(state:Int,message:String)
  2102. }
  2103. public protocol CommentDelegate: NSObjectProtocol {
  2104. func onReceiveComment(message: TMessage)
  2105. func onDeleteComment(message: TMessage)
  2106. }
  2107. public protocol UploadDelegate: NSObjectProtocol {
  2108. func onUploadProgress(fileName: String, progress: Double)
  2109. }
  2110. public protocol TimelineDelegate: NSObjectProtocol {
  2111. func onPostUpdate(status: String, message: String)
  2112. }
  2113. public protocol ConnectionDelegate: NSObjectProtocol {
  2114. func connectionStateChanged(userId: String!, deviceId: String, state: Bool)
  2115. }
  2116. public protocol ConnectDelegate: NSObjectProtocol {
  2117. func onSuccess(userId: String)
  2118. func onFailed(error: String)
  2119. }
  2120. public enum AppStoryBoard: String {
  2121. case Palio = "Palio"
  2122. public var instance: UIStoryboard {
  2123. return UIStoryboard(name: self.rawValue, bundle: Bundle.resourceBundle(for: Nexilis.self))
  2124. }
  2125. }
  2126. public var uuidOngoing = UUID()
  2127. extension Nexilis: CallDelegate {
  2128. func displayIncomingCall(uuid: UUID, handle: String, hasVideo: Bool = false, completion: ((Error?) -> Void)? = nil) {
  2129. providerDelegate?.reportIncomingCall(uuid: uuid, handle: handle, hasVideo: hasVideo, completion: completion)
  2130. }
  2131. public func onIncomingCall(state: Int, message: String) {
  2132. DispatchQueue.main.async {
  2133. let idMe = User.getMyPin()!
  2134. let myData = User.getData(pin: idMe)
  2135. let onGoingCC: String = SecureUserDefaults.shared.value(forKey: "onGoingCC") ?? ""
  2136. if !onGoingCC.isEmpty {
  2137. return
  2138. }
  2139. let deviceId = message.split(separator: ",")[0]
  2140. if myData?.offline_mode == "1" || self.stateUnfriend == deviceId {
  2141. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
  2142. API.terminateCall(sParty: nil)
  2143. })
  2144. return
  2145. }
  2146. var isShowAlert: Double?
  2147. let canShow = UIApplication.shared.visibleViewController
  2148. if canShow != nil && !(canShow is UINavigationController) {
  2149. if !(canShow is EditorPersonal) {
  2150. isShowAlert = 0
  2151. } else {
  2152. isShowAlert = 1.5
  2153. }
  2154. } else if canShow != nil {
  2155. if canShow is UINavigationController {
  2156. let canShowNC = canShow as! UINavigationController
  2157. if !(canShowNC.visibleViewController is EditorPersonal) {
  2158. isShowAlert = 0
  2159. } else {
  2160. isShowAlert = 1.5
  2161. }
  2162. } else {
  2163. isShowAlert = 0
  2164. }
  2165. }
  2166. if (state == Nexilis.AUDIO_CALL_INCOMING && message.split(separator: ",")[1] != "joining Ac.room on channel 0" && message.split(separator: ",")[1] != "joining Vc.room on channel 0") {
  2167. if Nexilis.callAPNActivated || APIS.checkAppStateisBackground() {
  2168. return
  2169. }
  2170. let data = User.getDataCanNil(pin: String(deviceId))
  2171. if data == nil {
  2172. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
  2173. API.terminateCall(sParty: nil)
  2174. })
  2175. return
  2176. }
  2177. // let backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
  2178. // uuidOngoing = UUID()
  2179. // self.displayIncomingCall(uuid: uuidOngoing, handle: String(deviceId), hasVideo: false) { error in
  2180. // UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
  2181. // }
  2182. let controller = QmeraAudioViewController()
  2183. controller.user = User.getData(pin: String(deviceId))
  2184. controller.isOutgoing = false
  2185. controller.modalPresentationStyle = .overCurrentContext
  2186. if UIApplication.shared.visibleViewController is UIAlertController {
  2187. let vc = UIApplication.shared.visibleViewController as! UIAlertController
  2188. vc.dismiss(animated: true, completion: {
  2189. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2190. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  2191. } else {
  2192. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  2193. }
  2194. })
  2195. return
  2196. }
  2197. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2198. UIApplication.shared.visibleViewController?.navigationController?.present(controller, animated: true, completion: nil)
  2199. } else {
  2200. UIApplication.shared.visibleViewController?.present(controller, animated: true, completion: nil)
  2201. }
  2202. // API.receiveCCall(sParty: String(deviceId))
  2203. } else if (state == Nexilis.VIDEO_CALL_INCOMING && message.split(separator: ",")[1] != "joining Ac.room on channel 0" && message.split(separator: ",")[1] != "joining Vc.room on channel 0") {
  2204. if Nexilis.callAPNActivated || APIS.checkAppStateisBackground() {
  2205. return
  2206. }
  2207. let dataUser = User.getDataCanNil(pin: String(deviceId))
  2208. if dataUser == nil {
  2209. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
  2210. API.terminateCall(sParty: nil)
  2211. })
  2212. return
  2213. }
  2214. let videoController = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
  2215. videoController.fPin = String(deviceId)
  2216. videoController.isInisiator = false
  2217. let navigationController = CustomNavigationController(rootViewController: videoController)
  2218. navigationController.modalPresentationStyle = .fullScreen
  2219. if UIApplication.shared.visibleViewController is UIAlertController {
  2220. let vc = UIApplication.shared.visibleViewController as! UIAlertController
  2221. vc.dismiss(animated: true, completion: {
  2222. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2223. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2224. } else {
  2225. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2226. }
  2227. })
  2228. return
  2229. }
  2230. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2231. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2232. } else {
  2233. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2234. }
  2235. }
  2236. }
  2237. }
  2238. public func onStatusCall(state: Int, message: String) {
  2239. // let r = message.split(separator: ",")
  2240. // if state == Nexilis.AUDIO_CALL_RINGING {
  2241. // if let call = callManager.call(with: String(r[0])) {
  2242. // //print("onStatusCall:connectingCall")
  2243. // DispatchQueue.main.async {
  2244. // call.connectingCall()
  2245. // }
  2246. // }
  2247. // } else if state == Nexilis.AUDIO_CALL_OFFHOOK {
  2248. //// if let call = callManager.call(with: String(r[1])) {
  2249. // //print("onStatusCall:answerCall")
  2250. //// DispatchQueue.main.async {
  2251. //// call.answerCall()
  2252. //// }
  2253. //// }
  2254. // } else if state == Nexilis.AUDIO_CALL_END {
  2255. // DispatchQueue.main.async {
  2256. // if QmeraAudioViewController().viewIfLoaded?.window == nil {
  2257. // Nexilis.shared.callManager.end(call: Call(uuid: uuidOngoing))
  2258. // }
  2259. // }
  2260. // }
  2261. var dataCall: [AnyHashable : Any] = [:]
  2262. dataCall["state"] = state
  2263. dataCall["message"] = message
  2264. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerStatusCall), object: nil, userInfo: dataCall)
  2265. }
  2266. }
  2267. var previewItem : NSURL?
  2268. var listCCIdInv: [String] = []
  2269. var imageGif: UIImageView!
  2270. var posGif = "0"
  2271. var loopGif = "0"
  2272. var timerAnimationGif = Timer()
  2273. extension Nexilis: MessageDelegate {
  2274. public func onReceiveComment(message: TMessage) {
  2275. var dataMessage: [AnyHashable : Any] = [:]
  2276. dataMessage["message"] = message
  2277. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onReceiveComment"), object: nil, userInfo: dataMessage)
  2278. }
  2279. @objc func tapLinkBroadcast(_ sender: ObjectGesture) {
  2280. var stringURl = sender.message_id.lowercased()
  2281. if stringURl.starts(with: "www.") {
  2282. stringURl = "https://" + stringURl.replacingOccurrences(of: "www.", with: "")
  2283. }
  2284. guard let url = URL(string: stringURl) else { return }
  2285. UIApplication.shared.open(url)
  2286. }
  2287. private func runAnimationGif() {
  2288. DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: { [self] in
  2289. if imageGif != nil {
  2290. timerAnimationGif.invalidate()
  2291. timerAnimationGif = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(animateGif), userInfo: nil, repeats: true)
  2292. }
  2293. })
  2294. }
  2295. @objc func animateGif() {
  2296. DispatchQueue.main.async {
  2297. if posGif == "0" { //left
  2298. if imageGif.frame.origin.x < (UIScreen.main.bounds.width - imageGif.frame.width) {
  2299. imageGif.frame.origin.x+=0.1
  2300. } else {
  2301. timerAnimationGif.invalidate()
  2302. }
  2303. } else if posGif == "1" { //right
  2304. if imageGif.frame.origin.x > 0 {
  2305. imageGif.frame.origin.x-=0.1
  2306. } else {
  2307. timerAnimationGif.invalidate()
  2308. }
  2309. } else if posGif == "2" { //top
  2310. if imageGif.frame.origin.y < (UIScreen.main.bounds.height - imageGif.frame.height) {
  2311. imageGif.frame.origin.y+=0.1
  2312. } else {
  2313. timerAnimationGif.invalidate()
  2314. }
  2315. } else { //bottom
  2316. if imageGif.frame.origin.y > 20 {
  2317. imageGif.frame.origin.y-=0.1
  2318. } else {
  2319. timerAnimationGif.invalidate()
  2320. }
  2321. }
  2322. }
  2323. }
  2324. func showBroadcastMessage(m: [String: String]) {
  2325. let fileType = m[CoreMessage_TMessageKey.CATEGORY_FLAG]!
  2326. let gifId = m[CoreMessage_TMessageKey.GIF_ID] ?? ""
  2327. let broadcastVC = UIViewController()
  2328. if let viewBroadcast = broadcastVC.view {
  2329. broadcastVC.modalPresentationStyle = .custom
  2330. viewBroadcast.backgroundColor = .black.withAlphaComponent(0.3)
  2331. if !gifId.isEmpty {
  2332. let urlGif = "\(Utils.getURLBase())filepalio/image/\(gifId)"
  2333. let scale = m[CoreMessage_TMessageKey.SCALE] ?? "0"
  2334. let link = m[CoreMessage_TMessageKey.LINK] ?? ""
  2335. posGif = m[CoreMessage_TMessageKey.START_ANIMATION] ?? "0"
  2336. loopGif = m[CoreMessage_TMessageKey.LOOP_ANIMATION] ?? "0"
  2337. imageGif = UIImageView()
  2338. viewBroadcast.addSubview(imageGif)
  2339. imageGif.isUserInteractionEnabled = true
  2340. imageGif.contentMode = .scaleAspectFit
  2341. let buttonClose = UIButton(type: .close)
  2342. buttonClose.frame.size = CGSize(width: 30, height: 30)
  2343. buttonClose.layer.cornerRadius = 15.0
  2344. buttonClose.clipsToBounds = true
  2345. buttonClose.backgroundColor = .black.withAlphaComponent(0.5)
  2346. buttonClose.actionHandle(controlEvents: .touchUpInside,
  2347. ForAction:{() -> Void in
  2348. broadcastVC.dismiss(animated: true, completion: {
  2349. imageGif = nil
  2350. Nexilis.broadcastList.remove(at: 0)
  2351. if Nexilis.broadcastList.count > 0 {
  2352. Nexilis.shared.showBroadcastMessage(m: Nexilis.broadcastList[0])
  2353. }
  2354. })
  2355. })
  2356. imageGif.addSubview(buttonClose)
  2357. buttonClose.anchor(top: imageGif.topAnchor, right: imageGif.rightAnchor, width: 30, height: 30)
  2358. var xpos: CGFloat = 0
  2359. var ypos: CGFloat = 0
  2360. var widthImage: CGFloat = 300
  2361. var heightImage: CGFloat = 300
  2362. if scale == "2" { //50%
  2363. widthImage = 150
  2364. heightImage = 150
  2365. } else if scale == "1" { //75%
  2366. widthImage = 225
  2367. heightImage = 225
  2368. }
  2369. if posGif == "0" { //left
  2370. xpos = 0
  2371. ypos = (viewBroadcast.frame.size.height / 2) - (heightImage / 2)
  2372. } else if posGif == "1" { //right
  2373. xpos = viewBroadcast.frame.size.width - widthImage
  2374. ypos = (viewBroadcast.frame.size.height / 2) - (heightImage / 2)
  2375. } else if posGif == "2" { //top
  2376. xpos = (viewBroadcast.frame.size.width / 2) - (widthImage / 2)
  2377. ypos = 20
  2378. } else { //bottom
  2379. xpos = (viewBroadcast.frame.size.width / 2) - (widthImage / 2)
  2380. ypos = viewBroadcast.frame.size.height - heightImage
  2381. }
  2382. imageGif.frame = CGRect(x: xpos, y: ypos, width: widthImage, height: heightImage)
  2383. imageGif.loadImageAsync(with: urlGif, isGif: true)
  2384. runAnimationGif()
  2385. imageGif.actionHandle(controlEvents: .touchUpInside, ForAction: {
  2386. broadcastVC.dismiss(animated: true, completion: {
  2387. imageGif = nil
  2388. Nexilis.broadcastList.remove(at: 0)
  2389. if Nexilis.broadcastList.count > 0 {
  2390. Nexilis.shared.showBroadcastMessage(m: Nexilis.broadcastList[0])
  2391. }
  2392. if !link.isEmpty {
  2393. APIS.openUrl(url: link)
  2394. }
  2395. })
  2396. })
  2397. } else {
  2398. let stringLink = m[CoreMessage_TMessageKey.LINK] ?? ""
  2399. let containerView = UIView()
  2400. viewBroadcast.addSubview(containerView)
  2401. if stringLink.isEmpty {
  2402. containerView.anchor(centerX: viewBroadcast.centerXAnchor, centerY: viewBroadcast.centerYAnchor, width: viewBroadcast.bounds.width - 40, minHeight: 100, maxHeight: viewBroadcast.bounds.height - 100)
  2403. } else {
  2404. containerView.anchor(centerX: viewBroadcast.centerXAnchor, centerY: viewBroadcast.centerYAnchor, width: viewBroadcast.bounds.width - 40, minHeight: 200, maxHeight: viewBroadcast.bounds.height - 100)
  2405. }
  2406. containerView.backgroundColor = .white.withAlphaComponent(0.9)
  2407. containerView.layer.cornerRadius = 15.0
  2408. containerView.clipsToBounds = true
  2409. let subContainerView = UIView()
  2410. subContainerView.backgroundColor = .clear
  2411. containerView.addSubview(subContainerView)
  2412. 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)
  2413. let buttonClose = UIButton(type: .close)
  2414. buttonClose.frame.size = CGSize(width: 30, height: 30)
  2415. buttonClose.layer.cornerRadius = 15.0
  2416. buttonClose.clipsToBounds = true
  2417. buttonClose.backgroundColor = .secondaryColor.withAlphaComponent(0.5)
  2418. buttonClose.actionHandle(controlEvents: .touchUpInside,
  2419. ForAction:{() -> Void in
  2420. broadcastVC.dismiss(animated: true, completion: {
  2421. Nexilis.broadcastList.remove(at: 0)
  2422. if Nexilis.broadcastList.count > 0 {
  2423. Nexilis.shared.showBroadcastMessage(m: Nexilis.broadcastList[0])
  2424. }
  2425. })
  2426. })
  2427. containerView.addSubview(buttonClose)
  2428. buttonClose.anchor(top: containerView.topAnchor, right: containerView.rightAnchor, width: 30, height: 30)
  2429. let title = UILabel()
  2430. title.font = .systemFont(ofSize: 18, weight: .bold)
  2431. title.text = m["MERNAM"]
  2432. title.textAlignment = .center
  2433. subContainerView.addSubview(title)
  2434. title.anchor(top: subContainerView.topAnchor, left: subContainerView.leftAnchor, right: subContainerView.rightAnchor)
  2435. let titleBroadcast = UILabel()
  2436. subContainerView.addSubview(titleBroadcast)
  2437. titleBroadcast.translatesAutoresizingMaskIntoConstraints = false
  2438. NSLayoutConstraint.activate([
  2439. titleBroadcast.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 20.0),
  2440. titleBroadcast.leadingAnchor.constraint(equalTo: subContainerView.leadingAnchor),
  2441. titleBroadcast.trailingAnchor.constraint(equalTo: subContainerView.trailingAnchor),
  2442. ])
  2443. titleBroadcast.font = UIFont.systemFont(ofSize: 14, weight: .semibold)
  2444. titleBroadcast.numberOfLines = 0
  2445. titleBroadcast.attributedText = m[CoreMessage_TMessageKey.TITLE]!.richText()
  2446. titleBroadcast.textColor = .black
  2447. let descBroadcast = UILabel()
  2448. subContainerView.addSubview(descBroadcast)
  2449. descBroadcast.translatesAutoresizingMaskIntoConstraints = false
  2450. let constraintDesc = descBroadcast.bottomAnchor.constraint(equalTo: subContainerView.bottomAnchor)
  2451. if !stringLink.isEmpty{
  2452. constraintDesc.constant = constraintDesc.constant - 30
  2453. }
  2454. if fileType != BroadcastViewController.FILE_TYPE_CHAT {
  2455. constraintDesc.constant = constraintDesc.constant - 260
  2456. }
  2457. NSLayoutConstraint.activate([
  2458. descBroadcast.topAnchor.constraint(equalTo: titleBroadcast.bottomAnchor, constant: 10),
  2459. descBroadcast.leadingAnchor.constraint(equalTo: subContainerView.leadingAnchor),
  2460. descBroadcast.trailingAnchor.constraint(equalTo: subContainerView.trailingAnchor),
  2461. constraintDesc,
  2462. ])
  2463. descBroadcast.font = UIFont.systemFont(ofSize: 12)
  2464. descBroadcast.numberOfLines = 0
  2465. descBroadcast.attributedText = m[CoreMessage_TMessageKey.MESSAGE_TEXT_ENG]!.richText()
  2466. descBroadcast.textColor = .black
  2467. let linkBroadcast = UILabel()
  2468. if !stringLink.isEmpty {
  2469. subContainerView.addSubview(linkBroadcast)
  2470. linkBroadcast.translatesAutoresizingMaskIntoConstraints = false
  2471. NSLayoutConstraint.activate([
  2472. linkBroadcast.topAnchor.constraint(equalTo: descBroadcast.bottomAnchor, constant: 10),
  2473. linkBroadcast.leadingAnchor.constraint(equalTo: subContainerView.leadingAnchor),
  2474. linkBroadcast.trailingAnchor.constraint(equalTo: subContainerView.trailingAnchor),
  2475. ])
  2476. linkBroadcast.font = UIFont.systemFont(ofSize: 12)
  2477. linkBroadcast.isUserInteractionEnabled = true
  2478. linkBroadcast.numberOfLines = 2
  2479. let attributedString = NSMutableAttributedString(string: stringLink, attributes:[NSAttributedString.Key.link: URL(string: stringLink)!])
  2480. linkBroadcast.attributedText = attributedString
  2481. let tap = ObjectGesture(target: self, action: #selector(tapLinkBroadcast))
  2482. tap.message_id = stringLink
  2483. linkBroadcast.addGestureRecognizer(tap)
  2484. }
  2485. let thumb = m[CoreMessage_TMessageKey.THUMB_ID] ?? ""
  2486. let image = m[CoreMessage_TMessageKey.IMAGE_ID] ?? ""
  2487. let video = m[CoreMessage_TMessageKey.VIDEO_ID] ?? ""
  2488. let file = m[CoreMessage_TMessageKey.FILE_ID] ?? ""
  2489. if fileType != BroadcastViewController.FILE_TYPE_CHAT {
  2490. let imageBroadcast = UIImageView()
  2491. subContainerView.addSubview(imageBroadcast)
  2492. imageBroadcast.translatesAutoresizingMaskIntoConstraints = false
  2493. var constImage = imageBroadcast.topAnchor.constraint(equalTo: descBroadcast.bottomAnchor, constant: 10)
  2494. if !stringLink.isEmpty {
  2495. constImage = imageBroadcast.topAnchor.constraint(equalTo: linkBroadcast.bottomAnchor, constant: 10)
  2496. }
  2497. NSLayoutConstraint.activate([
  2498. constImage,
  2499. imageBroadcast.leadingAnchor.constraint(equalTo: subContainerView.leadingAnchor),
  2500. imageBroadcast.trailingAnchor.constraint(equalTo: subContainerView.trailingAnchor),
  2501. imageBroadcast.heightAnchor.constraint(equalToConstant: 250)
  2502. ])
  2503. imageBroadcast.layer.cornerRadius = 10.0
  2504. imageBroadcast.clipsToBounds = true
  2505. if fileType != BroadcastViewController.FILE_TYPE_DOCUMENT {
  2506. imageBroadcast.contentMode = .scaleAspectFill
  2507. imageBroadcast.setImage(name: thumb)
  2508. if fileType == BroadcastViewController.FILE_TYPE_VIDEO {
  2509. let imagePlay = UIImageView(image: UIImage(systemName: "play.circle.fill"))
  2510. imageBroadcast.addSubview(imagePlay)
  2511. imagePlay.clipsToBounds = true
  2512. imagePlay.translatesAutoresizingMaskIntoConstraints = false
  2513. imagePlay.centerYAnchor.constraint(equalTo: imageBroadcast.centerYAnchor).isActive = true
  2514. imagePlay.centerXAnchor.constraint(equalTo: imageBroadcast.centerXAnchor).isActive = true
  2515. imagePlay.widthAnchor.constraint(equalToConstant: 60).isActive = true
  2516. imagePlay.heightAnchor.constraint(equalToConstant: 60).isActive = true
  2517. imagePlay.tintColor = .gray.withAlphaComponent(0.5)
  2518. }
  2519. } else {
  2520. imageBroadcast.image = UIImage(systemName: "doc.fill")
  2521. imageBroadcast.tintColor = .mainColor
  2522. imageBroadcast.contentMode = .scaleAspectFit
  2523. }
  2524. imageBroadcast.actionHandle(controlEvents: .touchUpInside,
  2525. ForAction:{() -> Void in
  2526. let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
  2527. let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
  2528. let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
  2529. if fileType == BroadcastViewController.FILE_TYPE_IMAGE {
  2530. if let dirPath = paths.first {
  2531. let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(image)
  2532. if FileManager.default.fileExists(atPath: imageURL.path) {
  2533. let image = UIImage(contentsOfFile: imageURL.path)
  2534. let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
  2535. previewImageVC.image = image
  2536. previewImageVC.isHiddenTextField = true
  2537. previewImageVC.modalPresentationStyle = .overFullScreen
  2538. previewImageVC.modalTransitionStyle = .crossDissolve
  2539. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2540. UIApplication.shared.visibleViewController?.navigationController?.present(previewImageVC, animated: true, completion: nil)
  2541. } else {
  2542. UIApplication.shared.visibleViewController?.present(previewImageVC, animated: true, completion: nil)
  2543. }
  2544. } else if FileEncryption.shared.isSecureExists(filename: image) {
  2545. do {
  2546. if var data = try FileEncryption.shared.readSecure(filename: image) {
  2547. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: data)
  2548. if dataDecrypt != nil {
  2549. data = dataDecrypt!
  2550. }
  2551. let image = UIImage(data: data)
  2552. let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
  2553. previewImageVC.image = image
  2554. previewImageVC.isHiddenTextField = true
  2555. previewImageVC.modalPresentationStyle = .overFullScreen
  2556. previewImageVC.modalTransitionStyle = .crossDissolve
  2557. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2558. UIApplication.shared.visibleViewController?.navigationController?.present(previewImageVC, animated: true, completion: nil)
  2559. } else {
  2560. UIApplication.shared.visibleViewController?.present(previewImageVC, animated: true, completion: nil)
  2561. }
  2562. }
  2563. } catch {
  2564. }
  2565. } else {
  2566. Download().startHTTP(forKey: image) { (name, progress) in
  2567. guard progress == 100 else {
  2568. return
  2569. }
  2570. DispatchQueue.main.async {
  2571. var image : UIImage?
  2572. if FileManager.default.fileExists(atPath: imageURL.path) {
  2573. image = UIImage(contentsOfFile: imageURL.path)
  2574. }
  2575. else if FileEncryption.shared.isSecureExists(filename: imageURL.lastPathComponent) {
  2576. do {
  2577. if let imageData = try FileEncryption.shared.readSecure(filename: imageURL.lastPathComponent) {
  2578. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: imageData)
  2579. if dataDecrypt == nil {
  2580. image = UIImage(data: imageData)
  2581. } else {
  2582. image = UIImage(data: dataDecrypt!)
  2583. }
  2584. }
  2585. } catch {
  2586. }
  2587. }
  2588. let previewImageVC = PreviewAttachmentImageVideo(nibName: "PreviewAttachmentImageVideo", bundle: Bundle.resourceBundle(for: Nexilis.self))
  2589. previewImageVC.image = image
  2590. previewImageVC.isHiddenTextField = true
  2591. previewImageVC.modalPresentationStyle = .overFullScreen
  2592. previewImageVC.modalTransitionStyle = .crossDissolve
  2593. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2594. UIApplication.shared.visibleViewController?.navigationController?.present(previewImageVC, animated: true, completion: nil)
  2595. } else {
  2596. UIApplication.shared.visibleViewController?.present(previewImageVC, animated: true, completion: nil)
  2597. }
  2598. }
  2599. }
  2600. }
  2601. }
  2602. } else if fileType == BroadcastViewController.FILE_TYPE_VIDEO {
  2603. //https://qmera.io/filepalio/image/
  2604. let player = AVPlayer(url: URL(string: "https://nexilis.io/get_file?account=\(Nexilis.sAPIKey)&image=\(video)")!)
  2605. let playerVC = AVPlayerViewController()
  2606. playerVC.player = player
  2607. playerVC.modalPresentationStyle = .custom
  2608. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2609. UIApplication.shared.visibleViewController?.navigationController?.present(playerVC, animated: true, completion: nil)
  2610. } else {
  2611. UIApplication.shared.visibleViewController?.present(playerVC, animated: true, completion: nil)
  2612. }
  2613. } else if fileType == BroadcastViewController.FILE_TYPE_DOCUMENT {
  2614. if let dirPath = paths.first {
  2615. let fileURL = URL(fileURLWithPath: dirPath).appendingPathComponent(file)
  2616. if FileManager.default.fileExists(atPath: fileURL.path) {
  2617. previewItem = fileURL as NSURL
  2618. let previewController = QLPreviewController()
  2619. let rightBarButton = UIBarButtonItem()
  2620. previewController.navigationItem.rightBarButtonItem = rightBarButton
  2621. previewController.dataSource = self
  2622. previewController.modalPresentationStyle = .overFullScreen
  2623. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2624. UIApplication.shared.visibleViewController?.navigationController?.present(previewController, animated: true, completion: nil)
  2625. } else {
  2626. UIApplication.shared.visibleViewController?.present(previewController, animated: true, completion: nil)
  2627. }
  2628. } else if FileEncryption.shared.isSecureExists(filename: file) {
  2629. do {
  2630. if var docData = try FileEncryption.shared.readSecure(filename: file) {
  2631. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
  2632. if dataDecrypt != nil {
  2633. docData = dataDecrypt!
  2634. }
  2635. let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
  2636. let tempPath = cachesDirectory.appendingPathComponent(file)
  2637. try docData.write(to: tempPath)
  2638. previewItem = tempPath as NSURL
  2639. let previewController = QLPreviewController()
  2640. let rightBarButton = UIBarButtonItem()
  2641. previewController.navigationItem.rightBarButtonItem = rightBarButton
  2642. previewController.dataSource = self
  2643. previewController.modalPresentationStyle = .overFullScreen
  2644. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2645. UIApplication.shared.visibleViewController?.navigationController?.present(previewController, animated: true, completion: nil)
  2646. } else {
  2647. UIApplication.shared.visibleViewController?.present(previewController, animated: true, completion: nil)
  2648. }
  2649. }
  2650. } catch {
  2651. }
  2652. } else {
  2653. Download().startHTTP(forKey: file, isImage: false) { (name, progress) in
  2654. DispatchQueue.main.async {
  2655. guard progress == 100 else {
  2656. return
  2657. }
  2658. do {
  2659. if var docData = try FileEncryption.shared.readSecure(filename: file) {
  2660. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: docData)
  2661. if dataDecrypt != nil {
  2662. docData = dataDecrypt!
  2663. }
  2664. let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
  2665. let tempPath = cachesDirectory.appendingPathComponent(file)
  2666. try docData.write(to: tempPath)
  2667. previewItem = tempPath as NSURL
  2668. let previewController = QLPreviewController()
  2669. let rightBarButton = UIBarButtonItem()
  2670. previewController.navigationItem.rightBarButtonItem = rightBarButton
  2671. previewController.dataSource = self
  2672. previewController.modalPresentationStyle = .overFullScreen
  2673. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2674. UIApplication.shared.visibleViewController?.navigationController?.present(previewController, animated: true, completion: nil)
  2675. } else {
  2676. UIApplication.shared.visibleViewController?.present(previewController, animated: true, completion: nil)
  2677. }
  2678. }
  2679. }
  2680. catch {
  2681. }
  2682. }
  2683. }
  2684. }
  2685. }
  2686. }
  2687. })
  2688. }
  2689. }
  2690. broadcastVC.modalTransitionStyle = .crossDissolve
  2691. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2692. UIApplication.shared.visibleViewController?.navigationController?.present(broadcastVC, animated: true, completion: nil)
  2693. } else {
  2694. UIApplication.shared.visibleViewController?.present(broadcastVC, animated: true, completion: nil)
  2695. }
  2696. }
  2697. }
  2698. public func onReceive(message: TMessage) {
  2699. var dataMessage: [AnyHashable : Any] = [:]
  2700. dataMessage["message"] = message
  2701. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerReceiveChat), object: nil, userInfo: dataMessage)
  2702. if message.getCode() == CoreMessage_TMessageCode.PUSH_CALL_CENTER {
  2703. if User.getDataCanNil(pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)) == nil {
  2704. Nexilis.addFriendSilent(fpin: message.getBody(key: CoreMessage_TMessageKey.L_PIN))
  2705. sleep(1)
  2706. }
  2707. DispatchQueue.main.async {
  2708. if Nexilis.onGoingPushCC.isEmpty {
  2709. var data: [String: String] = [:]
  2710. data["channel"] = message.getBody(key: CoreMessage_TMessageKey.CHANNEL)
  2711. data["l_pin"] = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2712. data["f_display_name"] = message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME)
  2713. Nexilis.onGoingPushCC = data
  2714. } else if Nexilis.onGoingPushCC["f_display_name"] == message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME) {
  2715. return
  2716. }
  2717. let alert = LibAlertController(title: "", message: "\n\n\n\n\n\n\n\n\n\n".localized(), preferredStyle: .alert)
  2718. let newWidth = UIScreen.main.bounds.width * 0.90 - 270
  2719. // update width constraint value for main view
  2720. if let viewWidthConstraint = alert.view.constraints.filter({ return $0.firstAttribute == .width }).first{
  2721. viewWidthConstraint.constant = newWidth
  2722. }
  2723. // update width constraint value for container view
  2724. if let containerViewWidthConstraint = alert.view.subviews.first?.constraints.filter({ return $0.firstAttribute == .width }).first {
  2725. containerViewWidthConstraint.constant = newWidth
  2726. }
  2727. let titleFont = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18), NSAttributedString.Key.foregroundColor: UIColor.black]
  2728. let titleAttrString = NSMutableAttributedString(string: "Call Center".localized(), attributes: titleFont)
  2729. alert.setValue(titleAttrString, forKey: "attributedTitle")
  2730. alert.view.subviews.first?.subviews.first?.subviews.first?.backgroundColor = .lightGray
  2731. alert.view.tintColor = .black
  2732. let rejectAction = UIAlertAction(title: "Pass to other representative".localized(), style: .destructive, handler: {(_) in
  2733. DispatchQueue.global().async {
  2734. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2735. }
  2736. Nexilis.onGoingPushCC.removeAll()
  2737. alert.dismiss(animated: true, completion: nil)
  2738. })
  2739. let acceptAction = UIAlertAction(title: "I'll handle the customer".localized(), style: .default, handler: {(_) in
  2740. let goAudioCall = Nexilis.checkMicPermission()
  2741. if !goAudioCall && message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  2742. let alert = LibAlertController(title: "Attention!".localized(), message: "Please allow microphone permission in your settings".localized(), preferredStyle: .alert)
  2743. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2744. if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
  2745. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  2746. }
  2747. }))
  2748. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2749. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  2750. } else {
  2751. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  2752. }
  2753. DispatchQueue.global().async {
  2754. DispatchQueue.global().async {
  2755. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2756. }
  2757. }
  2758. Nexilis.onGoingPushCC.removeAll()
  2759. return
  2760. }
  2761. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  2762. var permissionCheck = -1
  2763. if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
  2764. permissionCheck = 1
  2765. } else if AVCaptureDevice.authorizationStatus(for: .video) == .denied {
  2766. permissionCheck = 0
  2767. } else {
  2768. Nexilis.dispatch = DispatchGroup()
  2769. Nexilis.dispatch?.enter()
  2770. AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) -> Void in
  2771. if granted == true {
  2772. permissionCheck = 1
  2773. } else {
  2774. permissionCheck = 0
  2775. }
  2776. if let dispatch = Nexilis.dispatch {
  2777. dispatch.leave()
  2778. }
  2779. })
  2780. Nexilis.dispatch?.wait()
  2781. Nexilis.dispatch = nil
  2782. }
  2783. if permissionCheck == 0 {
  2784. let alert = LibAlertController(title: "Attention!".localized(), message: "Please allow camera permission in your settings".localized(), preferredStyle: .alert)
  2785. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2786. if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
  2787. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  2788. }
  2789. }))
  2790. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2791. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  2792. } else {
  2793. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  2794. }
  2795. DispatchQueue.global().async {
  2796. DispatchQueue.global().async {
  2797. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2798. }
  2799. }
  2800. Nexilis.onGoingPushCC.removeAll()
  2801. return
  2802. }
  2803. }
  2804. if UIApplication.shared.visibleViewController is UINavigationController {
  2805. let nc = UIApplication.shared.visibleViewController as! UINavigationController
  2806. if nc.visibleViewController is QmeraStreamingViewController {
  2807. let vc = nc.visibleViewController as! QmeraStreamingViewController
  2808. var alert = LibAlertController(title: "", message: "Are you sure you want to end Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  2809. if !vc.isLive {
  2810. alert = LibAlertController(title: "", message: "Are you sure you want to leave Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  2811. }
  2812. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2813. DispatchQueue.global().async {
  2814. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2815. }
  2816. Nexilis.onGoingPushCC.removeAll()
  2817. alert.dismiss(animated: true, completion: nil)
  2818. }))
  2819. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2820. DispatchQueue.global().async {
  2821. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  2822. vc.sendLeft()
  2823. }
  2824. vc.dismiss(animated: true, completion: {
  2825. acceptCC()
  2826. })
  2827. }))
  2828. nc.present(alert, animated: true, completion: nil)
  2829. // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "isRunningStreaming"), object: nil, userInfo: dataMessage)
  2830. } else if nc.visibleViewController is SeminarViewController {
  2831. let vc = nc.visibleViewController as! SeminarViewController
  2832. var alert = LibAlertController(title: "", message: "Are you sure you want to end Seminar, and open notification?".localized(), preferredStyle: .alert)
  2833. if !vc.isLive {
  2834. alert = LibAlertController(title: "", message: "Are you sure you want to leave Seminar, and open notification?".localized(), preferredStyle: .alert)
  2835. }
  2836. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2837. DispatchQueue.global().async {
  2838. _ = Nexilis.write(message: CoreMessage_TMessageBank.timeOutRequestCallCenter(channel: message.getBody(key: CoreMessage_TMessageKey.CHANNEL), l_pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN)))
  2839. }
  2840. Nexilis.onGoingPushCC.removeAll()
  2841. alert.dismiss(animated: true, completion: nil)
  2842. }))
  2843. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  2844. DispatchQueue.global().async {
  2845. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  2846. vc.sendLeft()
  2847. }
  2848. vc.dismiss(animated: true, completion: {
  2849. acceptCC()
  2850. })
  2851. }))
  2852. nc.present(alert, animated: true, completion: nil)
  2853. // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "isRunningStreaming"), object: nil, userInfo: dataMessage)
  2854. } else {
  2855. acceptCC()
  2856. }
  2857. } else {
  2858. acceptCC()
  2859. }
  2860. func acceptCC() {
  2861. 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))) {
  2862. if (response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "00") {
  2863. Nexilis.onGoingPushCC.removeAll()
  2864. let complaintId = response.getBody(key: CoreMessage_TMessageKey.DATA, default_value: "")
  2865. if !complaintId.isEmpty {
  2866. alert.dismiss(animated: true, completion: nil)
  2867. let idMe = User.getMyPin()!
  2868. SecureUserDefaults.shared.set("\(message.getBody(key: CoreMessage_TMessageKey.L_PIN)),\(idMe),\(complaintId)", forKey: "onGoingCC")
  2869. SecureUserDefaults.shared.set("\(message.getBody(key: CoreMessage_TMessageKey.L_PIN))", forKey: "membersCC")
  2870. SecureUserDefaults.shared.set("\(message.getBody(key: CoreMessage_TMessageKey.CHANNEL))", forKey: "channelCC")
  2871. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "0" {
  2872. let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  2873. editorPersonalVC.isContactCenter = true
  2874. editorPersonalVC.isRequestContactCenter = false
  2875. editorPersonalVC.unique_l_pin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2876. editorPersonalVC.complaintId = complaintId
  2877. editorPersonalVC.channelContactCenter = message.getBody(key: CoreMessage_TMessageKey.CHANNEL)
  2878. editorPersonalVC.fPinContacCenter = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2879. let navigationController = CustomNavigationController(rootViewController: editorPersonalVC)
  2880. navigationController.modalPresentationStyle = .fullScreen
  2881. navigationController.navigationBar.tintColor = .white
  2882. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  2883. navigationController.navigationBar.isTranslucent = false
  2884. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  2885. navigationController.navigationBar.barStyle = .black
  2886. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  2887. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  2888. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  2889. navigationController.navigationBar.titleTextAttributes = textAttributes
  2890. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2891. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2892. } else {
  2893. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2894. }
  2895. } else {
  2896. SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
  2897. DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
  2898. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  2899. let pin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2900. let controller = QmeraAudioViewController()
  2901. controller.user = User.getData(pin: pin)
  2902. controller.isOutgoing = true
  2903. controller.ticketId = complaintId
  2904. controller.modalPresentationStyle = .overCurrentContext
  2905. let navigationController = CustomNavigationController(rootViewController: controller)
  2906. navigationController.modalPresentationStyle = .fullScreen
  2907. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2908. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2909. } else {
  2910. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2911. }
  2912. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  2913. let videoVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
  2914. videoVC.fPin = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  2915. videoVC.users.append(User.getData(pin: message.getBody(key: CoreMessage_TMessageKey.L_PIN))!)
  2916. videoVC.ticketId = complaintId
  2917. let navigationController = CustomNavigationController(rootViewController: videoVC)
  2918. navigationController.modalPresentationStyle = .fullScreen
  2919. if UIApplication.shared.visibleViewController?.navigationController != nil {
  2920. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  2921. } else {
  2922. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  2923. }
  2924. }
  2925. })
  2926. }
  2927. }
  2928. }
  2929. }
  2930. }
  2931. })
  2932. alert.addAction(acceptAction)
  2933. alert.addAction(rejectAction)
  2934. let containerView = UIView(frame: CGRect(x: 20, y: 60, width: alert.view.bounds.size.width * 0.9 - 40, height: 150))
  2935. alert.view.addSubview(containerView)
  2936. containerView.layer.cornerRadius = 10.0
  2937. containerView.clipsToBounds = true
  2938. containerView.backgroundColor = .secondaryColor.withAlphaComponent(0.5)
  2939. let imageProfile = UIImageView()
  2940. containerView.addSubview(imageProfile)
  2941. imageProfile.translatesAutoresizingMaskIntoConstraints = false
  2942. NSLayoutConstraint.activate([
  2943. imageProfile.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 10),
  2944. imageProfile.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -10),
  2945. imageProfile.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 10),
  2946. imageProfile.widthAnchor.constraint(equalToConstant: 100)
  2947. ])
  2948. imageProfile.layer.cornerRadius = 10.0
  2949. imageProfile.clipsToBounds = true
  2950. imageProfile.backgroundColor = .lightGray.withAlphaComponent(0.3)
  2951. imageProfile.tintColor = .secondaryColor
  2952. imageProfile.image = UIImage(systemName: "person")
  2953. if message.getBody(key: CoreMessage_TMessageKey.THUMB_ID) != "" {
  2954. imageProfile.setImage(name: message.getBody(key: CoreMessage_TMessageKey.THUMB_ID))
  2955. imageProfile.contentMode = .scaleAspectFill
  2956. }
  2957. let labelName = UILabel()
  2958. containerView.addSubview(labelName)
  2959. labelName.translatesAutoresizingMaskIntoConstraints = false
  2960. NSLayoutConstraint.activate([
  2961. labelName.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 15),
  2962. labelName.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2963. ])
  2964. labelName.font = UIFont.systemFont(ofSize: 12)
  2965. labelName.text = "Name".localized()
  2966. labelName.textColor = .mainColor
  2967. let valueName = UILabel()
  2968. containerView.addSubview(valueName)
  2969. valueName.translatesAutoresizingMaskIntoConstraints = false
  2970. NSLayoutConstraint.activate([
  2971. valueName.topAnchor.constraint(equalTo: labelName.bottomAnchor),
  2972. valueName.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2973. ])
  2974. valueName.font = UIFont.systemFont(ofSize: 12)
  2975. valueName.text = message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME)
  2976. valueName.textColor = .mainColor
  2977. let labelType = UILabel()
  2978. containerView.addSubview(labelType)
  2979. labelType.translatesAutoresizingMaskIntoConstraints = false
  2980. NSLayoutConstraint.activate([
  2981. labelType.topAnchor.constraint(equalTo: valueName.bottomAnchor, constant: 5),
  2982. labelType.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2983. ])
  2984. labelType.font = UIFont.systemFont(ofSize: 12)
  2985. labelType.text = "Request Type".localized()
  2986. labelType.textColor = .mainColor
  2987. let valueType = UILabel()
  2988. containerView.addSubview(valueType)
  2989. valueType.translatesAutoresizingMaskIntoConstraints = false
  2990. NSLayoutConstraint.activate([
  2991. valueType.topAnchor.constraint(equalTo: labelType.bottomAnchor),
  2992. valueType.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  2993. ])
  2994. valueType.font = UIFont.systemFont(ofSize: 12)
  2995. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "0" {
  2996. valueType.text = "Chat".localized()
  2997. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  2998. valueType.text = "Audio Call".localized()
  2999. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  3000. valueType.text = "Video Call".localized()
  3001. } else {
  3002. valueType.text = "Email".localized()
  3003. }
  3004. valueType.textColor = .mainColor
  3005. let labelIdentity = UILabel()
  3006. containerView.addSubview(labelIdentity)
  3007. labelIdentity.translatesAutoresizingMaskIntoConstraints = false
  3008. NSLayoutConstraint.activate([
  3009. labelIdentity.topAnchor.constraint(equalTo: valueType.bottomAnchor, constant: 5),
  3010. labelIdentity.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  3011. ])
  3012. labelIdentity.font = UIFont.systemFont(ofSize: 12)
  3013. labelIdentity.text = "Complaint ID".localized()
  3014. labelIdentity.textColor = .mainColor
  3015. let valueIdentity = UILabel()
  3016. containerView.addSubview(valueIdentity)
  3017. valueIdentity.translatesAutoresizingMaskIntoConstraints = false
  3018. NSLayoutConstraint.activate([
  3019. valueIdentity.topAnchor.constraint(equalTo: labelIdentity.bottomAnchor),
  3020. valueIdentity.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5),
  3021. valueIdentity.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
  3022. ])
  3023. valueIdentity.font = UIFont.systemFont(ofSize: 12)
  3024. valueIdentity.text = message.getBody(key: CoreMessage_TMessageKey.DATA)
  3025. valueIdentity.numberOfLines = 0
  3026. valueIdentity.textColor = .mainColor
  3027. var isShowAlert: Int?
  3028. let canShow = UIApplication.shared.visibleViewController
  3029. if canShow != nil && !(canShow is UINavigationController) {
  3030. if !(canShow is EditorPersonal) && !(canShow is QmeraAudioViewController) && !(canShow is QmeraVideoViewController) {
  3031. isShowAlert = 0
  3032. } else {
  3033. isShowAlert = 3
  3034. }
  3035. } else if canShow != nil {
  3036. if canShow is UINavigationController {
  3037. let canShowNC = canShow as! UINavigationController
  3038. if !(canShowNC.visibleViewController is EditorPersonal) && !(canShowNC.visibleViewController is QmeraAudioViewController) && !(canShowNC.visibleViewController is QmeraVideoViewController) {
  3039. isShowAlert = 0
  3040. } else {
  3041. isShowAlert = 3
  3042. }
  3043. } else {
  3044. isShowAlert = 0
  3045. }
  3046. }
  3047. DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(isShowAlert!), execute: {
  3048. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3049. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  3050. } else {
  3051. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  3052. }
  3053. })
  3054. }
  3055. } else if message.getCode() == CoreMessage_TMessageCode.ACCEPT_CALL_CENTER {
  3056. let fPinContacCenter = message.getBody(key: CoreMessage_TMessageKey.F_PIN)
  3057. let requester = message.getBody(key: CoreMessage_TMessageKey.UPLINE_PIN)
  3058. let complaintId = message.getBody(key: CoreMessage_TMessageKey.DATA)
  3059. let onGoingCC: String = SecureUserDefaults.shared.value(forKey: "onGoingCC") ?? ""
  3060. if !requester.isEmpty && onGoingCC.isEmpty {
  3061. SecureUserDefaults.shared.set("\(requester),\(fPinContacCenter),\(complaintId)", forKey: "onGoingCC")
  3062. SecureUserDefaults.shared.set("\(fPinContacCenter)", forKey: "membersCC")
  3063. }
  3064. } else if message.getCode() == CoreMessage_TMessageCode.INVITE_TO_ROOM_CONTACT_CENTER {
  3065. if listCCIdInv.contains(message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)) {
  3066. return
  3067. }
  3068. listCCIdInv.append(message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID))
  3069. DispatchQueue.main.async {
  3070. let alert = LibAlertController(title: "", message: "\n\n\n\n\n\n\n\n\n\n".localized(), preferredStyle: .alert)
  3071. let newWidth = UIScreen.main.bounds.width * 0.90 - 270
  3072. // update width constraint value for main view
  3073. if let viewWidthConstraint = alert.view.constraints.filter({ return $0.firstAttribute == .width }).first{
  3074. viewWidthConstraint.constant = newWidth
  3075. }
  3076. // update width constraint value for container view
  3077. if let containerViewWidthConstraint = alert.view.subviews.first?.constraints.filter({ return $0.firstAttribute == .width }).first {
  3078. containerViewWidthConstraint.constant = newWidth
  3079. }
  3080. let titleFont = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18), NSAttributedString.Key.foregroundColor: UIColor.black]
  3081. let titleAttrString = NSMutableAttributedString(string: "You're invited to\nCall Center".localized(), attributes: titleFont)
  3082. alert.setValue(titleAttrString, forKey: "attributedTitle")
  3083. alert.view.subviews.first?.subviews.first?.subviews.first?.backgroundColor = .lightGray
  3084. alert.view.tintColor = .black
  3085. let rejectAction = UIAlertAction(title: "Reject".localized(), style: .destructive, handler: {(_) in
  3086. listCCIdInv.removeAll(where: {$0 == message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)})
  3087. DispatchQueue.global().async {
  3088. 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))) {
  3089. if result.isOk() {
  3090. return
  3091. }
  3092. }
  3093. }
  3094. alert.dismiss(animated: true, completion: nil)
  3095. })
  3096. let acceptAction = UIAlertAction(title: "Accept".localized(), style: .default, handler: {(_) in
  3097. listCCIdInv.removeAll(where: {$0 == message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)})
  3098. let goAudioCall = Nexilis.checkMicPermission()
  3099. if !goAudioCall && message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  3100. let alert = LibAlertController(title: "Attention!".localized(), message: "Please allow microphone permission in your settings".localized(), preferredStyle: .alert)
  3101. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3102. if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
  3103. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  3104. }
  3105. }))
  3106. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3107. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  3108. } else {
  3109. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  3110. }
  3111. DispatchQueue.global().async {
  3112. 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))) {
  3113. if result.isOk() {
  3114. return
  3115. }
  3116. }
  3117. }
  3118. return
  3119. }
  3120. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  3121. var permissionCheck = -1
  3122. if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
  3123. permissionCheck = 1
  3124. } else if AVCaptureDevice.authorizationStatus(for: .video) == .denied {
  3125. permissionCheck = 0
  3126. } else {
  3127. Nexilis.dispatch = DispatchGroup()
  3128. Nexilis.dispatch?.enter()
  3129. AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) -> Void in
  3130. if granted == true {
  3131. permissionCheck = 1
  3132. } else {
  3133. permissionCheck = 0
  3134. }
  3135. if let dispatch = Nexilis.dispatch {
  3136. dispatch.leave()
  3137. }
  3138. })
  3139. Nexilis.dispatch?.wait()
  3140. Nexilis.dispatch = nil
  3141. }
  3142. if permissionCheck == 0 {
  3143. let alert = LibAlertController(title: "Attention!".localized(), message: "Please allow camera permission in your settings".localized(), preferredStyle: .alert)
  3144. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3145. if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
  3146. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  3147. }
  3148. }))
  3149. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3150. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  3151. } else {
  3152. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  3153. }
  3154. DispatchQueue.global().async {
  3155. 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))) {
  3156. if result.isOk() {
  3157. return
  3158. }
  3159. }
  3160. }
  3161. return
  3162. }
  3163. }
  3164. if UIApplication.shared.visibleViewController is UINavigationController {
  3165. let nc = UIApplication.shared.visibleViewController as! UINavigationController
  3166. if nc.visibleViewController is QmeraStreamingViewController {
  3167. let vc = nc.visibleViewController as! QmeraStreamingViewController
  3168. var alert = LibAlertController(title: "", message: "Are you sure you want to end Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  3169. if !vc.isLive {
  3170. alert = LibAlertController(title: "", message: "Are you sure you want to leave Live Streaming, and open notification?".localized(), preferredStyle: .alert)
  3171. }
  3172. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3173. DispatchQueue.global().async {
  3174. 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))) {
  3175. if result.isOk() {
  3176. return
  3177. }
  3178. }
  3179. }
  3180. alert.dismiss(animated: true, completion: nil)
  3181. }))
  3182. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3183. DispatchQueue.global().async {
  3184. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  3185. vc.sendLeft()
  3186. }
  3187. vc.dismiss(animated: true, completion: {
  3188. acceptCC()
  3189. })
  3190. }))
  3191. nc.present(alert, animated: true, completion: nil)
  3192. } else if nc.visibleViewController is SeminarViewController {
  3193. let vc = nc.visibleViewController as! SeminarViewController
  3194. var alert = LibAlertController(title: "", message: "Are you sure you want to end Seminar, and open notification?".localized(), preferredStyle: .alert)
  3195. if !vc.isLive {
  3196. alert = LibAlertController(title: "", message: "Are you sure you want to leave Seminar, and open notification?".localized(), preferredStyle: .alert)
  3197. }
  3198. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3199. DispatchQueue.global().async {
  3200. 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))) {
  3201. if result.isOk() {
  3202. return
  3203. }
  3204. }
  3205. }
  3206. alert.dismiss(animated: true, completion: nil)
  3207. }))
  3208. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: { _ in
  3209. DispatchQueue.global().async {
  3210. API.terminateBC(sBroadcasterID: vc.isLive ? nil : vc.data)
  3211. vc.sendLeft()
  3212. }
  3213. vc.dismiss(animated: true, completion: {
  3214. acceptCC()
  3215. })
  3216. }))
  3217. nc.present(alert, animated: true, completion: nil)
  3218. } else {
  3219. acceptCC()
  3220. }
  3221. } else {
  3222. acceptCC()
  3223. }
  3224. func acceptCC() {
  3225. 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))) {
  3226. if result.isOk() {
  3227. let requester = result.getBody(key: CoreMessage_TMessageKey.UPLINE_PIN)
  3228. let officer = result.getBody(key: CoreMessage_TMessageKey.FRIEND_FPIN)
  3229. let data = result.getBody(key: CoreMessage_TMessageKey.DATA)
  3230. let complaintId = message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)
  3231. SecureUserDefaults.shared.set("\(requester),\(officer),\(complaintId)", forKey: "onGoingCC")
  3232. SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
  3233. if !data.isEmpty {
  3234. if let jsonArray = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [AnyObject] {
  3235. var members = ""
  3236. var user : [User] = []
  3237. let idMe = User.getMyPin()!
  3238. for json in jsonArray {
  3239. if "\(json)" != idMe {
  3240. if let userData = User.getData(pin: "\(json)") {
  3241. user.append(userData)
  3242. } else {
  3243. Nexilis.addFriendSilent(fpin: "\(json)")
  3244. DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
  3245. if let userData = User.getData(pin: "\(json)") {
  3246. user.append(userData)
  3247. }
  3248. })
  3249. }
  3250. if members.isEmpty {
  3251. members = "\(json)"
  3252. } else {
  3253. members += ",\(json)"
  3254. }
  3255. }
  3256. }
  3257. SecureUserDefaults.shared.set("\(members)", forKey: "membersCC")
  3258. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "0" {
  3259. let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  3260. editorPersonalVC.hidesBottomBarWhenPushed = true
  3261. editorPersonalVC.unique_l_pin = officer
  3262. editorPersonalVC.fromNotification = true
  3263. editorPersonalVC.isContactCenter = true
  3264. editorPersonalVC.fPinContacCenter = members
  3265. editorPersonalVC.complaintId = complaintId
  3266. editorPersonalVC.onGoingCC = true
  3267. editorPersonalVC.isRequestContactCenter = false
  3268. editorPersonalVC.users = user
  3269. let navigationController = CustomNavigationController(rootViewController: editorPersonalVC)
  3270. navigationController.modalPresentationStyle = .fullScreen
  3271. navigationController.navigationBar.tintColor = .white
  3272. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  3273. navigationController.navigationBar.isTranslucent = false
  3274. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  3275. navigationController.navigationBar.barStyle = .black
  3276. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  3277. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  3278. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  3279. navigationController.navigationBar.titleTextAttributes = textAttributes
  3280. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3281. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  3282. } else {
  3283. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  3284. }
  3285. } else {
  3286. SecureUserDefaults.shared.set("\(Date().currentTimeMillis())", forKey: "startTimeCC")
  3287. DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
  3288. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  3289. let pin = officer
  3290. let controller = QmeraAudioViewController()
  3291. controller.user = User.getData(pin: pin)
  3292. controller.isOutgoing = false
  3293. controller.ticketId = complaintId
  3294. controller.modalPresentationStyle = .overCurrentContext
  3295. let navigationController = CustomNavigationController(rootViewController: controller)
  3296. navigationController.modalPresentationStyle = .fullScreen
  3297. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3298. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  3299. } else {
  3300. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  3301. }
  3302. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  3303. let videoVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
  3304. videoVC.fPin = officer
  3305. videoVC.users.append(User.getData(pin: officer)!)
  3306. videoVC.ticketId = complaintId
  3307. videoVC.isInisiator = false
  3308. videoVC.isAutoAccept = true
  3309. let navigationController = CustomNavigationController(rootViewController: videoVC)
  3310. navigationController.modalPresentationStyle = .fullScreen
  3311. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3312. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  3313. } else {
  3314. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  3315. }
  3316. }
  3317. })
  3318. }
  3319. }
  3320. }
  3321. } else {
  3322. let imageView = UIImageView(image: UIImage(systemName: "info.circle"))
  3323. imageView.tintColor = .white
  3324. 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)
  3325. banner.show()
  3326. }
  3327. }
  3328. }
  3329. })
  3330. alert.addAction(rejectAction)
  3331. alert.addAction(acceptAction)
  3332. let containerView = UIView(frame: CGRect(x: 50, y: 80, width: alert.view.bounds.size.width * 0.9 - 100, height: 150))
  3333. alert.view.addSubview(containerView)
  3334. containerView.layer.cornerRadius = 10.0
  3335. containerView.clipsToBounds = true
  3336. containerView.backgroundColor = .secondaryColor.withAlphaComponent(0.5)
  3337. let userData = User.getData(pin: message.getPIN())
  3338. let imageProfile = UIImageView()
  3339. containerView.addSubview(imageProfile)
  3340. imageProfile.translatesAutoresizingMaskIntoConstraints = false
  3341. NSLayoutConstraint.activate([
  3342. imageProfile.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 10),
  3343. imageProfile.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -10),
  3344. imageProfile.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 10),
  3345. imageProfile.widthAnchor.constraint(equalToConstant: 100)
  3346. ])
  3347. imageProfile.layer.cornerRadius = 10.0
  3348. imageProfile.clipsToBounds = true
  3349. imageProfile.backgroundColor = .lightGray.withAlphaComponent(0.3)
  3350. imageProfile.tintColor = .secondaryColor
  3351. imageProfile.image = UIImage(systemName: "person")
  3352. if userData!.thumb != "" {
  3353. imageProfile.setImage(name: userData!.thumb)
  3354. imageProfile.contentMode = .scaleAspectFill
  3355. }
  3356. let labelName = UILabel()
  3357. containerView.addSubview(labelName)
  3358. labelName.translatesAutoresizingMaskIntoConstraints = false
  3359. NSLayoutConstraint.activate([
  3360. labelName.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 15),
  3361. labelName.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  3362. ])
  3363. labelName.font = UIFont.systemFont(ofSize: 12)
  3364. labelName.text = "Name".localized()
  3365. labelName.textColor = .mainColor
  3366. let valueName = UILabel()
  3367. containerView.addSubview(valueName)
  3368. valueName.translatesAutoresizingMaskIntoConstraints = false
  3369. NSLayoutConstraint.activate([
  3370. valueName.topAnchor.constraint(equalTo: labelName.bottomAnchor),
  3371. valueName.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  3372. ])
  3373. valueName.font = UIFont.systemFont(ofSize: 12)
  3374. valueName.text = userData!.fullName
  3375. valueName.textColor = .mainColor
  3376. let labelType = UILabel()
  3377. containerView.addSubview(labelType)
  3378. labelType.translatesAutoresizingMaskIntoConstraints = false
  3379. NSLayoutConstraint.activate([
  3380. labelType.topAnchor.constraint(equalTo: valueName.bottomAnchor, constant: 5),
  3381. labelType.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  3382. ])
  3383. labelType.font = UIFont.systemFont(ofSize: 12)
  3384. labelType.text = "Request Type".localized()
  3385. labelType.textColor = .mainColor
  3386. let valueType = UILabel()
  3387. containerView.addSubview(valueType)
  3388. valueType.translatesAutoresizingMaskIntoConstraints = false
  3389. NSLayoutConstraint.activate([
  3390. valueType.topAnchor.constraint(equalTo: labelType.bottomAnchor),
  3391. valueType.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  3392. ])
  3393. valueType.font = UIFont.systemFont(ofSize: 12)
  3394. if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "0" {
  3395. valueType.text = "Chat".localized()
  3396. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "1" {
  3397. valueType.text = "Audio Call".localized()
  3398. } else if message.getBody(key: CoreMessage_TMessageKey.CHANNEL) == "2" {
  3399. valueType.text = "Video Call".localized()
  3400. } else {
  3401. valueType.text = "Email".localized()
  3402. }
  3403. valueType.textColor = .mainColor
  3404. let labelIdentity = UILabel()
  3405. containerView.addSubview(labelIdentity)
  3406. labelIdentity.translatesAutoresizingMaskIntoConstraints = false
  3407. NSLayoutConstraint.activate([
  3408. labelIdentity.topAnchor.constraint(equalTo: valueType.bottomAnchor, constant: 5),
  3409. labelIdentity.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5)
  3410. ])
  3411. labelIdentity.font = UIFont.systemFont(ofSize: 12)
  3412. labelIdentity.text = "Complaint ID".localized()
  3413. labelIdentity.textColor = .mainColor
  3414. let valueIdentity = UILabel()
  3415. containerView.addSubview(valueIdentity)
  3416. valueIdentity.translatesAutoresizingMaskIntoConstraints = false
  3417. NSLayoutConstraint.activate([
  3418. valueIdentity.topAnchor.constraint(equalTo: labelIdentity.bottomAnchor),
  3419. valueIdentity.leadingAnchor.constraint(equalTo: imageProfile.trailingAnchor, constant: 5),
  3420. valueIdentity.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
  3421. ])
  3422. valueIdentity.font = UIFont.systemFont(ofSize: 12)
  3423. valueIdentity.text = message.getBody(key: CoreMessage_TMessageKey.CALL_CENTER_ID)
  3424. valueIdentity.numberOfLines = 0
  3425. valueIdentity.textColor = .mainColor
  3426. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3427. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  3428. } else {
  3429. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  3430. }
  3431. }
  3432. } 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.getBody(key: CoreMessage_TMessageKey.MERCHANT_NAME).isEmpty {
  3433. let m = message.mBodies
  3434. if !message.getBody(key: CoreMessage_TMessageKey.MERCHANT_NAME).isEmpty {
  3435. // Utils.setDebugBC(value: m)
  3436. DispatchQueue.main.async {
  3437. if !Nexilis.broadcastList.isEmpty {
  3438. Nexilis.broadcastList.append(m)
  3439. } else {
  3440. Nexilis.broadcastList.append(m)
  3441. Nexilis.shared.showBroadcastMessage(m: m)
  3442. }
  3443. }
  3444. return
  3445. }
  3446. if !Nexilis.showLibraryNotification || APIS.checkAppStateisBackground() || APIS.stopNotif {
  3447. return
  3448. }
  3449. let sender = message.getBody(key: CoreMessage_TMessageKey.F_PIN)
  3450. let me = User.getMyPin()!
  3451. if(sender != me) {
  3452. let inEditorPersonal: String? = SecureUserDefaults.shared.value(forKey: "inEditorPersonal") ?? nil
  3453. let inEditorGroup: [String]? = SecureUserDefaults.shared.value(forKey: "inEditorGroup") ?? nil
  3454. var text = message.getBody(key: CoreMessage_TMessageKey.MESSAGE_TEXT)
  3455. let imageId = CoreMessage_TMessageKey.IMAGE_ID
  3456. let videoId = CoreMessage_TMessageKey.VIDEO_ID
  3457. let fileId = CoreMessage_TMessageKey.FILE_ID
  3458. let audioId = CoreMessage_TMessageKey.AUDIO_ID
  3459. let attachmentFlag = CoreMessage_TMessageKey.ATTACHMENT_FLAG
  3460. let messageScopeId = CoreMessage_TMessageKey.MESSAGE_SCOPE_ID
  3461. let messageText = CoreMessage_TMessageKey.MESSAGE_TEXT
  3462. let credential = CoreMessage_TMessageKey.CREDENTIAL
  3463. let gif_id = CoreMessage_TMessageKey.GIF_ID
  3464. let is_secret = CoreMessage_TMessageKey.IS_SECRET
  3465. if message.getBody(key: is_secret) == "1" {
  3466. text = "You got messages..."
  3467. } else if message.getBody(key: gif_id) != "" {
  3468. text = "Sent GIF 🎬"
  3469. } else if !message.getBody(key: imageId).isEmpty {
  3470. text = "Sent Image 📷"
  3471. } else if message.getBody(key: attachmentFlag) == "11" {
  3472. text = "Sent Sticker ❤️"
  3473. } else if !message.getBody(key: videoId).isEmpty {
  3474. text = "Sent Video 📹"
  3475. } else if !message.getBody(key: fileId).isEmpty {
  3476. if message.getBody(key: messageScopeId) == MessageScope.FORM {
  3477. text = "Sent Form 📄"
  3478. } else {
  3479. text = "Sent File 📄"
  3480. }
  3481. } else if !message.getBody(key: audioId).isEmpty {
  3482. text = "Sent Audio ♫"
  3483. } else if message.getBody(key: messageText).contains("Share%20location%20") {
  3484. text = "Sent Location 📌"
  3485. } else if message.getBody(key: attachmentFlag) == "27" {
  3486. text = "Sent Live Streaming"
  3487. } else if message.getBody(key: attachmentFlag) == "26" {
  3488. text = "Sent Seminar"
  3489. } else if message.getBody(key: attachmentFlag) == "25" {
  3490. text = "Sent Video Conference Room"
  3491. } else if message.getBody(key: attachmentFlag) == "24" {
  3492. text = "Sent Quiz"
  3493. } else if message.getBody(key: credential) == "1" {
  3494. text = "Sent Confidential Message"
  3495. }
  3496. var nameUser: String?
  3497. var profile = ""
  3498. var threadIdentifier = sender
  3499. let onGoingCC: String = SecureUserDefaults.shared.value(forKey: "onGoingCC") ?? ""
  3500. if !onGoingCC.isEmpty {
  3501. return
  3502. }
  3503. // if Utils.inTabChats{
  3504. // return
  3505. // }
  3506. if message.getBody(key: messageScopeId) == MessageScope.WHISPER || message.getBody(key: messageScopeId) == MessageScope.FORM || message.getBody(key: messageScopeId) == MessageScope.CHATROOM {
  3507. if inEditorPersonal == sender || (inEditorPersonal != nil && inEditorPersonal!.contains(",")) {
  3508. return
  3509. }
  3510. if(nameUser == nil) {
  3511. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  3512. do {
  3513. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name, image_id FROM BUDDY WHERE f_pin='\(String(describing: sender))'") {
  3514. while cursor.next() {
  3515. let first_name = cursor.string(forColumnIndex: 0)!
  3516. let last_name = cursor.string(forColumnIndex: 1)!
  3517. nameUser = "\(first_name) \(last_name)".trimmingCharacters(in: .whitespaces)
  3518. profile = cursor.string(forColumnIndex: 2)!
  3519. }
  3520. cursor.close()
  3521. }
  3522. } catch {
  3523. rollback.pointee = true
  3524. print("Access database error: \(error.localizedDescription)")
  3525. }
  3526. })
  3527. }
  3528. } else {
  3529. let idGroup = message.getBody(key: CoreMessage_TMessageKey.L_PIN)
  3530. var topicGroup: String?
  3531. var idTopic: String?
  3532. if !message.getBody(key: CoreMessage_TMessageKey.CHAT_ID).isEmpty {
  3533. idTopic = message.getBody(key: CoreMessage_TMessageKey.CHAT_ID)
  3534. }
  3535. if (idTopic == nil) {
  3536. idTopic = "Lounge"
  3537. topicGroup = "Lounge"
  3538. } else {
  3539. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  3540. do {
  3541. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT title FROM DISCUSSION_FORUM WHERE chat_id='\(idTopic!)'") {
  3542. while cursor.next() {
  3543. let title = cursor.string(forColumnIndex: 0)
  3544. topicGroup = title
  3545. }
  3546. cursor.close()
  3547. }
  3548. } catch {
  3549. rollback.pointee = true
  3550. print("Access database error: \(error.localizedDescription)")
  3551. }
  3552. })
  3553. }
  3554. if (inEditorGroup != nil) {
  3555. let editorIdGroup = inEditorGroup![0]
  3556. let editorIdTopic = inEditorGroup![1]
  3557. var idTempTopic = idTopic
  3558. if (idTempTopic == "Lounge") {
  3559. idTempTopic = ""
  3560. }
  3561. if (editorIdGroup == idGroup && editorIdTopic == idTempTopic) {
  3562. return
  3563. }
  3564. }
  3565. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  3566. do {
  3567. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_name, image_id FROM GROUPZ WHERE group_id='\(idGroup)'") {
  3568. while cursor.next() {
  3569. let f_name = cursor.string(forColumnIndex: 0)
  3570. var senderName = message.getBody(key: CoreMessage_TMessageKey.F_DISPLAY_NAME)
  3571. if senderName.isEmpty {
  3572. senderName = "Bot"
  3573. }
  3574. nameUser =
  3575. "\(senderName) \u{2022} \(f_name!)(\(topicGroup!))"
  3576. profile = cursor.string(forColumnIndex: 1)!
  3577. }
  3578. cursor.close()
  3579. }
  3580. } catch {
  3581. rollback.pointee = true
  3582. print("Access database error: \(error.localizedDescription)")
  3583. }
  3584. })
  3585. if idTopic == "Lounge" {
  3586. threadIdentifier = idGroup
  3587. } else {
  3588. threadIdentifier = idTopic!
  3589. }
  3590. }
  3591. if nameUser == nil && threadIdentifier == "-999" {
  3592. nameUser = "Bot"
  3593. }
  3594. DispatchQueue.main.async { [self] in
  3595. let container = UIView()
  3596. container.backgroundColor = .gray
  3597. let profileImage = UIImageView()
  3598. profileImage.frame.size = CGSize(width: 60, height: 60)
  3599. container.addSubview(profileImage)
  3600. profileImage.translatesAutoresizingMaskIntoConstraints = false
  3601. NSLayoutConstraint.activate([
  3602. profileImage.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 8.0),
  3603. profileImage.centerYAnchor.constraint(equalTo: container.centerYAnchor),
  3604. profileImage.widthAnchor.constraint(equalToConstant: 60),
  3605. profileImage.heightAnchor.constraint(equalToConstant: 60),
  3606. ])
  3607. let title = UILabel()
  3608. container.addSubview(title)
  3609. title.translatesAutoresizingMaskIntoConstraints = false
  3610. NSLayoutConstraint.activate([
  3611. title.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 8.0),
  3612. title.topAnchor.constraint(equalTo: container.topAnchor, constant: 20.0),
  3613. ])
  3614. title.font = UIFont.systemFont(ofSize: 14)
  3615. title.text = nameUser ?? "Unknown"
  3616. title.textColor = .white
  3617. let subtitle = UILabel()
  3618. container.addSubview(subtitle)
  3619. subtitle.translatesAutoresizingMaskIntoConstraints = false
  3620. NSLayoutConstraint.activate([
  3621. subtitle.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 8.0),
  3622. subtitle.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -15.0),
  3623. subtitle.topAnchor.constraint(equalTo: title.bottomAnchor),
  3624. ])
  3625. subtitle.font = UIFont.systemFont(ofSize: 12)
  3626. subtitle.attributedText = text.richText()
  3627. subtitle.textColor = .white
  3628. if floating != nil {
  3629. return
  3630. }
  3631. if UIApplication.shared.visibleViewController is UINavigationController {
  3632. let nc = UIApplication.shared.visibleViewController as! UINavigationController
  3633. if nc.visibleViewController is QmeraStreamingViewController {
  3634. return
  3635. } else if nc.visibleViewController is SeminarViewController {
  3636. return
  3637. }
  3638. }
  3639. if UIApplication.shared.visibleViewController is UIAlertController {
  3640. return
  3641. }
  3642. displayNotif()
  3643. func displayNotif() {
  3644. floating = FloatingNotificationBanner(customView: container)
  3645. floating.bannerHeight = 100.0
  3646. floating.transparency = 0.9
  3647. if threadIdentifier == "-999" {
  3648. if !Utils.getIconDock().isEmpty {
  3649. 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
  3650. if dataImage != nil {
  3651. profileImage.image = UIImage(data: dataImage!)
  3652. }
  3653. } else {
  3654. profileImage.image = UIImage(named: "pb_button", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
  3655. }
  3656. } else if profile != "" {
  3657. profileImage.circle()
  3658. do {
  3659. let documentDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  3660. let file = documentDir.appendingPathComponent(profile)
  3661. if FileManager().fileExists(atPath: file.path) {
  3662. profileImage.image = UIImage(contentsOfFile: file.path)
  3663. profileImage.backgroundColor = .clear
  3664. } else {
  3665. Download().startHTTP(forKey: profile) { (name, progress) in
  3666. guard progress == 100 else {
  3667. return
  3668. }
  3669. DispatchQueue.main.async { [self] in
  3670. profileImage.image = UIImage(contentsOfFile: file.path)
  3671. profileImage.backgroundColor = .clear
  3672. if !onGoingCC.isEmpty {
  3673. floating.autoDismiss = false
  3674. }
  3675. 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)
  3676. floating.onTap = {
  3677. self.floating = nil
  3678. showNotif()
  3679. }
  3680. var soundId: String = SecureUserDefaults.shared.value(forKey: "newNotifSoundPersonal") ?? "001:Nexilis Message (Default)"
  3681. if message.getBody(key: CoreMessage_TMessageKey.MESSAGE_SCOPE_ID) == MessageScope.GROUP {
  3682. soundId = SecureUserDefaults.shared.value(forKey: "newNotifSoundGroup") ?? "001:Nexilis Message (Default)"
  3683. }
  3684. do {
  3685. var nameSound = soundId.components(separatedBy: ":")[1].replacingOccurrences(of: " ", with: "_")
  3686. var fromPref = false
  3687. if nameSound.contains("_(Default)") {
  3688. if !Utils.getDefaultIncomingMsg().isEmpty {
  3689. nameSound = Utils.getDefaultIncomingMsg()
  3690. fromPref = true
  3691. } else {
  3692. nameSound = nameSound.replacingOccurrences(of: "_(Default)", with: "")
  3693. }
  3694. }
  3695. var soundURL: URL?
  3696. if fromPref {
  3697. let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
  3698. let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
  3699. let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
  3700. if let dirPath = paths.first {
  3701. let audioURL = URL(fileURLWithPath: dirPath).appendingPathComponent(nameSound)
  3702. if !FileManager.default.fileExists(atPath: audioURL.path) && !FileEncryption.shared.isSecureExists(filename: nameSound) {
  3703. Download().startHTTP(forKey: nameSound,downloadUrl: Utils.getURLBase() + "filepalio/ringtone/") { (name, progress) in
  3704. guard progress == 100 else {
  3705. return
  3706. }
  3707. playAudio()
  3708. }
  3709. } else {
  3710. playAudio()
  3711. }
  3712. func playAudio() {
  3713. if FileManager.default.fileExists(atPath: audioURL.path) {
  3714. do {
  3715. do {
  3716. try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
  3717. try AVAudioSession.sharedInstance().setActive(true)
  3718. } catch {
  3719. }
  3720. Nexilis.sharedAudioPlayer = try AVAudioPlayer(contentsOf: audioURL)
  3721. Nexilis.sharedAudioPlayer?.prepareToPlay()
  3722. Nexilis.sharedAudioPlayer?.play()
  3723. } catch {
  3724. }
  3725. } else if FileEncryption.shared.isSecureExists(filename: nameSound) {
  3726. do {
  3727. if var audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
  3728. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
  3729. if dataDecrypt != nil {
  3730. audioData = dataDecrypt!
  3731. }
  3732. let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
  3733. let tempPath = cachesDirectory.appendingPathComponent(nameSound)
  3734. try audioData.write(to: tempPath)
  3735. do {
  3736. do {
  3737. try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
  3738. try AVAudioSession.sharedInstance().setActive(true)
  3739. } catch {
  3740. }
  3741. Nexilis.sharedAudioPlayer = try AVAudioPlayer(contentsOf: tempPath)
  3742. Nexilis.sharedAudioPlayer?.prepareToPlay()
  3743. Nexilis.sharedAudioPlayer?.play()
  3744. } catch {
  3745. }
  3746. }
  3747. } catch {
  3748. }
  3749. }
  3750. }
  3751. }
  3752. } else {
  3753. soundURL = Bundle.resourceBundle(for: Nexilis.self).url(forResource: nameSound, withExtension: "mp3")
  3754. if soundURL == nil {
  3755. soundURL = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: nameSound, withExtension: "mp3")
  3756. }
  3757. do {
  3758. do {
  3759. try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
  3760. try AVAudioSession.sharedInstance().setActive(true)
  3761. } catch {
  3762. }
  3763. Nexilis.sharedAudioPlayer = try AVAudioPlayer(contentsOf: soundURL!)
  3764. Nexilis.sharedAudioPlayer?.prepareToPlay()
  3765. Nexilis.sharedAudioPlayer?.play()
  3766. } catch {
  3767. }
  3768. }
  3769. DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {
  3770. self.floating = nil
  3771. })
  3772. } catch {
  3773. }
  3774. }
  3775. }
  3776. return
  3777. }
  3778. } catch {}
  3779. profileImage.contentMode = .scaleAspectFill
  3780. } else {
  3781. profileImage.circle()
  3782. if message.getBody(key: messageScopeId) == MessageScope.WHISPER {
  3783. profileImage.image = UIImage(systemName: "person")
  3784. } else {
  3785. profileImage.image = UIImage(systemName: "person.3")
  3786. }
  3787. profileImage.contentMode = .scaleAspectFit
  3788. profileImage.backgroundColor = .lightGray
  3789. profileImage.tintColor = .white
  3790. }
  3791. 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)
  3792. // let vibrateMode: Bool = SecureUserDefaults.shared.value(forKey: "vibrateMode") ?? false
  3793. var soundId: String = SecureUserDefaults.shared.value(forKey: "newNotifSoundPersonal") ?? "001:Nexilis Message (Default)"
  3794. if message.getBody(key: CoreMessage_TMessageKey.MESSAGE_SCOPE_ID) == MessageScope.GROUP {
  3795. soundId = SecureUserDefaults.shared.value(forKey: "newNotifSoundGroup") ?? "001:Nexilis Message (Default)"
  3796. }
  3797. do {
  3798. var nameSound = soundId.components(separatedBy: ":")[1].replacingOccurrences(of: " ", with: "_")
  3799. var fromPref = false
  3800. if nameSound.contains("_(Default)") {
  3801. if !Utils.getDefaultIncomingMsg().isEmpty {
  3802. nameSound = Utils.getDefaultIncomingMsg()
  3803. fromPref = true
  3804. } else {
  3805. nameSound = nameSound.replacingOccurrences(of: "_(Default)", with: "")
  3806. }
  3807. }
  3808. var soundURL: URL?
  3809. if fromPref {
  3810. let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
  3811. let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
  3812. let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
  3813. if let dirPath = paths.first {
  3814. let audioURL = URL(fileURLWithPath: dirPath).appendingPathComponent(nameSound)
  3815. if !FileManager.default.fileExists(atPath: audioURL.path) && !FileEncryption.shared.isSecureExists(filename: nameSound) {
  3816. Download().startHTTP(forKey: nameSound,downloadUrl: Utils.getURLBase() + "filepalio/ringtone/") { (name, progress) in
  3817. guard progress == 100 else {
  3818. return
  3819. }
  3820. playAudio()
  3821. }
  3822. } else {
  3823. playAudio()
  3824. }
  3825. func playAudio() {
  3826. if FileManager.default.fileExists(atPath: audioURL.path) {
  3827. do {
  3828. do {
  3829. try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
  3830. try AVAudioSession.sharedInstance().setActive(true)
  3831. } catch {
  3832. }
  3833. Nexilis.sharedAudioPlayer = try AVAudioPlayer(contentsOf: audioURL)
  3834. Nexilis.sharedAudioPlayer?.prepareToPlay()
  3835. Nexilis.sharedAudioPlayer?.play()
  3836. } catch {
  3837. }
  3838. } else if FileEncryption.shared.isSecureExists(filename: nameSound) {
  3839. do {
  3840. if var audioData = try FileEncryption.shared.readSecure(filename: nameSound) {
  3841. let dataDecrypt = FileEncryption.shared.decryptFileFromServer(data: audioData)
  3842. if dataDecrypt != nil {
  3843. audioData = dataDecrypt!
  3844. }
  3845. let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
  3846. let tempPath = cachesDirectory.appendingPathComponent(nameSound)
  3847. try audioData.write(to: tempPath)
  3848. do {
  3849. do {
  3850. try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
  3851. try AVAudioSession.sharedInstance().setActive(true)
  3852. } catch {
  3853. }
  3854. Nexilis.sharedAudioPlayer = try AVAudioPlayer(contentsOf: tempPath)
  3855. Nexilis.sharedAudioPlayer?.prepareToPlay()
  3856. Nexilis.sharedAudioPlayer?.play()
  3857. } catch {
  3858. }
  3859. }
  3860. } catch {
  3861. }
  3862. }
  3863. }
  3864. }
  3865. } else {
  3866. soundURL = Bundle.resourceBundle(for: Nexilis.self).url(forResource: nameSound, withExtension: "mp3")
  3867. if soundURL == nil {
  3868. soundURL = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: nameSound, withExtension: "mp3")
  3869. }
  3870. do {
  3871. do {
  3872. try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
  3873. try AVAudioSession.sharedInstance().setActive(true)
  3874. } catch {
  3875. }
  3876. Nexilis.sharedAudioPlayer = try AVAudioPlayer(contentsOf: soundURL!)
  3877. Nexilis.sharedAudioPlayer?.prepareToPlay()
  3878. Nexilis.sharedAudioPlayer?.play()
  3879. } catch {
  3880. }
  3881. }
  3882. } catch {
  3883. }
  3884. DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {
  3885. self.floating = nil
  3886. })
  3887. // if !onGoingCC.isEmpty {
  3888. // floating.autoDismiss = false
  3889. // }
  3890. floating.onTap = {
  3891. self.floating = nil
  3892. showNotif()
  3893. }
  3894. }
  3895. func showNotif() {
  3896. if UIApplication.shared.visibleViewController is UINavigationController {
  3897. let nc = UIApplication.shared.visibleViewController as! UINavigationController
  3898. if nc.visibleViewController is QmeraStreamingViewController {
  3899. return
  3900. } else if nc.visibleViewController is SeminarViewController {
  3901. return
  3902. }
  3903. if let navigationC = UIApplication.shared.visibleViewController as? UINavigationController {
  3904. if navigationC.viewControllers[navigationC.viewControllers.count - 1] is EditorPersonal || navigationC.viewControllers[navigationC.viewControllers.count - 1] is EditorGroup {
  3905. navigationC.popViewController(animated: true)
  3906. }
  3907. }
  3908. } else if UIApplication.shared.visibleViewController is UIAlertController {
  3909. return
  3910. }
  3911. if message.getBody(key: attachmentFlag) == "59" {
  3912. let date = Date(milliseconds: Int64(message.getBody(key: CoreMessage_TMessageKey.LOCAL_TIMESTAMP))!)
  3913. let formatter = DateFormatter()
  3914. formatter.dateFormat = "HH:mm"
  3915. formatter.locale = NSLocale(localeIdentifier: "id") as Locale?
  3916. var timeSignIn = formatter.string(from: date as Date)
  3917. let dialog = DialogSignIn()
  3918. dialog.valueDevice = message.getBody(key: CoreMessage_TMessageKey.DEVICE_BRAND)
  3919. dialog.valueTime = timeSignIn
  3920. dialog.valueLocation = message.getBody(key: CoreMessage_TMessageKey.PLACE_NAME)
  3921. dialog.valueToken = message.getBody(key: CoreMessage_TMessageKey.TOKEN)
  3922. dialog.valueUser = message.getBody(key: CoreMessage_TMessageKey.USER_ID)
  3923. dialog.modalTransitionStyle = .crossDissolve
  3924. dialog.modalPresentationStyle = .overCurrentContext
  3925. UIApplication.shared.visibleViewController?.present(dialog, animated: true)
  3926. return
  3927. }
  3928. if !onGoingCC.isEmpty {
  3929. floating.dismiss()
  3930. }
  3931. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  3932. do {
  3933. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT first_name, last_name FROM BUDDY where f_pin = '\(User.getMyPin()!)'"), cursorData.next() {
  3934. if (cursorData.string(forColumnIndex: 0)! + " " + cursorData.string(forColumnIndex: 1)!).trimmingCharacters(in: .whitespaces) == "USR\(User.getMyPin()!)" {
  3935. let alert = LibAlertController(title: "Set Profile".localized(), message: "You must set your profile to use this feature".localized(), preferredStyle: .alert)
  3936. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  3937. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "signupsignin") as! SignUpSignIn
  3938. controller.forceLogin = true
  3939. let navigationController = CustomNavigationController(rootViewController: controller)
  3940. navigationController.modalPresentationStyle = .fullScreen
  3941. navigationController.navigationBar.tintColor = .white
  3942. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  3943. navigationController.navigationBar.isTranslucent = false
  3944. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  3945. navigationController.navigationBar.barStyle = .black
  3946. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  3947. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  3948. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  3949. navigationController.navigationBar.titleTextAttributes = textAttributes
  3950. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3951. UIApplication.shared.visibleViewController?.navigationController?.present(navigationController, animated: true, completion: nil)
  3952. } else {
  3953. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  3954. }
  3955. }))
  3956. if UIApplication.shared.visibleViewController?.navigationController != nil {
  3957. UIApplication.shared.visibleViewController?.navigationController?.present(alert, animated: true, completion: nil)
  3958. } else {
  3959. UIApplication.shared.visibleViewController?.present(alert, animated: true, completion: nil)
  3960. }
  3961. }
  3962. cursorData.close()
  3963. return
  3964. }
  3965. } catch {
  3966. rollback.pointee = true
  3967. print("Access database error: \(error.localizedDescription)")
  3968. }
  3969. })
  3970. if message.getBody(key: messageScopeId) == MessageScope.WHISPER || message.getBody(key: messageScopeId) == MessageScope.FORM || message.getBody(key: messageScopeId) == MessageScope.CHATROOM {
  3971. let editorPersonalVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorPersonalVC") as! EditorPersonal
  3972. editorPersonalVC.hidesBottomBarWhenPushed = true
  3973. editorPersonalVC.unique_l_pin = threadIdentifier
  3974. editorPersonalVC.fromNotification = true
  3975. if !onGoingCC.isEmpty {
  3976. let compalintId = onGoingCC.components(separatedBy: ",")[2]
  3977. let fPinCC = onGoingCC.isEmpty ? "" : onGoingCC.components(separatedBy: ",")[1]
  3978. editorPersonalVC.isContactCenter = true
  3979. editorPersonalVC.fPinContacCenter = fPinCC
  3980. editorPersonalVC.complaintId = compalintId
  3981. editorPersonalVC.onGoingCC = true
  3982. editorPersonalVC.isRequestContactCenter = false
  3983. }
  3984. let navigationController = CustomNavigationController(rootViewController: editorPersonalVC)
  3985. navigationController.modalPresentationStyle = .fullScreen
  3986. navigationController.navigationBar.tintColor = .white
  3987. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  3988. navigationController.navigationBar.isTranslucent = false
  3989. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  3990. navigationController.navigationBar.barStyle = .black
  3991. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  3992. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  3993. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  3994. navigationController.navigationBar.titleTextAttributes = textAttributes
  3995. if UIApplication.shared.visibleViewController is UINavigationController && Nexilis.fromMAB {
  3996. editorPersonalVC.fromNotification = false
  3997. UIApplication.shared.visibleViewController?.show(editorPersonalVC, sender: nil)
  3998. } else {
  3999. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  4000. }
  4001. } else {
  4002. let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "editorGroupVC") as! EditorGroup
  4003. editorGroupVC.hidesBottomBarWhenPushed = true
  4004. editorGroupVC.unique_l_pin = threadIdentifier
  4005. editorGroupVC.fromNotification = true
  4006. let navigationController = CustomNavigationController(rootViewController: editorGroupVC)
  4007. navigationController.modalPresentationStyle = .fullScreen
  4008. navigationController.navigationBar.tintColor = .white
  4009. navigationController.navigationBar.barTintColor = UIApplication.shared.visibleViewController?.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  4010. navigationController.navigationBar.isTranslucent = false
  4011. navigationController.navigationBar.overrideUserInterfaceStyle = .dark
  4012. navigationController.navigationBar.barStyle = .black
  4013. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  4014. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  4015. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  4016. navigationController.navigationBar.titleTextAttributes = textAttributes
  4017. if UIApplication.shared.visibleViewController is UINavigationController && Nexilis.fromMAB {
  4018. editorGroupVC.fromNotification = false
  4019. UIApplication.shared.visibleViewController?.show(editorGroupVC, sender: nil)
  4020. } else {
  4021. UIApplication.shared.visibleViewController?.present(navigationController, animated: true, completion: nil)
  4022. }
  4023. }
  4024. }
  4025. }
  4026. }
  4027. }
  4028. }
  4029. public static func addFriend(fpin: String, completion: @escaping (Bool) -> ()) {
  4030. DispatchQueue.global().async {
  4031. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getAddFriendQRCode(fpin: fpin)), response.isOk() {
  4032. completion(true)
  4033. } else {
  4034. completion(false)
  4035. }
  4036. }
  4037. }
  4038. public static func addFriendSilent(fpin: String) {
  4039. DispatchQueue.global().async {
  4040. _ = Nexilis.write(message: CoreMessage_TMessageBank.getAddFriendQRCodeSilent(fpin: fpin))
  4041. }
  4042. }
  4043. public func onReceive(message: [AnyHashable : Any?]) {
  4044. var dataMessage: [AnyHashable : Any] = [:]
  4045. dataMessage["message"] = message
  4046. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerReceiveChat), object: nil, userInfo: dataMessage)
  4047. }
  4048. public func onMessage(message: TMessage) {
  4049. var dataMessage: [AnyHashable : Any] = [:]
  4050. dataMessage["message"] = message
  4051. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerStatusChat), object: nil, userInfo: dataMessage)
  4052. }
  4053. public func onUpload(name: String, progress: Double) {
  4054. var dataMessage: [AnyHashable : Any] = [:]
  4055. dataMessage["name"] = name
  4056. dataMessage["progress"] = progress
  4057. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onUploadChat"), object: nil, userInfo: dataMessage)
  4058. }
  4059. public func onTyping(message: TMessage) {
  4060. var dataMessage: [AnyHashable : Any] = [:]
  4061. dataMessage["message"] = message
  4062. NotificationCenter.default.post(name: NSNotification.Name(rawValue: Nexilis.listenerTypingChat), object: nil, userInfo: dataMessage)
  4063. }
  4064. // public static func faceDetect(fd: FaceDetector?,image: UIImage, completion: ((Bool) -> ())?){
  4065. // //print("enter vision")
  4066. // let visionImage = VisionImage(image: image)
  4067. // //print("exit vision")
  4068. // var retval = false
  4069. // visionImage.orientation = image.imageOrientation
  4070. // var fd1 : FaceDetector?
  4071. // if(fd == nil){
  4072. // fd1 = FaceDetector.faceDetector()
  4073. // }
  4074. // else {
  4075. // fd1 = fd
  4076. // }
  4077. //
  4078. // // [START detect_faces]
  4079. // fd1?.process(visionImage) {faces, error in
  4080. // guard error == nil, let faces = faces, !faces.isEmpty else {
  4081. // //print("faces empty")
  4082. // completion?(false)
  4083. // return
  4084. // }
  4085. // if(faces.count > 0){
  4086. // //print("face count: \(faces.count)")
  4087. // retval = true
  4088. // }
  4089. // completion?(retval)
  4090. // }
  4091. //
  4092. // }
  4093. }
  4094. extension Nexilis: GroupDelegate {
  4095. public func onGroup(code: String, f_pin: String, groupId: String) {
  4096. var data: [AnyHashable : Any] = [:]
  4097. data["code"] = code
  4098. data["f_pin"] = f_pin
  4099. data["groupId"] = groupId
  4100. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onGroup"), object: nil, userInfo: data)
  4101. }
  4102. public func onTopic(code: String, f_pin: String, topicId: String) {
  4103. var data: [AnyHashable : Any] = [:]
  4104. data["code"] = code
  4105. data["f_pin"] = f_pin
  4106. data["topicId"] = topicId
  4107. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onTopic"), object: nil, userInfo: data)
  4108. }
  4109. public func onMember(code: String, f_pin: String, groupId: String, member: String) {
  4110. var data: [AnyHashable : Any] = [:]
  4111. data["code"] = code
  4112. data["f_pin"] = f_pin
  4113. data["groupId"] = groupId
  4114. data["member"] = member
  4115. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onMember"), object: nil, userInfo: data)
  4116. }
  4117. }
  4118. extension Nexilis: PersonInfoDelegate {
  4119. public func onUpdatePersonInfo(state: Int, message: String) {
  4120. var data: [AnyHashable : Any] = [:]
  4121. data["state"] = state
  4122. data["message"] = message
  4123. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onUpdatePersonInfo"), object: nil, userInfo: data)
  4124. }
  4125. }
  4126. extension Nexilis: QLPreviewControllerDataSource {
  4127. public func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
  4128. return 1
  4129. }
  4130. public func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
  4131. return previewItem!
  4132. }
  4133. }
  4134. public class SelfSignedURLSessionDelegate: NSObject, URLSessionTaskDelegate, URLSessionDataDelegate {
  4135. public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
  4136. if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
  4137. if let serverTrust = challenge.protectionSpace.serverTrust {
  4138. let credential = URLCredential(trust: serverTrust)
  4139. completionHandler(.useCredential, credential)
  4140. }
  4141. }
  4142. }
  4143. }