ContactCallViewController.swift 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. //
  2. // ContactViewController.swift
  3. // FloatingButtonApp
  4. //
  5. // Created by Yayan Dwi on 05/08/21.
  6. //
  7. import UIKit
  8. import nuSDKService
  9. import NotificationBannerSwift
  10. class ContactCallViewController: UIViewController {
  11. @IBOutlet weak var tableView: UITableView!
  12. var dataPersonNotChange: [[String: String?]] = []
  13. var dataPerson: [[String: String?]] = []
  14. var fillteredData: [[String: String?]] = []
  15. var isAddParticipantVideo: Bool = false
  16. var connectedCall: [[String: String?]] = []
  17. var isDismiss: (([String: String?]) -> ())?
  18. var searchController: UISearchController!
  19. var isSearchBarEmpty: Bool {
  20. return searchController.searchBar.text!.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
  21. }
  22. var isFilltering: Bool {
  23. return searchController.isActive && !isSearchBarEmpty
  24. }
  25. var onlyAudioOrVideo = 0
  26. var startWhiteBoard = false
  27. var startSS = false
  28. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  29. if (segue.identifier == "videoVC") {
  30. if !CheckConnection.isConnectedToNetwork() {
  31. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  32. imageView.tintColor = .white
  33. 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)
  34. banner.show()
  35. return
  36. }
  37. let destination = segue.destination as! QmeraVideoViewController
  38. let index = sender as! UIButton
  39. destination.dataPerson.append(dataPerson[index.tag])
  40. }
  41. }
  42. override func viewDidDisappear(_ animated: Bool) {
  43. NotificationCenter.default.removeObserver(self)
  44. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "refreshView"), object: nil, userInfo: nil)
  45. }
  46. override func viewDidLoad() {
  47. super.viewDidLoad()
  48. title = "Start Call".localized()
  49. if startWhiteBoard && startSS {
  50. title = "Start Whiteboard/Screen Sharing".localized()
  51. } else if onlyAudioOrVideo == 1 {
  52. title = "Start Audio Call".localized()
  53. } else if onlyAudioOrVideo == 2 {
  54. title = "Start Video Call".localized()
  55. } else if startWhiteBoard {
  56. title = "Start Whiteboard".localized()
  57. } else if startSS {
  58. title = "Start Screen Sharing".localized()
  59. }
  60. let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16.0), NSAttributedString.Key.foregroundColor: UIColor.white]
  61. self.navigationController?.navigationBar.titleTextAttributes = attributes
  62. if (isAddParticipantVideo) {
  63. title = "Friends".localized()
  64. } else {
  65. let cancel = UIBarButtonItem(title: "Cancel".localized(), style: .plain, target: self, action: #selector(didTapCancel(sender:)))
  66. navigationItem.leftBarButtonItem = cancel
  67. }
  68. let buttonAddFriend = UIBarButtonItem(image: UIImage(systemName: "person.badge.plus", withConfiguration: UIImage.SymbolConfiguration(pointSize: 18, weight: .regular, scale: .default))?.withTintColor(.white), style: .plain, target: self, action: #selector(addFriend(sender:)))
  69. navigationItem.rightBarButtonItem = buttonAddFriend
  70. getData()
  71. dataPersonNotChange = dataPerson
  72. searchController = UISearchController(searchResultsController: nil)
  73. searchController.delegate = self
  74. searchController.searchResultsUpdater = self
  75. searchController.searchBar.autocapitalizationType = .none
  76. searchController.searchBar.delegate = self
  77. searchController.searchBar.barTintColor = .secondaryColor
  78. searchController.searchBar.searchTextField.backgroundColor = .secondaryColor
  79. searchController.obscuresBackgroundDuringPresentation = false
  80. searchController.searchBar.searchTextField.attributedPlaceholder = NSAttributedString(string: "Search".localized(), attributes: [NSAttributedString.Key.foregroundColor: UIColor.gray])
  81. searchController.searchBar.setMagnifyingGlassColorTo(color: .mainColor)
  82. searchController.searchBar.tintColor = .mainColor
  83. navigationItem.searchController = searchController
  84. navigationItem.hidesSearchBarWhenScrolling = false
  85. definesPresentationContext = true
  86. tableView.delegate = self
  87. tableView.dataSource = self
  88. let center: NotificationCenter = NotificationCenter.default
  89. center.addObserver(self, selector: #selector(refresh(notification:)), name: NSNotification.Name(rawValue: "onUpdatePersonInfo"), object: nil)
  90. }
  91. @objc func addFriend(sender: UIBarButtonItem) {
  92. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "addFriendNav") as! UINavigationController
  93. if let vc = controller.viewControllers.first as? AddFriendTableViewController {
  94. vc.isDismiss = {
  95. self.getData()
  96. self.dataPersonNotChange = self.dataPerson
  97. self.tableView.reloadData()
  98. }
  99. }
  100. self.navigationController?.present(controller, animated: true, completion: nil)
  101. }
  102. @objc func refresh(notification: NSNotification) {
  103. DispatchQueue.main.async {
  104. print("MASuK SINI DONG")
  105. self.getData()
  106. self.dataPersonNotChange = self.dataPerson
  107. self.tableView.reloadData()
  108. }
  109. }
  110. @objc func didTapCancel(sender: AnyObject) {
  111. navigationController?.dismiss(animated: true, completion: nil)
  112. }
  113. @objc func didTapBroadcastButton(sender: AnyObject){
  114. }
  115. func getData() {
  116. dataPerson.removeAll()
  117. let idMe = UserDefaults.standard.string(forKey: "me") as String?
  118. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  119. if let cursorData = Database.shared.getRecords(fmdb: fmdb, query: "SELECT f_pin, first_name, last_name, official_account, image_id, device_id, offline_mode, user_type, ex_block, ex_offmp FROM BUDDY where official_account<>'1' and f_pin <> '\(idMe!)' order by 4 desc, 2 collate nocase asc") {
  120. while cursorData.next() {
  121. var row: [String: String?] = [:]
  122. row["f_pin"] = cursorData.string(forColumnIndex: 0)
  123. if(connectedCall.count > 0 && connectedCall.contains(where: { $0["f_pin"] == row["f_pin"] })) {
  124. continue
  125. }
  126. var name = ""
  127. if let firstname = cursorData.string(forColumnIndex: 1) {
  128. name = firstname
  129. }
  130. if let lastname = cursorData.string(forColumnIndex: 2) {
  131. name = name + " " + lastname
  132. }
  133. if name.trimmingCharacters(in: .whitespaces) == "USR\(row["f_pin"]!!)" {
  134. continue
  135. }
  136. row["block"] = cursorData.string(forColumnIndex: 8)
  137. if row["block"] == "1" || row["block"] == "-1" {
  138. continue
  139. }
  140. row["name"] = name
  141. row["picture"] = cursorData.string(forColumnIndex: 4)
  142. row["isOfficial"] = cursorData.string(forColumnIndex: 3)
  143. row["deviceId"] = cursorData.string(forColumnIndex: 5)
  144. row["isOffline"] = cursorData.string(forColumnIndex: 6)
  145. row["user_type"] = cursorData.string(forColumnIndex: 7)
  146. row["ex_offmp"] = cursorData.string(forColumnIndex: 7)
  147. dataPerson.append(row)
  148. }
  149. cursorData.close()
  150. }
  151. })
  152. }
  153. func filterContentForSearchText(_ searchText: String) {
  154. fillteredData = self.dataPerson.filter { $0["name"]!!.lowercased().contains(searchText.lowercased()) }
  155. tableView.reloadData()
  156. }
  157. }
  158. extension ContactCallViewController: UITableViewDelegate {
  159. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  160. if startWhiteBoard && startSS {
  161. return
  162. } else if (isAddParticipantVideo) {
  163. self.dismiss(animated: true, completion: {
  164. self.isDismiss?(self.dataPerson[indexPath.row] as [String: String?])
  165. })
  166. } else if startWhiteBoard {
  167. if !CheckConnection.isConnectedToNetwork() {
  168. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  169. imageView.tintColor = .white
  170. 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)
  171. banner.show()
  172. return
  173. }
  174. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "wbVC") as! WhiteboardViewController
  175. controller.modalPresentationStyle = .overFullScreen
  176. controller.fromContact = 0
  177. controller.user = User.getData(pin: self.dataPerson[indexPath.row]["f_pin"]!!)
  178. present(controller, animated: true, completion: nil)
  179. } else if startSS {
  180. if !CheckConnection.isConnectedToNetwork() {
  181. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  182. imageView.tintColor = .white
  183. 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)
  184. banner.show()
  185. return
  186. }
  187. let controller = ScreenSharingViewController()
  188. controller.modalPresentationStyle = .overFullScreen
  189. controller.fromContact = 0
  190. controller.user = User.getData(pin: self.dataPerson[indexPath.row]["f_pin"]!!)
  191. present(controller, animated: true, completion: nil)
  192. }
  193. }
  194. }
  195. extension ContactCallViewController: UITableViewDataSource {
  196. func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  197. return 60
  198. }
  199. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  200. if isFilltering {
  201. return fillteredData.count
  202. }
  203. return dataPersonNotChange.count
  204. }
  205. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  206. let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath ) as! ContactCallCell
  207. cell.imagePerson.layer.masksToBounds = false
  208. cell.imagePerson.circle()
  209. cell.imagePerson.clipsToBounds = true
  210. cell.imagePerson.image = UIImage(named: "Profile---Purple", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
  211. cell.imagePerson.contentMode = .scaleAspectFit
  212. if isFilltering {
  213. dataPerson = fillteredData
  214. } else {
  215. dataPerson = dataPersonNotChange
  216. }
  217. if dataPerson.count > 0 {
  218. let pictureImage = dataPerson[indexPath.row]["picture"]!
  219. if (pictureImage != "" && pictureImage != nil) {
  220. cell.imagePerson.setImage(name: pictureImage!)
  221. cell.imagePerson.contentMode = .scaleAspectFill
  222. }
  223. cell.selectionStyle = UITableViewCell.SelectionStyle.none
  224. if User.isOfficial(official_account: (dataPerson[indexPath.row]["isOfficial"] ?? "")!) || User.isOfficialRegular(official_account: (dataPerson[indexPath.row]["isOfficial"] ?? "")!) {
  225. cell.namePerson.attributedText = self.set(image: UIImage(named: "ic_official_flag", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(dataPerson[indexPath.row]["name"]!!)", size: 15, y: -4, colorText: UIColor.officialColor)
  226. } else if User.isVerified(official_account: (dataPerson[indexPath.row]["isOfficial"] ?? "")!) {
  227. cell.namePerson.attributedText = self.set(image: UIImage(named: "ic_verified", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(dataPerson[indexPath.row]["name"]!!)", size: 15, y: -4, colorText: UIColor.verifiedColor)
  228. }
  229. else if User.isInternal(userType: (dataPerson[indexPath.row]["user_type"] ?? "")!) {
  230. cell.namePerson.attributedText = self.set(image: UIImage(named: "ic_internal", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(dataPerson[indexPath.row]["name"]!!)", size: 15, y: -4, colorText: UIColor.internalColor)
  231. } else if User.isCallCenter(userType: (dataPerson[indexPath.row]["user_type"] ?? "")!) {
  232. let dataCategory = CategoryCC.getDataFromServiceId(service_id: (dataPerson[indexPath.row]["ex_offmp"] ?? "")!)
  233. if dataCategory != nil {
  234. cell.namePerson.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(dataPerson[indexPath.row]["name"]!!) (\(dataCategory!.service_name))", size: 15, y: -4, colorText: UIColor.ccColor)
  235. } else {
  236. cell.namePerson.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " \(dataPerson[indexPath.row]["name"]!!)", size: 15, y: -4, colorText: UIColor.ccColor)
  237. }
  238. } else {
  239. cell.namePerson.text = dataPerson[indexPath.row]["name"] as? String
  240. }
  241. if startWhiteBoard && startSS {
  242. cell.audioCallButton.tag = indexPath.row
  243. cell.videoCallButton.tag = indexPath.row
  244. cell.audioCallButton.setImage(UIImage(named: "pb_screen_share", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(.mainColor).resize(target: CGSize(width: 35, height: 35)), for: .normal)
  245. cell.videoCallButton.setImage(UIImage(named: "pb_whiteboard", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(.mainColor).resize(target: CGSize(width: 25, height: 25)), for: .normal)
  246. cell.audioCallButton.addTarget(self, action: #selector(SS(sender:)), for: .touchUpInside)
  247. cell.videoCallButton.addTarget(self, action: #selector(WB(sender:)), for: .touchUpInside)
  248. } else if onlyAudioOrVideo == 1 {
  249. if cell.videoCallButton != nil && cell.videoCallButton.isDescendant(of: cell) {
  250. cell.videoCallButton.removeFromSuperview()
  251. cell.audioCallButton.removeConstraints(cell.audioCallButton.constraints)
  252. cell.audioCallButton.anchor(right: cell.rightAnchor, paddingRight: 20.0, centerY: cell.centerYAnchor)
  253. }
  254. } else if startWhiteBoard || startSS {
  255. cell.audioCallButton.isHidden = true
  256. cell.videoCallButton.isHidden = true
  257. } else if onlyAudioOrVideo == 2 {
  258. cell.audioCallButton.isHidden = true
  259. } else if (isAddParticipantVideo) {
  260. cell.audioCallButton.isHidden = true
  261. cell.videoCallButton.isHidden = true
  262. } else {
  263. cell.audioCallButton.tag = indexPath.row
  264. cell.videoCallButton.tag = indexPath.row
  265. cell.audioCallButton.addTarget(self, action: #selector(call(sender:)), for: .touchUpInside)
  266. cell.videoCallButton.addTarget(self, action: #selector(videoCall(sender:)), for: .touchUpInside)
  267. }
  268. }
  269. return cell
  270. }
  271. @objc func call(sender: Any) {
  272. let index = sender as! UIButton
  273. if let pin = dataPerson[index.tag]["f_pin"] {
  274. if !CheckConnection.isConnectedToNetwork() {
  275. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  276. imageView.tintColor = .white
  277. 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)
  278. banner.show()
  279. return
  280. }
  281. let controller = QmeraAudioViewController()
  282. controller.user = User.getData(pin: pin)
  283. controller.isOutgoing = true
  284. controller.modalPresentationStyle = .overFullScreen
  285. present(controller, animated: true, completion: nil)
  286. }
  287. }
  288. @objc func videoCall(sender: Any) {
  289. let index = sender as! UIButton
  290. if !CheckConnection.isConnectedToNetwork() {
  291. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  292. imageView.tintColor = .white
  293. 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)
  294. banner.show()
  295. return
  296. }
  297. let videoVC = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "videoVCQmera") as! QmeraVideoViewController
  298. videoVC.dataPerson.append(dataPerson[index.tag])
  299. videoVC.modalPresentationStyle = .overFullScreen
  300. self.show(videoVC, sender: nil)
  301. }
  302. @objc func WB(sender: Any) {
  303. let index = sender as! UIButton
  304. if let pin = dataPerson[index.tag]["f_pin"] {
  305. if !CheckConnection.isConnectedToNetwork() {
  306. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  307. imageView.tintColor = .white
  308. 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)
  309. banner.show()
  310. return
  311. }
  312. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "wbVC") as! WhiteboardViewController
  313. controller.modalPresentationStyle = .overFullScreen
  314. controller.fromContact = 0
  315. controller.user = User.getData(pin: pin)
  316. present(controller, animated: true, completion: nil)
  317. }
  318. }
  319. @objc func SS(sender: Any) {
  320. let index = sender as! UIButton
  321. if let pin = dataPerson[index.tag]["f_pin"] {
  322. if !CheckConnection.isConnectedToNetwork() {
  323. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  324. imageView.tintColor = .white
  325. 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)
  326. banner.show()
  327. return
  328. }
  329. let controller = ScreenSharingViewController()
  330. controller.modalPresentationStyle = .overFullScreen
  331. controller.fromContact = 0
  332. controller.user = User.getData(pin: pin)
  333. present(controller, animated: true, completion: nil)
  334. }
  335. }
  336. }
  337. class ContactCallCell: UITableViewCell {
  338. @IBOutlet weak var imagePerson: UIImageView!
  339. @IBOutlet weak var videoCallButton: UIButton!
  340. @IBOutlet weak var audioCallButton: UIButton!
  341. @IBOutlet weak var namePerson: UILabel!
  342. }
  343. extension ContactCallViewController {
  344. func set(image: UIImage, with text: String, size: CGFloat, y: CGFloat, colorText: UIColor = UIColor.black) -> NSAttributedString {
  345. let attachment = NSTextAttachment()
  346. attachment.image = image
  347. attachment.bounds = CGRect(x: 0, y: y, width: size, height: size)
  348. let attachmentStr = NSAttributedString(attachment: attachment)
  349. let mutableAttributedString = NSMutableAttributedString()
  350. mutableAttributedString.append(attachmentStr)
  351. let attributedStringColor = [NSAttributedString.Key.foregroundColor : colorText]
  352. let textString = NSAttributedString(string: text, attributes: attributedStringColor)
  353. mutableAttributedString.append(textString)
  354. return mutableAttributedString
  355. }
  356. }
  357. extension ContactCallViewController: UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating {
  358. func updateSearchResults(for searchController: UISearchController) {
  359. filterContentForSearchText(searchController.searchBar.text!.trimmingCharacters(in: .whitespacesAndNewlines))
  360. }
  361. func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
  362. searchBar.showsCancelButton = true
  363. let cBtn = searchBar.value(forKey: "cancelButton") as! UIButton
  364. cBtn.setTitle("Cancel".localized(), for: .normal)
  365. }
  366. func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
  367. searchBar.showsCancelButton = false
  368. }
  369. }