BroadcastViewController.swift 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  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 = UserDefaults.standard.string(forKey: "me")!
  87. _ = DigiX.write(message: CoreMessage_TMessageBank.getFormList(p_pin: me, p_last_id: "0"))
  88. }
  89. navigationController?.navigationBar.backgroundColor = .mainColor
  90. navigationController?.navigationBar.tintColor = .white
  91. navigationController?.navigationBar.barTintColor = .mainColor
  92. navigationController?.navigationBar.isTranslucent = false
  93. navigationController?.navigationBar.overrideUserInterfaceStyle = .dark
  94. navigationController?.navigationBar.barStyle = .black
  95. navigationController?.view.backgroundColor = .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. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query) {
  133. while cursor.next() {
  134. var form = Form()
  135. form.id = cursor.long(forColumnIndex: 0)
  136. form.formId = cursor.string(forColumnIndex: 1)!
  137. form.title = cursor.string(forColumnIndex: 2)!
  138. form.createdDate = Int(cursor.string(forColumnIndex: 3)!)!
  139. form.createdBy = cursor.string(forColumnIndex: 4)!
  140. form.sqNo = Int(cursor.int(forColumnIndex: 5))
  141. forms.append(form)
  142. }
  143. }
  144. })
  145. // Do any additional setup after loading the view.
  146. }
  147. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  148. textField.resignFirstResponder()
  149. return true
  150. }
  151. func textViewDidBeginEditing(_ textView: UITextView) {
  152. if(textView.text == placeholder){
  153. textView.text = ""
  154. textView.textColor = .black
  155. }
  156. textView.becomeFirstResponder()
  157. }
  158. func textViewDidEndEditing(_ textView: UITextView)
  159. {
  160. if (textView.text == "")
  161. {
  162. textView.text = placeholder
  163. textView.textColor = .opaqueSeparator
  164. }
  165. textView.resignFirstResponder()
  166. }
  167. func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
  168. if text == "\n" {
  169. textView.resignFirstResponder()
  170. return false
  171. }
  172. return true
  173. }
  174. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  175. if segue.identifier == "br_audience" {
  176. let destination = segue.destination as! AudienceViewController
  177. destination.isBroadcast = true
  178. destination.selected = targetAudienceLabel.text
  179. } else if segue.identifier == "br_type" {
  180. let destination = segue.destination as! TypeViewController
  181. destination.selected = broadcastTypeLabel.text
  182. } else if segue.identifier == "br_mode" {
  183. let destination = segue.destination as! BroadcastModeViewController
  184. destination.selected = broadcastModeLabel.text
  185. } else if segue.identifier == "br_variant" {
  186. let destination = segue.destination as! BroadcastVariantViewController
  187. destination.selected = broadcastVariantLabel.text
  188. destination.data = forms
  189. } else if segue.identifier == "br_member" {
  190. let destination = segue.destination as! BroadcastMembersTableViewController
  191. let isGroup = dest == BroadcastViewController.DESTINATION_GROUP
  192. destination.isGroup = isGroup
  193. if(isGroup){
  194. for g in groups{
  195. destination.existing.append(g.id)
  196. }
  197. }
  198. else {
  199. for c in contacts {
  200. destination.existing.append(c.pin)
  201. }
  202. }
  203. }
  204. }
  205. @objc func didTapCancel() {
  206. navigationController?.dismiss(animated: true, completion: nil)
  207. }
  208. @IBAction func selectImage(_ sender: Any) {
  209. imageVideoPicker.present(source: .imageAlbum)
  210. }
  211. @IBAction func selectVideo(_ sender: Any) {
  212. imageVideoPicker.present(source: .videoAlbum)
  213. }
  214. @IBAction func selectDocument(_ sender: Any) {
  215. documentPicker.present()
  216. }
  217. func didSelect(imagevideo: Any?) {
  218. if (imagevideo != nil) {
  219. imageVideoData = imagevideo as? [UIImagePickerController.InfoKey: Any]
  220. if (imageVideoData![.mediaType] as! String == "public.movie") {
  221. do {
  222. let url = imageVideoData![.mediaURL] as! URL
  223. let asset = AVURLAsset(url: url, options: nil)
  224. let imgGenerator = AVAssetImageGenerator(asset: asset)
  225. imgGenerator.appliesPreferredTrackTransform = true
  226. let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
  227. let thumbnail = UIImage(cgImage: cgImage)
  228. imagePreview.image = thumbnail
  229. self.fileType = BroadcastViewController.FILE_TYPE_VIDEO
  230. } catch let error {
  231. //print(("*** Error generating thumbnail: \(error.localizedDescription)")
  232. }
  233. } else {
  234. let url = imageVideoData![.imageURL] as! URL
  235. //print(("url: \(url.lastPathComponent)")
  236. imagePreview.image = imageVideoData![.originalImage] as? UIImage
  237. self.fileType = BroadcastViewController.FILE_TYPE_IMAGE
  238. }
  239. imagePreview.isHidden = false
  240. documentPreview.isHidden = true
  241. clearAttachButton.isHidden = false
  242. }
  243. }
  244. func didSelectDocument(document: Any?) {
  245. if (document != nil) {
  246. previewItem = (document as! [URL])[0] as URL
  247. fileType = BroadcastViewController.FILE_TYPE_DOCUMENT
  248. fileId = previewItem?.lastPathComponent ?? ""
  249. documentLabel.text = fileId
  250. imagePreview.isHidden = true
  251. documentPreview.isHidden = false
  252. clearAttachButton.isHidden = false
  253. }
  254. }
  255. func uploadAttachment(){
  256. }
  257. @IBAction func addMembers(_ sender: Any) {
  258. }
  259. @IBAction func clearAttach(_ sender: Any) {
  260. clearAttachment()
  261. }
  262. func clearAttachment(){
  263. fileType = BroadcastViewController.FILE_TYPE_CHAT
  264. thumbId = ""
  265. fileId = ""
  266. documentLabel.text = ""
  267. imagePreview.isHidden = true
  268. documentPreview.isHidden = true
  269. clearAttachButton.isHidden = true
  270. imageVideoData = nil
  271. previewItem = nil
  272. }
  273. func showActivityIndicatory() {
  274. loadingView.view.backgroundColor = .black.withAlphaComponent(0.3)
  275. let activityView = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large)
  276. activityView.center = self.view.center
  277. loadingView.view.addSubview(activityView)
  278. activityView.startAnimating()
  279. loadingView.modalPresentationStyle = .custom
  280. loadingView.modalTransitionStyle = .crossDissolve
  281. self.present(loadingView, animated: true)
  282. }
  283. @objc func submitBroadcast() {
  284. let startTime = startTimePicker.date.millisecondsSince1970
  285. var endTime = startTime
  286. if(!endTimeCell.isHidden){
  287. endTime = endTimePicker.date.millisecondsSince1970
  288. }
  289. if(startTime > endTime){
  290. return
  291. }
  292. messageTitle = titleTextField.text!
  293. message = messageTextView.text
  294. link = linkTextField.text!
  295. dest = "\(targetAudienceLabel.tag + 1)"
  296. type = "\(broadcastTypeLabel.tag + 1)"
  297. mode = "\(broadcastModeLabel.tag + 1)"
  298. if(messageTitle.trimmingCharacters(in: .whitespaces).isEmpty || message.trimmingCharacters(in: .whitespaces).isEmpty){
  299. let alert = LibAlertController(title: "", message: "Title and message must not be empty".localized(), preferredStyle: .alert)
  300. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: nil))
  301. self.present(alert, animated: true, completion: nil)
  302. return
  303. }
  304. if(dest == BroadcastViewController.DESTINATION_GROUP){
  305. if(groups.isEmpty){
  306. let alert = LibAlertController(title: "", message: "Please select at least one contact".localized(), preferredStyle: .alert)
  307. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: nil))
  308. self.present(alert, animated: true, completion: nil)
  309. return
  310. }
  311. var gs = [String]()
  312. for g in groups {
  313. gs.append(g.id)
  314. }
  315. let jsonData = try! JSONSerialization.data(withJSONObject: gs, options: [])
  316. membersInvited = String(data: jsonData, encoding: .utf8) ?? ""
  317. }
  318. else if(dest == BroadcastViewController.DESTINATION_SPESIFIC){
  319. if(contacts.isEmpty){
  320. let alert = LibAlertController(title: "", message: "Please select at least one contact".localized(), preferredStyle: .alert)
  321. alert.addAction(UIAlertAction(title: "OK".localized(), style: UIAlertAction.Style.default, handler: nil))
  322. self.present(alert, animated: true, completion: nil)
  323. return
  324. }
  325. var cs = [String]()
  326. for c in contacts {
  327. cs.append(c.pin)
  328. }
  329. let jsonData = try! JSONSerialization.data(withJSONObject: cs, options: [])
  330. membersInvited = String(data: jsonData, encoding: .utf8) ?? ""
  331. }
  332. //print(("dest: \(dest)")
  333. //print(("type: \(type)")
  334. //print(("mode: \(mode)")
  335. //print(("fileType: \(fileType)")
  336. //print(("thumb_id: \(thumbId)")
  337. //print(("file_id: \(fileId)")
  338. //print(("members: \(membersInvited)")
  339. if !CheckConnection.isConnectedToNetwork() {
  340. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  341. imageView.tintColor = .white
  342. 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)
  343. banner.show()
  344. return
  345. }
  346. showActivityIndicatory()
  347. if(form == BroadcastViewController.FORM_NOT_FORM){
  348. if(fileType == BroadcastViewController.FILE_TYPE_IMAGE){
  349. saveImage()
  350. }
  351. else if(fileType == BroadcastViewController.FILE_TYPE_VIDEO){
  352. saveVideo()
  353. }
  354. else if(fileType == BroadcastViewController.FILE_TYPE_DOCUMENT){
  355. saveDocument()
  356. }
  357. }
  358. else {
  359. clearAttachment()
  360. }
  361. if !thumbId.isEmpty {
  362. Network().uploadHTTP(name: String(thumbId)) { (result1, progress, response1) in
  363. if result1 {
  364. if progress == 100 {
  365. Network().uploadHTTP(name: String(self.fileId)) { (result2, progress, response2) in
  366. if result2 {
  367. if progress == 100 {
  368. self.sendMsg(startTime: startTime, endTime: endTime)
  369. }
  370. }
  371. }
  372. }
  373. }
  374. }
  375. } else if !fileId.isEmpty {
  376. Network().uploadHTTP(name: String(fileId)) { (result2, progress, response2) in
  377. if result2 {
  378. if progress == 100 {
  379. self.sendMsg(startTime: startTime, endTime: endTime)
  380. }
  381. }
  382. }
  383. } else {
  384. sendMsg(startTime: startTime, endTime: endTime)
  385. }
  386. }
  387. func saveImage(){
  388. var originalImageName = ""
  389. if (imageVideoData![.imageURL] == nil) {
  390. originalImageName = "\(Date().currentTimeMillis())_takeImage"
  391. } else {
  392. let urlImage = (imageVideoData![.imageURL] as! NSURL).absoluteString
  393. originalImageName = (urlImage! as NSString).lastPathComponent
  394. }
  395. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
  396. let compressedImageName = "THUMB-Qmera_image_\(originalImageName)"
  397. let thumbName = "THUMB_Qmera_image_\(originalImageName)"
  398. let fileURL = documentsDirectory.appendingPathComponent(compressedImageName)
  399. let compressedImage = (imageVideoData![.originalImage] as! UIImage).jpegData(compressionQuality: 1.0)
  400. if let data = compressedImage,
  401. !FileManager.default.fileExists(atPath: fileURL.path) {
  402. do {
  403. try data.write(to: fileURL)
  404. //print(("file saved")
  405. } catch {
  406. //print(("error saving file:", error)
  407. }
  408. }
  409. let thumbImage = UIImage(data: compressedImage!)
  410. let fileURLTHUMB = documentsDirectory.appendingPathComponent(thumbName)
  411. if let dataThumb = thumbImage!.jpegData(compressionQuality: 0.25),
  412. !FileManager.default.fileExists(atPath: fileURLTHUMB.path) {
  413. do {
  414. try dataThumb.write(to: fileURLTHUMB)
  415. //print(("thumb saved")
  416. } catch {
  417. //print(("error saving file:", error)
  418. }
  419. }
  420. fileId = compressedImageName
  421. thumbId = thumbName
  422. }
  423. func saveVideo(){
  424. guard var dataVideo = try? Data(contentsOf: imageVideoData![.mediaURL] as! URL) else {
  425. return
  426. }
  427. let sizeOfVideo = Double(dataVideo.count / 1048576)
  428. if (sizeOfVideo > 10.0) {
  429. let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + UUID().uuidString + ".mp4")
  430. compressVideo(inputURL: imageVideoData![.mediaURL] as! URL,
  431. outputURL: compressedURL) { exportSession in
  432. guard let session = exportSession else {
  433. return
  434. }
  435. switch session.status {
  436. case .unknown:
  437. break
  438. case .waiting:
  439. break
  440. case .exporting:
  441. break
  442. case .completed:
  443. guard let compressedData = try? Data(contentsOf: compressedURL) else {
  444. return
  445. }
  446. dataVideo = compressedData
  447. case .failed:
  448. break
  449. case .cancelled:
  450. break
  451. @unknown default:
  452. break
  453. }
  454. }
  455. }
  456. let urlVideo = (imageVideoData![.mediaURL] as! NSURL).absoluteString
  457. let originalVideoName = (urlVideo! as NSString).lastPathComponent
  458. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
  459. let renamedVideoName = "Qmera_video_\(originalVideoName)"
  460. let thumbName = "THUMB_Qmera_video_\(originalVideoName)"
  461. let fileURL = documentsDirectory.appendingPathComponent(renamedVideoName)
  462. if !FileManager.default.fileExists(atPath: fileURL.path) {
  463. do {
  464. try dataVideo.write(to: fileURL)
  465. //print(("file saved")
  466. } catch {
  467. //print(("error saving file:", error)
  468. }
  469. }
  470. let dataThumbVideo = imagePreview.image!.jpegData(compressionQuality: 1.0)
  471. let fileURLTHUMB = documentsDirectory.appendingPathComponent(thumbName)
  472. if !FileManager.default.fileExists(atPath: fileURLTHUMB.path) {
  473. do {
  474. try dataThumbVideo!.write(to: fileURLTHUMB)
  475. //print(("thumb saved")
  476. } catch {
  477. //print(("error saving file:", error)
  478. }
  479. }
  480. fileId = renamedVideoName
  481. thumbId = thumbName
  482. }
  483. func saveDocument(){
  484. do {
  485. let dataFile = try Data(contentsOf: self.previewItem! as URL)
  486. let urlFile = self.previewItem?.absoluteString
  487. var originaFileName = (urlFile! as NSString).lastPathComponent
  488. originaFileName = NSString(string: originaFileName).removingPercentEncoding!
  489. let renamedNameFile = "Qmera_doc_" + "\(Date().currentTimeMillis())_" + originaFileName
  490. let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
  491. let fileURL = documentsDirectory.appendingPathComponent(renamedNameFile)
  492. if !FileManager.default.fileExists(atPath: fileURL.path) {
  493. do {
  494. try dataFile.write(to: fileURL)
  495. //print(("file saved")
  496. } catch {
  497. //print(("error saving file:", error)
  498. }
  499. }
  500. fileId = renamedNameFile
  501. } catch {
  502. }
  503. }
  504. func compressVideo(inputURL: URL,
  505. outputURL: URL,
  506. handler:@escaping (_ exportSession: AVAssetExportSession?) -> Void) {
  507. let urlAsset = AVURLAsset(url: inputURL, options: nil)
  508. guard let exportSession = AVAssetExportSession(asset: urlAsset,
  509. presetName: AVAssetExportPresetMediumQuality) else {
  510. handler(nil)
  511. return
  512. }
  513. exportSession.outputURL = outputURL
  514. exportSession.outputFileType = .mp4
  515. exportSession.exportAsynchronously {
  516. handler(exportSession)
  517. }
  518. }
  519. func sendMsg(startTime: Int64, endTime: Int64){
  520. 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)
  521. if(form != BroadcastViewController.FORM_NOT_FORM){
  522. message.mBodies[CoreMessage_TMessageKey.FILE_ID] = form
  523. message.mBodies[CoreMessage_TMessageKey.MESSAGE_SCOPE_ID] = "18"
  524. }
  525. if let response = DigiX.writeSync(message: message) {
  526. if (response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "00") {
  527. DispatchQueue.main.async {
  528. let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
  529. imageView.tintColor = .white
  530. 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)
  531. banner.show()
  532. self.navigationController?.presentingViewController?.dismiss(animated: true)
  533. }
  534. } else {
  535. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  536. imageView.tintColor = .white
  537. 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)
  538. banner.show()
  539. self.loadingView.dismiss(animated: true)
  540. }
  541. }
  542. }
  543. /*
  544. // MARK: - Navigation
  545. // In a storyboard-based application, you will often want to do a little preparation before navigation
  546. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  547. // Get the new view controller using segue.destination.
  548. // Pass the selected object to the new view controller.
  549. }
  550. */
  551. @IBAction func result(unwind segue: UIStoryboardSegue) {
  552. }
  553. override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  554. if(tableView == memberTable){
  555. let mcell = tableView.dequeueReusableCell(withIdentifier: "memberCell", for: indexPath) as! BroadcastMembersTableViewCell
  556. if(dest == BroadcastViewController.DESTINATION_SPESIFIC){
  557. var content = mcell.defaultContentConfiguration()
  558. let data: User
  559. data = contacts[indexPath.row]
  560. content.imageProperties.maximumSize = CGSize(width: 40, height: 40)
  561. getImage(name: data.thumb, placeholderImage: UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: DigiX.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath, completion: { result, isDownloaded, image in
  562. content.image = image
  563. })
  564. if User.isOfficial(official_account: data.official ?? "") || User.isOfficialRegular(official_account: data.official ?? "") {
  565. content.attributedText = self.set(image: UIImage(named: "ic_official_flag", in: Bundle.resourceBundle(for: DigiX.self), with: nil)!, with: " \(data.fullName)", size: 15, y: -4, colorText: UIColor.officialColor)
  566. } else if User.isVerified(official_account: data.official ?? "") {
  567. content.attributedText = self.set(image: UIImage(named: "ic_verified", in: Bundle.resourceBundle(for: DigiX.self), with: nil)!, with: " \(data.fullName)", size: 15, y: -4, colorText: UIColor.verifiedColor)
  568. }
  569. else if User.isInternal(userType: data.userType ?? "") {
  570. content.attributedText = self.set(image: UIImage(named: "ic_internal", in: Bundle.resourceBundle(for: DigiX.self), with: nil)!, with: " \(data.fullName)", size: 15, y: -4, colorText: UIColor.internalColor)
  571. } else if User.isCallCenter(userType: data.userType ?? "") {
  572. // let dataCategory = CategoryCC.getDataFromServiceId(service_id: data.ex_offmp!)
  573. // if dataCategory != nil {
  574. // content.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: DigiX.self), with: nil)!, with: " \(data.fullName) (\(dataCategory!.service_name))", size: 15, y: -4, colorText: UIColor.ccColor)
  575. // } else {
  576. content.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: DigiX.self), with: nil)!, with: " \(data.fullName)", size: 15, y: -4, colorText: UIColor.ccColor)
  577. // }
  578. } else {
  579. content.text = data.fullName
  580. }
  581. content.textProperties.font = UIFont.systemFont(ofSize: 14)
  582. mcell.contentConfiguration = content
  583. }
  584. else if(dest == BroadcastViewController.DESTINATION_GROUP){
  585. var content = mcell.defaultContentConfiguration()
  586. let group: Group
  587. group = groups[indexPath.row]
  588. content.imageProperties.maximumSize = CGSize(width: 40, height: 40)
  589. getImage(name: group.profile, placeholderImage: UIImage(named: "Conversation---Purple", in: Bundle.resourceBundle(for: DigiX.self), with: nil), isCircle: true, tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in
  590. content.image = image
  591. // tableView.reloadRows(at: [indexPath], with: .none)
  592. }
  593. content.text = group.name
  594. content.textProperties.font = UIFont.systemFont(ofSize: 14)
  595. mcell.contentConfiguration = content
  596. }
  597. return mcell
  598. }
  599. else {
  600. return super.tableView(tableView, cellForRowAt: indexPath)
  601. }
  602. }
  603. override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  604. tableView.deselectRow(at: indexPath, animated: true)
  605. if(tableView == memberTable){
  606. deleteMember(index: indexPath.item)
  607. }
  608. }
  609. func deleteMember(index: Int){
  610. if(dest == BroadcastViewController.DESTINATION_SPESIFIC){
  611. contacts.remove(at: index)
  612. }
  613. else{
  614. groups.remove(at: index)
  615. }
  616. memberTable.reloadData()
  617. tableView.reloadData()
  618. }
  619. override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  620. if(tableView == memberTable){
  621. if(dest == BroadcastViewController.DESTINATION_SPESIFIC){
  622. return contacts.count
  623. }
  624. else if(dest == BroadcastViewController.DESTINATION_GROUP){
  625. return groups.count
  626. }
  627. else {
  628. return 0
  629. }
  630. }
  631. else {
  632. return super.tableView(tableView, numberOfRowsInSection: section)
  633. }
  634. }
  635. override func numberOfSections(in tableView: UITableView) -> Int {
  636. if(tableView == memberTable){
  637. return 1
  638. }
  639. else {
  640. return super.numberOfSections(in: tableView)
  641. }
  642. }
  643. func set(image: UIImage, with text: String, size: CGFloat, y: CGFloat, colorText: UIColor = UIColor.black) -> NSAttributedString {
  644. let attachment = NSTextAttachment()
  645. attachment.image = image
  646. attachment.bounds = CGRect(x: 0, y: y, width: size, height: size)
  647. let attachmentStr = NSAttributedString(attachment: attachment)
  648. let mutableAttributedString = NSMutableAttributedString()
  649. mutableAttributedString.append(attachmentStr)
  650. let attributedStringColor = [NSAttributedString.Key.foregroundColor : colorText]
  651. let textString = NSAttributedString(string: text, attributes: attributedStringColor)
  652. mutableAttributedString.append(textString)
  653. return mutableAttributedString
  654. }
  655. override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  656. if indexPath.section == 0 && broadcastModeLabel.text == "One Time".localized() {
  657. if indexPath.row == 5 {
  658. return 0
  659. }
  660. }
  661. if indexPath.section == 3 && (targetAudienceLabel.text != "Group".localized() && targetAudienceLabel.text != "User".localized()) {
  662. return 0
  663. }
  664. if indexPath.section == 3 {
  665. if targetAudienceLabel.text == "Group".localized() {
  666. return CGFloat(44 + (44 * groups.count) + 7)
  667. }
  668. return CGFloat(44 + (44 * contacts.count) + 7)
  669. }
  670. if indexPath.section == 4 {
  671. return 260
  672. }
  673. return 44
  674. }
  675. }
  676. struct Form {
  677. var id = 0
  678. var formId = "0"
  679. var title = ""
  680. var createdDate = 0
  681. var createdBy = ""
  682. var sqNo = 0
  683. }