BroadcastViewController.swift 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. //
  2. // BroadcastViewController.swift
  3. // Qmera
  4. //
  5. // Created by Kevin Maulana on 27/09/21.
  6. //
  7. import UIKit
  8. import AVKit
  9. import AVFoundation
  10. import FMDB
  11. import NotificationBannerSwift
  12. class BroadcastViewController: UITableViewController, UITextFieldDelegate, UITextViewDelegate, ImageVideoPickerDelegate, DocumentPickerDelegate {
  13. @IBOutlet weak var targetAudienceLabel: UILabel!
  14. @IBOutlet weak var targetAudienceTitle: UILabel!
  15. @IBOutlet weak var broadcastTypeLabel: UILabel!
  16. @IBOutlet weak var broadcastTypeTitle: UILabel!
  17. @IBOutlet weak var broadcastModeLabel: UILabel!
  18. @IBOutlet weak var broadcastModeTitle: UILabel!
  19. @IBOutlet weak var broadcastVariantLabel: UILabel!
  20. @IBOutlet weak var broadcastVariantTitle: UILabel!
  21. @IBOutlet weak var startTimePicker: UIDatePicker!
  22. @IBOutlet weak var starttimeTitle: UILabel!
  23. @IBOutlet weak var endTimeCell: UITableViewCell!
  24. @IBOutlet weak var endTimeTitle: UILabel!
  25. @IBOutlet weak var endTimePicker: UIDatePicker!
  26. @IBOutlet weak var titleTextField: UITextField!
  27. @IBOutlet weak var messageTextView: UITextView!
  28. @IBOutlet weak var linkTextField: UITextField!
  29. @IBOutlet weak var imagePreview: UIImageView!
  30. @IBOutlet weak var documentPreview: UIView!
  31. @IBOutlet weak var clearAttachButton: UIButton!
  32. @IBOutlet weak var documentLabel: UILabel!
  33. @IBOutlet weak var addMemberButton: UIButton!
  34. @IBOutlet weak var memberTable: UITableView!
  35. @IBOutlet weak var memberCell: UITableViewCell!
  36. @IBOutlet weak var memberListLabel: UILabel!
  37. @IBOutlet weak var attachmentLabel: UILabel!
  38. let placeholder = "Message".localized()
  39. static let FLAG_NEW_POST = "0"
  40. static let FLAG_EDIT_POST = "1"
  41. static let FILE_TYPE_CHAT = "0"
  42. static let FILE_TYPE_IMAGE = "1"
  43. static let FILE_TYPE_VIDEO = "2"
  44. static let FILE_TYPE_DOCUMENT = "3"
  45. static let DESTINATION_CUSTOMER = "1"
  46. static let DESTINATION_TEAM_MEMBER = "2"
  47. static let DESTINATION_ALL = "3"
  48. static let DESTINATION_GROUP = "4"
  49. static let DESTINATION_SPESIFIC = "5"
  50. static let DESTINATION_MEMBER_MERCHANT = "6"
  51. static let TYPE_PUSH_NOTIFICATION = "1"
  52. static let TYPE_IN_APP = "2"
  53. static let MODE_ONCE = "1"
  54. static let MODE_DAILY = "2"
  55. static let MODE_WEEKLY = "3"
  56. static let MODE_MONTHLY = "4"
  57. static let FORM_NOT_FORM = "-99"
  58. var fileType = FILE_TYPE_CHAT
  59. var dest = DESTINATION_CUSTOMER
  60. var type = TYPE_PUSH_NOTIFICATION
  61. var mode = MODE_ONCE
  62. var membersInvited = ""
  63. var thumbId = ""
  64. var fileId = ""
  65. var form = FORM_NOT_FORM
  66. var link = ""
  67. var messageTitle = ""
  68. var message = ""
  69. var imageVideoPicker : ImageVideoPicker!
  70. var documentPicker : DocumentPicker!
  71. var imageVideoData : [UIImagePickerController.InfoKey: Any]?
  72. var previewItem : URL?
  73. var contacts: [User] = []
  74. var groups: [Group] = []
  75. var forms: [Form] = []
  76. var loadingView = UIViewController()
  77. override func viewWillAppear(_ animated: Bool) {
  78. let backButton = UIBarButtonItem(title: "Back".localized(), style: .plain, target: nil, action: nil)
  79. let attributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
  80. backButton.setTitleTextAttributes(attributes, for: .normal)
  81. navigationController?.navigationBar.topItem?.backBarButtonItem = backButton
  82. }
  83. override func viewDidLoad() {
  84. super.viewDidLoad()
  85. DispatchQueue.global().async {
  86. let me = User.getMyPin()!
  87. _ = Nexilis.write(message: CoreMessage_TMessageBank.getFormList(p_pin: me, p_last_id: "0"))
  88. }
  89. navigationController?.navigationBar.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  90. navigationController?.navigationBar.tintColor = .white
  91. navigationController?.navigationBar.barTintColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  92. navigationController?.navigationBar.isTranslucent = false
  93. navigationController?.navigationBar.overrideUserInterfaceStyle = .dark
  94. navigationController?.navigationBar.barStyle = .black
  95. navigationController?.view.backgroundColor = self.traitCollection.userInterfaceStyle == .dark ? .blackDarkMode : .mainColor
  96. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)]
  97. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  98. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  99. navigationController?.navigationBar.titleTextAttributes = textAttributes
  100. navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel".localized(), style: .plain, target: self, action: #selector(didTapCancel))
  101. navigationItem.leftBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: .normal)
  102. navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Submit".localized(), style: .plain,target: self, action: #selector(submitBroadcast))
  103. navigationItem.rightBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: .normal)
  104. title = "Broadcast Message".localized()
  105. targetAudienceTitle.text = "Target Audience".localized()
  106. broadcastTypeTitle.text = "Broadcast Type".localized()
  107. broadcastModeTitle.text = "Broadcast Mode".localized()
  108. broadcastVariantTitle.text = "Broadcast Variant".localized()
  109. starttimeTitle.text = "Start Time".localized()
  110. endTimeTitle.text = "End Time".localized()
  111. titleTextField.placeholder = "Title".localized()
  112. attachmentLabel.text = "Attachment (Optional)".localized()
  113. attachmentLabel.textColor = .lightGray
  114. linkTextField.placeholder = "Link (Optional)".localized()
  115. titleTextField.delegate = self
  116. messageTextView.delegate = self
  117. linkTextField.delegate = self
  118. messageTextView.delegate = self
  119. messageTextView.text = placeholder
  120. messageTextView.textColor = .opaqueSeparator
  121. targetAudienceLabel.text = "Customer".localized()
  122. broadcastTypeLabel.text = "Notification".localized()
  123. broadcastModeLabel.text = "One Time".localized()
  124. broadcastVariantLabel.text = "Message".localized()
  125. endTimeCell.isHidden = true
  126. imageVideoPicker = ImageVideoPicker(presentationController: self, delegate: self)
  127. documentPicker = DocumentPicker(presentationController: self, delegate: self)
  128. memberTable.dataSource = self
  129. memberTable.delegate = self
  130. let query = "select f.id, f.form_id, f.name, f.created_date, f.created_by, f.sq_no from FORM f"
  131. Database.shared.database?.inTransaction({ fmdb, rollback in
  132. do {
  133. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query) {
  134. while cursor.next() {
  135. var form = Form()
  136. form.id = cursor.long(forColumnIndex: 0)
  137. form.formId = cursor.string(forColumnIndex: 1)!
  138. form.title = cursor.string(forColumnIndex: 2)!
  139. form.createdDate = Int(cursor.string(forColumnIndex: 3)!)!
  140. form.createdBy = cursor.string(forColumnIndex: 4)!
  141. form.sqNo = Int(cursor.int(forColumnIndex: 5))
  142. forms.append(form)
  143. }
  144. }
  145. } catch {
  146. rollback.pointee = true
  147. print("Access database error: \(error.localizedDescription)")
  148. }
  149. })
  150. // Do any additional setup after loading the view.
  151. }
  152. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  153. textField.resignFirstResponder()
  154. return true
  155. }
  156. func textViewDidBeginEditing(_ textView: UITextView) {
  157. if(textView.text == placeholder){
  158. textView.text = ""
  159. textView.textColor = .black
  160. }
  161. textView.becomeFirstResponder()
  162. }
  163. func textViewDidEndEditing(_ textView: UITextView)
  164. {
  165. if (textView.text == "")
  166. {
  167. textView.text = placeholder
  168. textView.textColor = .opaqueSeparator
  169. }
  170. textView.resignFirstResponder()
  171. }
  172. func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
  173. if text == "\n" {
  174. textView.resignFirstResponder()
  175. return false
  176. }
  177. return true
  178. }
  179. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  180. if segue.identifier == "br_audience" {
  181. let destination = segue.destination as! AudienceViewController
  182. destination.isBroadcast = true
  183. destination.selected = targetAudienceLabel.text
  184. } else if segue.identifier == "br_type" {
  185. let destination = segue.destination as! TypeViewController
  186. destination.selected = broadcastTypeLabel.text
  187. } else if segue.identifier == "br_mode" {
  188. let destination = segue.destination as! BroadcastModeViewController
  189. destination.selected = broadcastModeLabel.text
  190. } else if segue.identifier == "br_variant" {
  191. let destination = segue.destination as! BroadcastVariantViewController
  192. destination.selected = broadcastVariantLabel.text
  193. destination.data = forms
  194. } else if segue.identifier == "br_member" {
  195. let destination = segue.destination as! BroadcastMembersTableViewController
  196. let isGroup = dest == BroadcastViewController.DESTINATION_GROUP
  197. destination.isGroup = isGroup
  198. if(isGroup){
  199. for g in groups{
  200. destination.existing.append(g.id)
  201. }
  202. }
  203. else {
  204. for c in contacts {
  205. destination.existing.append(c.pin)
  206. }
  207. }
  208. }
  209. }
  210. @objc func didTapCancel() {
  211. navigationController?.dismiss(animated: true, completion: nil)
  212. }
  213. @IBAction func selectImage(_ sender: Any) {
  214. imageVideoPicker.present(source: .imageAlbum)
  215. }
  216. @IBAction func selectVideo(_ sender: Any) {
  217. imageVideoPicker.present(source: .videoAlbum)
  218. }
  219. @IBAction func selectDocument(_ sender: Any) {
  220. documentPicker.present()
  221. }
  222. func didSelect(imagevideo: Any?) {
  223. if (imagevideo != nil) {
  224. imageVideoData = imagevideo as? [UIImagePickerController.InfoKey: Any]
  225. if (imageVideoData![.mediaType] as! String == "public.movie") {
  226. do {
  227. let url = imageVideoData![.mediaURL] as! URL
  228. let asset = AVURLAsset(url: url, options: nil)
  229. let imgGenerator = AVAssetImageGenerator(asset: asset)
  230. imgGenerator.appliesPreferredTrackTransform = true
  231. let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
  232. let thumbnail = UIImage(cgImage: cgImage)
  233. imagePreview.image = thumbnail
  234. self.fileType = BroadcastViewController.FILE_TYPE_VIDEO
  235. } catch let error {
  236. //print("*** Error generating thumbnail: \(error.localizedDescription)")
  237. }
  238. } else {
  239. let url = imageVideoData![.imageURL] as! URL
  240. //print("url: \(url.lastPathComponent)")
  241. imagePreview.image = imageVideoData![.originalImage] as? UIImage
  242. self.fileType = BroadcastViewController.FILE_TYPE_IMAGE
  243. }
  244. imagePreview.isHidden = false
  245. documentPreview.isHidden = true
  246. clearAttachButton.isHidden = false
  247. }
  248. }
  249. func didSelectDocument(document: Any?) {
  250. if (document != nil) {
  251. previewItem = (document as! [URL])[0] as URL
  252. fileType = BroadcastViewController.FILE_TYPE_DOCUMENT
  253. fileId = previewItem?.lastPathComponent ?? ""
  254. documentLabel.text = fileId
  255. imagePreview.isHidden = true
  256. documentPreview.isHidden = false
  257. clearAttachButton.isHidden = false
  258. }
  259. }
  260. func uploadAttachment(){
  261. }
  262. @IBAction func addMembers(_ sender: Any) {
  263. }
  264. @IBAction func clearAttach(_ sender: Any) {
  265. clearAttachment()
  266. }
  267. func clearAttachment(){
  268. fileType = BroadcastViewController.FILE_TYPE_CHAT
  269. thumbId = ""
  270. fileId = ""
  271. documentLabel.text = ""
  272. imagePreview.isHidden = true
  273. documentPreview.isHidden = true
  274. clearAttachButton.isHidden = true
  275. imageVideoData = nil
  276. previewItem = nil
  277. }
  278. func showActivityIndicatory() {
  279. loadingView.view.backgroundColor = .black.withAlphaComponent(0.3)
  280. let activityView = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large)
  281. activityView.center = self.view.center
  282. loadingView.view.addSubview(activityView)
  283. activityView.startAnimating()
  284. loadingView.modalPresentationStyle = .custom
  285. loadingView.modalTransitionStyle = .crossDissolve
  286. self.present(loadingView, animated: true)
  287. }
  288. @objc func submitBroadcast() {
  289. let startTime = startTimePicker.date.millisecondsSince1970
  290. var endTime = startTime
  291. if(!endTimeCell.isHidden){
  292. endTime = endTimePicker.date.millisecondsSince1970
  293. }
  294. if(startTime > endTime){
  295. return
  296. }
  297. messageTitle = titleTextField.text!
  298. message = messageTextView.text
  299. link = linkTextField.text!
  300. dest = "\(targetAudienceLabel.tag + 1)"
  301. type = "\(broadcastTypeLabel.tag + 1)"
  302. mode = "\(broadcastModeLabel.tag + 1)"
  303. if(messageTitle.trimmingCharacters(in: .whitespaces).isEmpty || message.trimmingCharacters(in: .whitespaces).isEmpty){
  304. let alert = LibAlertController(title: "", message: "Title and message must not be empty".localized(), preferredStyle: .alert)
  305. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: nil))
  306. self.present(alert, animated: true, completion: nil)
  307. return
  308. }
  309. if(dest == BroadcastViewController.DESTINATION_GROUP){
  310. if(groups.isEmpty){
  311. let alert = LibAlertController(title: "", message: "Please select at least one contact".localized(), preferredStyle: .alert)
  312. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: nil))
  313. self.present(alert, animated: true, completion: nil)
  314. return
  315. }
  316. var gs = [String]()
  317. for g in groups {
  318. gs.append(g.id)
  319. }
  320. let jsonData = try! JSONSerialization.data(withJSONObject: gs, options: [])
  321. membersInvited = String(data: jsonData, encoding: .utf8) ?? ""
  322. }
  323. else if(dest == BroadcastViewController.DESTINATION_SPESIFIC){
  324. if(contacts.isEmpty){
  325. let alert = LibAlertController(title: "", message: "Please select at least one contact".localized(), preferredStyle: .alert)
  326. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: nil))
  327. self.present(alert, animated: true, completion: nil)
  328. return
  329. }
  330. var cs = [String]()
  331. for c in contacts {
  332. cs.append(c.pin)
  333. }
  334. let jsonData = try! JSONSerialization.data(withJSONObject: cs, options: [])
  335. membersInvited = String(data: jsonData, encoding: .utf8) ?? ""
  336. }
  337. //print("dest: \(dest)")
  338. //print("type: \(type)")
  339. //print("mode: \(mode)")
  340. //print("fileType: \(fileType)")
  341. //print("thumb_id: \(thumbId)")
  342. //print("file_id: \(fileId)")
  343. //print("members: \(membersInvited)")
  344. if !CheckConnection.isConnectedToNetwork() {
  345. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  346. imageView.tintColor = .white
  347. let banner = FloatingNotificationBanner(title: "Check your connection".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
  348. banner.show()
  349. return
  350. }
  351. showActivityIndicatory()
  352. if(form == BroadcastViewController.FORM_NOT_FORM){
  353. if(fileType == BroadcastViewController.FILE_TYPE_IMAGE){
  354. saveImage()
  355. }
  356. else if(fileType == BroadcastViewController.FILE_TYPE_VIDEO){
  357. saveVideo()
  358. }
  359. else if(fileType == BroadcastViewController.FILE_TYPE_DOCUMENT){
  360. saveDocument()
  361. }
  362. }
  363. else {
  364. clearAttachment()
  365. }
  366. if !thumbId.isEmpty {
  367. Network().uploadHTTP(name: String(thumbId)) { (result1, progress) in
  368. if result1 {
  369. if progress == 100 {
  370. do {
  371. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
  372. let fileURL = documentsDirectory.appendingPathComponent(self.thumbId)
  373. try FileEncryption.shared.writeSecure(filename: self.thumbId, data: Data(contentsOf: fileURL))
  374. try FileManager.default.removeItem(atPath: fileURL.path)
  375. } catch {
  376. }
  377. Network().uploadHTTP(name: String(self.fileId)) { (result2, progress) in
  378. if result2 {
  379. if progress == 100 {
  380. self.sendMsg(startTime: startTime, endTime: endTime)
  381. do {
  382. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
  383. let fileURL = documentsDirectory.appendingPathComponent(self.fileId)
  384. try FileEncryption.shared.writeSecure(filename: self.fileId, data: Data(contentsOf: fileURL))
  385. try FileManager.default.removeItem(atPath: fileURL.path)
  386. } catch {
  387. }
  388. }
  389. }
  390. }
  391. }
  392. }
  393. }
  394. } else if !fileId.isEmpty {
  395. Network().uploadHTTP(name: String(fileId)) { (result2, progress) in
  396. if result2 {
  397. if progress == 100 {
  398. self.sendMsg(startTime: startTime, endTime: endTime)
  399. do {
  400. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
  401. let fileURL = documentsDirectory.appendingPathComponent(self.fileId)
  402. try FileEncryption.shared.writeSecure(filename: self.fileId, data: Data(contentsOf: fileURL))
  403. try FileManager.default.removeItem(atPath: fileURL.path)
  404. } catch {
  405. }
  406. }
  407. }
  408. }
  409. } else {
  410. sendMsg(startTime: startTime, endTime: endTime)
  411. }
  412. }
  413. func saveImage(){
  414. var originalImageName = ""
  415. if (imageVideoData![.imageURL] == nil) {
  416. originalImageName = "\(Date().currentTimeMillis())_takeImage"
  417. } else {
  418. let urlImage = (imageVideoData![.imageURL] as! NSURL).absoluteString
  419. originalImageName = (urlImage! as NSString).lastPathComponent
  420. }
  421. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
  422. let compressedImageName = "THUMB-Nexilis_image_\(originalImageName)"
  423. let thumbName = "THUMB_Nexilis_image_\(originalImageName)"
  424. let fileURL = documentsDirectory.appendingPathComponent(compressedImageName)
  425. let compressedImage = (imageVideoData![.originalImage] as! UIImage).jpegData(compressionQuality: 1.0)
  426. if let data = compressedImage,
  427. !FileManager.default.fileExists(atPath: fileURL.path) {
  428. do {
  429. try data.write(to: fileURL)
  430. //print("file saved")
  431. } catch {
  432. //print("error saving file:", error)
  433. }
  434. }
  435. let thumbImage = UIImage(data: compressedImage!)
  436. let fileURLTHUMB = documentsDirectory.appendingPathComponent(thumbName)
  437. if let dataThumb = thumbImage!.jpegData(compressionQuality: 0.25),
  438. !FileManager.default.fileExists(atPath: fileURLTHUMB.path) {
  439. do {
  440. try dataThumb.write(to: fileURLTHUMB)
  441. //print("thumb saved")
  442. } catch {
  443. //print("error saving file:", error)
  444. }
  445. }
  446. fileId = compressedImageName
  447. thumbId = thumbName
  448. }
  449. func saveVideo(){
  450. guard var dataVideo = try? Data(contentsOf: imageVideoData![.mediaURL] as! URL) else {
  451. return
  452. }
  453. let sizeOfVideo = Double(dataVideo.count / 1048576)
  454. if (sizeOfVideo > 10.0) {
  455. let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + UUID().uuidString + ".mp4")
  456. compressVideo(inputURL: imageVideoData![.mediaURL] as! URL,
  457. outputURL: compressedURL) { exportSession in
  458. guard let session = exportSession else {
  459. return
  460. }
  461. switch session.status {
  462. case .unknown:
  463. break
  464. case .waiting:
  465. break
  466. case .exporting:
  467. break
  468. case .completed:
  469. guard let compressedData = try? Data(contentsOf: compressedURL) else {
  470. return
  471. }
  472. dataVideo = compressedData
  473. case .failed:
  474. break
  475. case .cancelled:
  476. break
  477. @unknown default:
  478. break
  479. }
  480. }
  481. }
  482. let urlVideo = (imageVideoData![.mediaURL] as! NSURL).absoluteString
  483. let originalVideoName = (urlVideo! as NSString).lastPathComponent
  484. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
  485. let renamedVideoName = "Nexilis_video_\(originalVideoName)"
  486. let thumbName = "THUMB_Nexilis_video_\(originalVideoName)"
  487. let fileURL = documentsDirectory.appendingPathComponent(renamedVideoName)
  488. if !FileManager.default.fileExists(atPath: fileURL.path) {
  489. do {
  490. try dataVideo.write(to: fileURL)
  491. //print("file saved")
  492. } catch {
  493. //print("error saving file:", error)
  494. }
  495. }
  496. let dataThumbVideo = imagePreview.image!.jpegData(compressionQuality: 1.0)
  497. let fileURLTHUMB = documentsDirectory.appendingPathComponent(thumbName)
  498. if !FileManager.default.fileExists(atPath: fileURLTHUMB.path) {
  499. do {
  500. try dataThumbVideo!.write(to: fileURLTHUMB)
  501. //print("thumb saved")
  502. } catch {
  503. //print("error saving file:", error)
  504. }
  505. }
  506. fileId = renamedVideoName
  507. thumbId = thumbName
  508. }
  509. func saveDocument(){
  510. do {
  511. let dataFile = try Data(contentsOf: self.previewItem! as URL)
  512. let urlFile = self.previewItem?.absoluteString
  513. var originaFileName = (urlFile! as NSString).lastPathComponent
  514. originaFileName = NSString(string: originaFileName).removingPercentEncoding!
  515. let renamedNameFile = "Nexilis_doc_" + "\(Date().currentTimeMillis())_" + originaFileName
  516. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
  517. let fileURL = documentsDirectory.appendingPathComponent(renamedNameFile)
  518. if !FileManager.default.fileExists(atPath: fileURL.path) {
  519. do {
  520. try dataFile.write(to: fileURL)
  521. //print("file saved")
  522. } catch {
  523. //print("error saving file:", error)
  524. }
  525. }
  526. fileId = renamedNameFile
  527. } catch {
  528. }
  529. }
  530. func compressVideo(inputURL: URL,
  531. outputURL: URL,
  532. handler:@escaping (_ exportSession: AVAssetExportSession?) -> Void) {
  533. let urlAsset = AVURLAsset(url: inputURL, options: nil)
  534. guard let exportSession = AVAssetExportSession(asset: urlAsset,
  535. presetName: AVAssetExportPresetMediumQuality) else {
  536. handler(nil)
  537. return
  538. }
  539. exportSession.outputURL = outputURL
  540. exportSession.outputFileType = .mp4
  541. exportSession.exportAsynchronously {
  542. handler(exportSession)
  543. }
  544. }
  545. func sendMsg(startTime: Int64, endTime: Int64){
  546. let message = CoreMessage_TMessageBank.broadcastMessage(title: messageTitle, broadcast_flag: mode, message: message, starting_date: startTime, ending_date: startTime, destination: dest, data: membersInvited, category_flag: fileType, notification_type: type, link: link, thumb_id: thumbId, file_id: fileId)
  547. if(form != BroadcastViewController.FORM_NOT_FORM){
  548. message.mBodies[CoreMessage_TMessageKey.FILE_ID] = form
  549. message.mBodies[CoreMessage_TMessageKey.MESSAGE_SCOPE_ID] = "18"
  550. }
  551. if let response = Nexilis.writeSync(message: message) {
  552. if (response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "00") {
  553. DispatchQueue.main.async {
  554. let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
  555. imageView.tintColor = .white
  556. let banner = FloatingNotificationBanner(title: "Broadcast Message Sent".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .success, colors: nil, iconPosition: .center)
  557. banner.show()
  558. self.navigationController?.presentingViewController?.dismiss(animated: true)
  559. }
  560. } else {
  561. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  562. imageView.tintColor = .white
  563. let banner = FloatingNotificationBanner(title: "Unable to access servers. Try again later".localized(), subtitle: nil, titleFont: UIFont.systemFont(ofSize: 16), titleColor: nil, titleTextAlign: .left, subtitleFont: nil, subtitleColor: nil, subtitleTextAlign: nil, leftView: imageView, rightView: nil, style: .danger, colors: nil, iconPosition: .center)
  564. banner.show()
  565. self.loadingView.dismiss(animated: true)
  566. }
  567. }
  568. }
  569. /*
  570. // MARK: - Navigation
  571. // In a storyboard-based application, you will often want to do a little preparation before navigation
  572. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  573. // Get the new view controller using segue.destination.
  574. // Pass the selected object to the new view controller.
  575. }
  576. */
  577. @IBAction func result(unwind segue: UIStoryboardSegue) {
  578. }
  579. override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  580. if(tableView == memberTable){
  581. let mcell = tableView.dequeueReusableCell(withIdentifier: "memberCell", for: indexPath) as! BroadcastMembersTableViewCell
  582. if(dest == BroadcastViewController.DESTINATION_SPESIFIC){
  583. var content = mcell.defaultContentConfiguration()
  584. let data: User
  585. data = contacts[indexPath.row]
  586. content.imageProperties.maximumSize = CGSize(width: 40, height: 40)
  587. getImage(name: data.thumb, placeholderImage: UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
  588. content.image = image
  589. })
  590. if User.isOfficial(official_account: data.official ?? "") || User.isOfficialRegular(official_account: data.official ?? "") {
  591. content.attributedText = self.set(image: UIImage(named: "ic_official_flag", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(data.fullName)", size: 15, y: -4, colorText: UIColor.officialColor)
  592. } else if User.isVerified(official_account: data.official ?? "") {
  593. content.attributedText = self.set(image: UIImage(named: "ic_verified", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(data.fullName)", size: 15, y: -4, colorText: UIColor.verifiedColor)
  594. }
  595. else if User.isInternal(userType: data.userType ?? "") {
  596. content.attributedText = self.set(image: UIImage(named: "ic_internal", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(data.fullName)", size: 15, y: -4, colorText: UIColor.internalColor)
  597. } else if User.isCallCenter(userType: data.userType ?? "") {
  598. // let dataCategory = CategoryCC.getDataFromServiceId(service_id: data.ex_offmp!)
  599. // if dataCategory != nil {
  600. // content.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(data.fullName) (\(dataCategory!.service_name))", size: 15, y: -4, colorText: UIColor.ccColor)
  601. // } else {
  602. content.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(data.fullName)", size: 15, y: -4, colorText: UIColor.ccColor)
  603. // }
  604. } else {
  605. content.text = data.fullName
  606. }
  607. content.textProperties.font = UIFont.systemFont(ofSize: 14)
  608. mcell.contentConfiguration = content
  609. }
  610. else if(dest == BroadcastViewController.DESTINATION_GROUP){
  611. var content = mcell.defaultContentConfiguration()
  612. let group: Group
  613. group = groups[indexPath.row]
  614. content.imageProperties.maximumSize = CGSize(width: 40, height: 40)
  615. getImage(name: group.profile, placeholderImage: UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in
  616. content.image = image
  617. // tableView.reloadRows(at: [indexPath], with: .none)
  618. }
  619. content.text = group.name
  620. content.textProperties.font = UIFont.systemFont(ofSize: 14)
  621. mcell.contentConfiguration = content
  622. }
  623. return mcell
  624. }
  625. else {
  626. return super.tableView(tableView, cellForRowAt: indexPath)
  627. }
  628. }
  629. override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  630. tableView.deselectRow(at: indexPath, animated: true)
  631. if(tableView == memberTable){
  632. deleteMember(index: indexPath.item)
  633. }
  634. }
  635. func deleteMember(index: Int){
  636. if(dest == BroadcastViewController.DESTINATION_SPESIFIC){
  637. contacts.remove(at: index)
  638. }
  639. else{
  640. groups.remove(at: index)
  641. }
  642. memberTable.reloadData()
  643. tableView.reloadData()
  644. }
  645. override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  646. if(tableView == memberTable){
  647. if(dest == BroadcastViewController.DESTINATION_SPESIFIC){
  648. return contacts.count
  649. }
  650. else if(dest == BroadcastViewController.DESTINATION_GROUP){
  651. return groups.count
  652. }
  653. else {
  654. return 0
  655. }
  656. }
  657. else {
  658. return super.tableView(tableView, numberOfRowsInSection: section)
  659. }
  660. }
  661. override func numberOfSections(in tableView: UITableView) -> Int {
  662. if(tableView == memberTable){
  663. return 1
  664. }
  665. else {
  666. return super.numberOfSections(in: tableView)
  667. }
  668. }
  669. func set(image: UIImage, with text: String, size: CGFloat, y: CGFloat, colorText: UIColor = UIColor.black) -> NSAttributedString {
  670. let attachment = NSTextAttachment()
  671. attachment.image = image
  672. attachment.bounds = CGRect(x: 0, y: y, width: size, height: size)
  673. let attachmentStr = NSAttributedString(attachment: attachment)
  674. let mutableAttributedString = NSMutableAttributedString()
  675. mutableAttributedString.append(attachmentStr)
  676. let attributedStringColor = [NSAttributedString.Key.foregroundColor : colorText]
  677. let textString = NSAttributedString(string: text, attributes: attributedStringColor)
  678. mutableAttributedString.append(textString)
  679. return mutableAttributedString
  680. }
  681. override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  682. if indexPath.section == 0 && broadcastModeLabel.text == "One Time".localized() {
  683. if indexPath.row == 5 {
  684. return 0
  685. }
  686. }
  687. if indexPath.section == 3 && (targetAudienceLabel.text != "Group".localized() && targetAudienceLabel.text != "User".localized()) {
  688. return 0
  689. }
  690. if indexPath.section == 3 {
  691. if targetAudienceLabel.text == "Group".localized() {
  692. return CGFloat(44 + (44 * groups.count) + 7)
  693. }
  694. return CGFloat(44 + (44 * contacts.count) + 7)
  695. }
  696. if indexPath.section == 4 {
  697. return 260
  698. }
  699. return 44
  700. }
  701. }
  702. struct Form {
  703. var id = 0
  704. var formId = "0"
  705. var title = ""
  706. var createdDate = 0
  707. var createdBy = ""
  708. var sqNo = 0
  709. }