GroupDetailViewController.swift 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. //
  2. // GroupViewController.swift
  3. // Qmera
  4. //
  5. // Created by Yayan Dwi on 24/09/21.
  6. //
  7. import UIKit
  8. import NotificationBannerSwift
  9. import nuSDKService
  10. class GroupDetailViewController: UITableViewController {
  11. enum Flag {
  12. case edit
  13. case view
  14. }
  15. var flag: Flag = .edit
  16. var data: String = ""
  17. static let SUBGROUP_LEVEL_LIMIT = 10
  18. private var group: Group?
  19. private var isAdmin: Bool = false
  20. private var imageVideoPicker : ImageVideoPicker!
  21. private var tempImage: UIImage?
  22. private let imageAdmin = UIImageView()
  23. private let imageAddContact = UIImageView()
  24. private enum Section {
  25. case profile
  26. case description
  27. case access
  28. case topic
  29. case detail
  30. case member
  31. case exit
  32. }
  33. private var sections: [Section] = [
  34. .profile,
  35. .description,
  36. .access,
  37. .topic,
  38. .detail
  39. ]
  40. var checkReadMessage: (() -> ())?
  41. private let idSubGroup = Date().currentTimeMillis().toHex()
  42. var fromNotification = false
  43. override func viewDidLoad() {
  44. super.viewDidLoad()
  45. imageVideoPicker = ImageVideoPicker(presentationController: self, delegate: self)
  46. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  47. navigationController?.navigationBar.titleTextAttributes = textAttributes
  48. navigationController?.navigationBar.topItem?.backButtonTitle = ""
  49. if fromNotification {
  50. let imageButton = UIImageView(frame: CGRect(x: -16, y: 0, width: 20, height: 44))
  51. imageButton.image = UIImage(systemName: "chevron.backward", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular, scale: .default))?.withTintColor(.white)
  52. imageButton.contentMode = .left
  53. let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapExit))
  54. imageButton.isUserInteractionEnabled = true
  55. imageButton.addGestureRecognizer(tapGestureRecognizer)
  56. let leftItem = UIBarButtonItem(customView: imageButton)
  57. self.navigationItem.leftBarButtonItem = leftItem
  58. }
  59. reload()
  60. let center: NotificationCenter = NotificationCenter.default
  61. center.addObserver(self, selector: #selector(updateData(notification:)), name: NSNotification.Name(rawValue: "onGroup"), object: nil)
  62. center.addObserver(self, selector: #selector(updateData(notification:)), name: NSNotification.Name(rawValue: "onTopic"), object: nil)
  63. center.addObserver(self, selector: #selector(updateData(notification:)), name: NSNotification.Name(rawValue: "onMember"), object: nil)
  64. }
  65. override func viewWillDisappear(_ animated: Bool) {
  66. if self.isMovingFromParent {
  67. self.checkReadMessage?()
  68. }
  69. }
  70. var alert2: UIAlertController?
  71. var textFields = [UITextField]()
  72. // MARK: - Data source
  73. @objc func didTapExit() {
  74. self.dismiss(animated: true, completion: nil)
  75. }
  76. func reload() {
  77. getData { group in
  78. self.group = group
  79. if let myData = self.group?.members.first(where: { member in
  80. return member.pin == UserDefaults.standard.string(forKey: "me")!
  81. }) {
  82. if myData.position == "1" {
  83. self.isAdmin = true
  84. } else {
  85. self.isAdmin = false
  86. }
  87. }
  88. if self.sections.count == 5, group.groupType != "1" {
  89. self.sections.append(.member)
  90. self.sections.append(.exit)
  91. }
  92. DispatchQueue.main.async {
  93. self.title = group.name
  94. self.tableView.reloadData()
  95. if group.official == "1" && !group.parent.isEmpty {
  96. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  97. if let cursorImage = Database.shared.getRecords(fmdb: fmdb, query: "SELECT image_id FROM GROUPZ where group_type = 1 AND official = 1"), cursorImage.next() {
  98. self.group?.profile = cursorImage.string(forColumnIndex: 0)!
  99. cursorImage.close()
  100. }
  101. })
  102. }
  103. if self.isAdmin && group.official != "1" {
  104. var children : [UIAction] = []
  105. if Int(group.level)! <= GroupDetailViewController.SUBGROUP_LEVEL_LIMIT {
  106. children.append(UIAction(title: "Add Sub Group".localized(), handler: {(_) in
  107. self.createSubGroup()
  108. }))
  109. }
  110. children.append(UIAction(title: "Change Name Group".localized(), handler: {(_) in
  111. self.edit()
  112. }))
  113. let menu = UIMenu(title: "", children: children)
  114. let moreIcon = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), menu: menu)
  115. self.navigationItem.rightBarButtonItem = moreIcon
  116. }
  117. }
  118. }
  119. }
  120. func createSubGroup() {
  121. self.alert2 = UIAlertController(title: "Create Sub Group".localized(), message: nil, preferredStyle: .alert)
  122. self.textFields.removeAll()
  123. self.alert2?.addTextField{ (texfield) in
  124. texfield.placeholder = "Group's Name".localized()
  125. texfield.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
  126. }
  127. let submitAction = UIAlertAction(title: "Create".localized(), style: .default, handler: { (action) -> Void in
  128. let textField = self.alert2?.textFields![0]
  129. if !CheckConnection.isConnectedToNetwork() || API.nGetCLXConnState() == 0 {
  130. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  131. imageView.tintColor = .white
  132. 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)
  133. banner.show()
  134. return
  135. }
  136. var level = self.group!.level
  137. if level.isEmpty || level == "-1"{
  138. level = "2"
  139. } else {
  140. level = "\(Int(level)! + 1)"
  141. }
  142. print("level: \(level)")
  143. DispatchQueue.main.async {
  144. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getCreateSubGroup(group_id: self.idSubGroup, group_name: textField!.text!, parent_id: self.group!.id, level: level)) {
  145. if response.isOk() {
  146. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "groupDetailView") as! GroupDetailViewController
  147. controller.data = self.idSubGroup
  148. self.navigationController?.show(controller, sender: nil)
  149. self.navigationController?.viewControllers.removeSubrange(1...(self.navigationController?.viewControllers.count)! - 2)
  150. } else {
  151. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  152. imageView.tintColor = .white
  153. let banner = FloatingNotificationBanner(title: "Unable to access servers".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)
  154. banner.show()
  155. }
  156. }
  157. }
  158. })
  159. self.alert2?.addAction(submitAction)
  160. self.alert2?.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: nil))
  161. self.present(self.alert2!, animated: true, completion: nil)
  162. }
  163. func edit() {
  164. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "groupNameView") as! GroupNameViewController
  165. controller.data = self.data
  166. controller.name = group?.name
  167. controller.isDismiss = {
  168. self.reload()
  169. }
  170. let navController = UINavigationController(rootViewController: controller)
  171. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white]
  172. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  173. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  174. navController.navigationBar.titleTextAttributes = textAttributes
  175. navigationController?.present(navController, animated: true)
  176. }
  177. @objc func updateData(notification: NSNotification) {
  178. let data:[AnyHashable : Any] = notification.userInfo!
  179. if data["code"] as! String == "A008" && data["member"] as! String == UserDefaults.standard.string(forKey: "me")! {
  180. DispatchQueue.main.async {
  181. self.navigationController?.popViewController(animated: true)
  182. }
  183. } else if data["f_pin"] as! String != UserDefaults.standard.string(forKey: "me")! || data["code"] as! String == "BD" {
  184. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
  185. self.reload()
  186. }
  187. }
  188. }
  189. private func getData(completion: @escaping (Group) -> ()) {
  190. DispatchQueue.global().async {
  191. let query = "select g.group_id, g.f_name, g.image_id, g.quote, g.created_by, g.created_date, g.parent, g.group_type, g.is_open, g.official, g.level from GROUPZ g where g.group_id = '\(self.data)'"
  192. Database.shared.database?.inTransaction({ fmdb, rollback in
  193. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: query), cursor.next() {
  194. let group = Group(id: cursor.string(forColumnIndex: 0) ?? "",
  195. name: cursor.string(forColumnIndex: 1) ?? "",
  196. profile: cursor.string(forColumnIndex: 2) ?? "",
  197. quote: cursor.string(forColumnIndex: 3) ?? "",
  198. by: cursor.string(forColumnIndex: 4) ?? "",
  199. date: cursor.string(forColumnIndex: 5) ?? "",
  200. parent: cursor.string(forColumnIndex: 6) ?? "",
  201. groupType: cursor.string(forColumnIndex: 7) ?? "",
  202. isOpen: cursor.string(forColumnIndex: 8) ?? "",
  203. official: cursor.string(forColumnIndex: 9) ?? "",
  204. level: cursor.string(forColumnIndex: 10) ?? "")
  205. cursor.close()
  206. group.topics.append(Topic(chatId: "", title: "Lounge".localized(), thumb: ""))
  207. if let cursorTopic = Database.shared.getRecords(fmdb: fmdb, query: "select chat_id, title, thumb from DISCUSSION_FORUM where group_id = '\(self.data)'") {
  208. while cursorTopic.next() {
  209. let topic = Topic(chatId: cursorTopic.string(forColumnIndex: 0) ?? "",
  210. title: cursorTopic.string(forColumnIndex: 1) ?? "",
  211. thumb: cursorTopic.string(forColumnIndex: 2) ?? "")
  212. group.topics.append(topic)
  213. }
  214. cursorTopic.close()
  215. }
  216. if let cursorMember = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin, first_name, last_name, thumb_id, position from GROUPZ_MEMBER where group_id = '\(self.data)' order by 2 asc") {
  217. while cursorMember.next() {
  218. let member = Member(pin: cursorMember.string(forColumnIndex: 0) ?? "",
  219. firstName: cursorMember.string(forColumnIndex: 1) ?? "",
  220. lastName: cursorMember.string(forColumnIndex: 2) ?? "",
  221. thumb: cursorMember.string(forColumnIndex: 3) ?? "",
  222. position: cursorMember.string(forColumnIndex: 4) ?? "")
  223. if let cursorUser = Database.shared.getRecords(fmdb: fmdb, query: "SELECT user_type, official_account FROM BUDDY where f_pin='\(member.pin)'"), cursorUser.next() {
  224. member.userType = cursorUser.string(forColumnIndex: 0)
  225. member.official = cursorUser.string(forColumnIndex: 1)
  226. cursorUser.close()
  227. }
  228. group.members.append(member)
  229. }
  230. cursorMember.close()
  231. }
  232. completion(group)
  233. }
  234. })
  235. }
  236. }
  237. // MARK: - Cell selected
  238. override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  239. tableView.deselectRow(at: indexPath, animated: false)
  240. switch sections[indexPath.section] {
  241. case .profile:
  242. if isAdmin {
  243. let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
  244. alert.addAction(UIAlertAction(title: "Take Photo".localized(), style: .default, handler: { action in
  245. self.imageVideoPicker.present(source: .imageCamera)
  246. }))
  247. alert.addAction(UIAlertAction(title: "Choose Photo".localized(), style: .default, handler: { action in
  248. self.imageVideoPicker.present(source: .imageAlbum)
  249. }))
  250. alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { action in
  251. }))
  252. navigationController?.present(alert, animated: true)
  253. }
  254. case .description:
  255. if let g = group, isAdmin {
  256. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "groupDescView") as! GroupDescViewController
  257. controller.data = g.id
  258. controller.quote = g.quote
  259. controller.isDismiss = {
  260. self.reload()
  261. }
  262. let navController = UINavigationController(rootViewController: controller)
  263. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white]
  264. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  265. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  266. navController.navigationBar.titleTextAttributes = textAttributes
  267. navigationController?.present(navController, animated: true)
  268. }
  269. case .access:
  270. if let g = group, isAdmin, g.official != "1" {
  271. var currentAccess = g.isOpen
  272. if currentAccess.isEmpty || currentAccess == "0" {
  273. currentAccess = "1"
  274. } else {
  275. currentAccess = "0"
  276. }
  277. Nexilis.showLoader()
  278. self.changeOpenGroup(open: currentAccess) { result in
  279. if result {
  280. DispatchQueue.main.async {
  281. Nexilis.hideLoader(completion: {
  282. g.isOpen = currentAccess
  283. tableView.reloadRows(at: [indexPath], with: .none)
  284. })
  285. }
  286. } else {
  287. DispatchQueue.main.async {
  288. Nexilis.hideLoader(completion: {
  289. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  290. imageView.tintColor = .white
  291. 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)
  292. banner.show()
  293. })
  294. }
  295. }
  296. }
  297. }
  298. case .topic:
  299. if let g = group, isAdmin, indexPath.row == 0 {
  300. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "groupTopicView") as! GroupTopicViewController
  301. controller.data = g.id
  302. controller.isDismiss = {
  303. self.reload()
  304. }
  305. let navController = UINavigationController(rootViewController: controller)
  306. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white]
  307. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  308. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  309. navController.navigationBar.titleTextAttributes = textAttributes
  310. navigationController?.present(navController, animated: true)
  311. } else if let g = group, isAdmin {
  312. let topic = g.topics[indexPath.row - 1]
  313. if topic.chatId.isEmpty {
  314. if let controller = self.previousViewController as? EditorGroup {
  315. if controller.dataTopic["chat_id"] as! String == topic.chatId {
  316. self.navigationController?.popViewController(animated: true)
  317. return
  318. }
  319. controller.unique_l_pin = g.id
  320. controller.loadData()
  321. self.navigationController?.popViewController(animated: true)
  322. } else {
  323. self.navigationController?.popViewController(animated: true)
  324. let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
  325. editorGroupVC.hidesBottomBarWhenPushed = true
  326. editorGroupVC.unique_l_pin = g.id
  327. self.navigationController?.viewControllers.first?.show(editorGroupVC, sender: nil)
  328. }
  329. return
  330. }
  331. let alert = UIAlertController(title: nil, message: topic.title, preferredStyle: .actionSheet)
  332. alert.addAction(UIAlertAction(title: "Enter Topic", style: .default, handler: { action in
  333. if let controller = self.previousViewController as? EditorGroup {
  334. if controller.dataTopic["chat_id"] as! String == topic.chatId {
  335. self.navigationController?.popViewController(animated: true)
  336. return
  337. }
  338. controller.unique_l_pin = topic.chatId
  339. controller.loadData()
  340. self.navigationController?.popViewController(animated: true)
  341. } else {
  342. self.navigationController?.popViewController(animated: true)
  343. let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
  344. editorGroupVC.hidesBottomBarWhenPushed = true
  345. editorGroupVC.unique_l_pin = topic.chatId
  346. self.navigationController?.viewControllers.first?.show(editorGroupVC, sender: nil)
  347. }
  348. }))
  349. alert.addAction(UIAlertAction(title: "Rename Topic", style: .default, handler: { action in
  350. self.alert2 = UIAlertController(title: "Change Topic's Name".localized(), message: nil, preferredStyle: .alert)
  351. self.textFields.removeAll()
  352. self.alert2?.addTextField{ (texfield) in
  353. texfield.text = topic.title
  354. texfield.placeholder = "Topic's Name"
  355. texfield.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
  356. }
  357. let submitAction = UIAlertAction(title: "Rename".localized(), style: .default, handler: { (action) -> Void in
  358. let textField = self.alert2?.textFields![0]
  359. if !CheckConnection.isConnectedToNetwork() || API.nGetCLXConnState() == 0 {
  360. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  361. imageView.tintColor = .white
  362. 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)
  363. banner.show()
  364. return
  365. }
  366. if textField!.text! == topic.title {
  367. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  368. imageView.tintColor = .white
  369. let banner = FloatingNotificationBanner(title: "Topic name has been used. Enter another topic name".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)
  370. banner.show()
  371. return
  372. }
  373. if textField!.text! == "Lounge" || textField!.text! == "Beranda" {
  374. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  375. imageView.tintColor = .white
  376. let banner = FloatingNotificationBanner(title: "Topic already registered".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)
  377. banner.show()
  378. return
  379. }
  380. DispatchQueue.main.async {
  381. if let g = self.group, let _ = Nexilis.write(message: CoreMessage_TMessageBank.getUpdateChat(p_chat_id: topic.chatId, p_f_pin: g.id, p_title: textField!.text!, p_anonym: "", p_image: topic.thumb)) {
  382. let imageView = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
  383. imageView.tintColor = .white
  384. let banner = FloatingNotificationBanner(title: "Successfully changed".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)
  385. banner.show()
  386. }
  387. }
  388. })
  389. self.alert2?.addAction(submitAction)
  390. self.alert2?.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: nil))
  391. self.present(self.alert2!, animated: true, completion: nil)
  392. }))
  393. alert.addAction(UIAlertAction(title: "Remove Topic".localized(), style: .destructive, handler: { action in
  394. let message = "Remove \(topic.title) from the \"\(g.name)\" group?"
  395. let notif = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
  396. notif.addAction(UIAlertAction(title: "Remove".localized(), style: .destructive, handler: { notifAction in
  397. self.removeTopic(chatId: topic.chatId) { result in
  398. if result, let index = g.topics.firstIndex(of: topic) {
  399. Database.shared.database?.inTransaction({ (fmdb, rollback) in
  400. _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "chat_id = '\(topic.chatId)'")
  401. _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE", _where: "chat_id='\(topic.chatId)'")
  402. _ = Database.shared.deleteRecord(fmdb: fmdb, table: "MESSAGE_SUMMARY", _where: "l_pin='\(topic.chatId)'")
  403. })
  404. var data: [AnyHashable : Any] = [:]
  405. data["code"] = CoreMessage_TMessageCode.DELETE_CHAT
  406. data["f_pin"] = UserDefaults.standard.string(forKey: "me")!
  407. data["topicId"] = topic.chatId
  408. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "onTopic"), object: nil, userInfo: data)
  409. DispatchQueue.main.async {
  410. tableView.beginUpdates()
  411. tableView.deleteRows(at: [indexPath], with: .none)
  412. g.topics.remove(at: index)
  413. tableView.endUpdates()
  414. }
  415. }
  416. }
  417. }))
  418. notif.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { notifAction in
  419. }))
  420. self.navigationController?.present(notif, animated: true, completion: nil)
  421. }))
  422. alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { action in
  423. }))
  424. navigationController?.present(alert, animated: true)
  425. } else if let g = group {
  426. let topic = g.topics[indexPath.row]
  427. if topic.chatId.isEmpty {
  428. if let controller = self.previousViewController as? EditorGroup {
  429. if controller.dataTopic["chat_id"] as! String == topic.chatId {
  430. self.navigationController?.popViewController(animated: true)
  431. return
  432. }
  433. controller.unique_l_pin = g.id
  434. controller.loadData()
  435. self.navigationController?.popViewController(animated: true)
  436. } else {
  437. self.navigationController?.popViewController(animated: true)
  438. let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
  439. editorGroupVC.hidesBottomBarWhenPushed = true
  440. editorGroupVC.unique_l_pin = g.id
  441. self.navigationController?.viewControllers.first?.show(editorGroupVC, sender: nil)
  442. }
  443. return
  444. }
  445. else if let controller = self.previousViewController as? EditorGroup {
  446. if controller.dataTopic["chat_id"] as! String == topic.chatId {
  447. self.navigationController?.popViewController(animated: true)
  448. return
  449. }
  450. controller.unique_l_pin = topic.chatId
  451. controller.loadData()
  452. self.navigationController?.popViewController(animated: true)
  453. } else {
  454. self.navigationController?.popViewController(animated: true)
  455. let editorGroupVC = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "editorGroupVC") as! EditorGroup
  456. editorGroupVC.hidesBottomBarWhenPushed = true
  457. editorGroupVC.unique_l_pin = topic.chatId
  458. self.navigationController?.viewControllers.first?.show(editorGroupVC, sender: nil)
  459. }
  460. }
  461. case .member:
  462. if let g = group, isAdmin, indexPath.row == 0 {
  463. let controller = AppStoryBoard.Palio.instance.instantiateViewController(identifier: "groupMemberView") as! GroupMemberViewController
  464. controller.group = g
  465. if g.official == "1" && g.level == "3" {
  466. controller.isContactCenterInvite = true
  467. }
  468. controller.isDismiss = {
  469. self.reload()
  470. }
  471. let navController = UINavigationController(rootViewController: controller)
  472. let cancelButtonAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white]
  473. UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, for: .normal)
  474. let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
  475. navController.navigationBar.titleTextAttributes = textAttributes
  476. navController.navigationBar.largeTitleTextAttributes = textAttributes
  477. navigationController?.present(navController, animated: true)
  478. } else if let g = group, isAdmin {
  479. let member = g.members[indexPath.row - 1]
  480. if member.pin != UserDefaults.standard.string(forKey: "me")! {
  481. if member.pin == g.by {
  482. let data = User.getDataCanNil(pin: member.pin)
  483. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "profileView") as! ProfileViewController
  484. controller.flag = data == nil ? .invite : .friend
  485. controller.user = member
  486. controller.name = member.fullName
  487. controller.data = member.pin
  488. controller.picture = member.thumb
  489. self.navigationController?.show(controller, sender: nil)
  490. return
  491. }
  492. let alert = UIAlertController(title: nil, message: "\(member.firstName) \(member.lastName)", preferredStyle: .actionSheet)
  493. alert.addAction(UIAlertAction(title: "Info".localized(), style: .default, handler: { action in
  494. let data = User.getDataCanNil(pin: member.pin)
  495. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "profileView") as! ProfileViewController
  496. controller.flag = data == nil ? .invite : .friend
  497. controller.user = member
  498. controller.name = member.fullName
  499. controller.data = member.pin
  500. controller.picture = member.thumb
  501. controller.isDismiss = {
  502. self.reload()
  503. }
  504. self.navigationController?.show(controller, sender: nil)
  505. }))
  506. alert.addAction(UIAlertAction(title: member.position == "0" ? "Make Group Admin".localized() : "Remove Group Admin".localized(), style: member.position == "0" ? .default : .destructive, handler: { action in
  507. let message = "\(member.position == "0" ? "Make" : "Remove") \(member.fullName) from the \"\(g.name)\" group Admin?"
  508. let notif = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
  509. notif.addAction(UIAlertAction(title: member.position == "0" ? "Make".localized() : "Remove".localized(), style: member.position == "0" ? .default : .destructive, handler: { notifAction in
  510. self.changePosition(pin: member.pin, isAdmin: member.position == "0") { result in
  511. if result {
  512. DispatchQueue.main.async {
  513. tableView.beginUpdates()
  514. member.position = member.position == "1" ? "0" : "1"
  515. tableView.reloadRows(at: [indexPath], with: .none)
  516. tableView.endUpdates()
  517. }
  518. }
  519. }
  520. }))
  521. notif.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { notifAction in
  522. }))
  523. self.navigationController?.present(notif, animated: true, completion: nil)
  524. }))
  525. alert.addAction(UIAlertAction(title: "Remove From Group".localized(), style: .destructive, handler: { action in
  526. let message = "Remove \(member.fullName) from the \"\(g.name)\" group?"
  527. let notif = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
  528. notif.addAction(UIAlertAction(title: "Remove".localized(), style: .destructive, handler: { notifAction in
  529. self.exitGroup(pin: member.pin) { result in
  530. if result, let index = g.members.firstIndex(of: member) {
  531. DispatchQueue.main.async {
  532. tableView.beginUpdates()
  533. tableView.deleteRows(at: [indexPath], with: .none)
  534. g.members.remove(at: index)
  535. tableView.endUpdates()
  536. }
  537. }
  538. }
  539. }))
  540. notif.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { notifAction in
  541. }))
  542. self.navigationController?.present(notif, animated: true, completion: nil)
  543. }))
  544. alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { action in
  545. }))
  546. navigationController?.present(alert, animated: true)
  547. }
  548. } else if let g = group {
  549. let member = g.members[indexPath.row]
  550. if member.pin == UserDefaults.standard.string(forKey: "me") {
  551. // skip self profile
  552. return
  553. }
  554. let data = User.getDataCanNil(pin: member.pin)
  555. let controller = AppStoryBoard.Palio.instance.instantiateViewController(withIdentifier: "profileView") as! ProfileViewController
  556. controller.flag = data == nil ? .invite : .friend
  557. controller.user = member
  558. controller.name = member.fullName
  559. controller.data = member.pin
  560. controller.picture = member.thumb
  561. controller.isDismiss = {
  562. self.reload()
  563. }
  564. self.navigationController?.show(controller, sender: nil)
  565. }
  566. case .exit:
  567. if let g = group {
  568. let idMe = UserDefaults.standard.string(forKey: "me") as String?
  569. let admins = g.members.filter { member in
  570. return member.position == "1"
  571. }
  572. var isDeleted = false
  573. if admins.count == 1 {
  574. if admins.first?.pin == idMe {
  575. isDeleted = true
  576. }
  577. }
  578. let message: String
  579. if isDeleted {
  580. message = "Are you sure want to delete the group?".localized()
  581. // message = "Are you sure want to delete the \"\(g.name)\" group?".localized()
  582. } else {
  583. message = "Are you sure want to exit the group?".localized()
  584. // message = "Are you sure want to exit the \"\(g.name)\" group?".localized()
  585. }
  586. let alert = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
  587. alert.addAction(UIAlertAction(title: isDeleted ? "Delete Group".localized() : "Exit Group".localized(), style: .destructive, handler: { action in
  588. self.exitGroup(pin: isDeleted ? "ALL": UserDefaults.standard.string(forKey: "me")!) { result in
  589. if result {
  590. DispatchQueue.main.async {
  591. self.navigationController?.popToRootViewController(animated: true)
  592. }
  593. }
  594. }
  595. }))
  596. alert.addAction(UIAlertAction(title: "Cancel".localized(), style: .cancel, handler: { action in
  597. }))
  598. navigationController?.present(alert, animated: true)
  599. }
  600. default:
  601. print("No handler..")
  602. }
  603. }
  604. @objc func alertTextFieldDidChange(_ sender: UITextField) {
  605. if(!textFields.isEmpty){
  606. alert2?.actions[0].isEnabled = textFields[0].text!.trimmingCharacters(in: .whitespaces).count > 0
  607. }
  608. else {
  609. alert2?.actions[0].isEnabled = sender.text!.trimmingCharacters(in: .whitespaces).count > 0
  610. }
  611. }
  612. private func removeTopic(chatId: String, completion: @escaping (Bool) -> ()) {
  613. DispatchQueue.global().async {
  614. var result: Bool = false
  615. if let g = self.group, let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getDeleteChat(chat_id: chatId, f_pin: g.id)), response.isOk() {
  616. result = true
  617. }
  618. completion(result)
  619. }
  620. }
  621. private func changePosition(pin: String, isAdmin: Bool = true, completion: @escaping (Bool) -> ()) {
  622. DispatchQueue.global().async {
  623. var result: Bool = false
  624. if let g = self.group, let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangeGroupMemberPosition(p_group_id: g.id, p_pin: pin, p_position: isAdmin ? "1" : "0")), response.isOk() {
  625. result = true
  626. }
  627. completion(result)
  628. }
  629. }
  630. private func exitGroup(pin: String, completion: @escaping (Bool) -> ()) {
  631. DispatchQueue.global().async {
  632. var result: Bool = false
  633. if let g = self.group, let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getExitGroup(p_group_id: g.id, p_pin: pin)), response.isOk() {
  634. result = true
  635. }
  636. completion(result)
  637. }
  638. }
  639. private func changeOpenGroup(open: String, completion: @escaping (Bool) -> ()) {
  640. DispatchQueue.global().async {
  641. var result: Bool = false
  642. if let g = self.group, let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangeGroupInfo(p_group_id: g.id, p_open: open)), response.isOk() {
  643. result = true
  644. } else {
  645. result = false
  646. }
  647. completion(result)
  648. }
  649. }
  650. private func checkIsFriend(pin: String) -> Bool {
  651. var isFriend = true
  652. Database.shared.database?.inTransaction({ fmdb, rollback in
  653. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select f_pin from BUDDY where f_pin = '\(pin)'"), cursor.next() {
  654. cursor.close()
  655. } else {
  656. isFriend = false
  657. }
  658. })
  659. return isFriend
  660. }
  661. // MARK: - Table view data source
  662. override func numberOfSections(in tableView: UITableView) -> Int {
  663. return sections.count
  664. }
  665. override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  666. guard let g = group else {
  667. return 1
  668. }
  669. switch sections[section] {
  670. case .topic:
  671. return isAdmin ? g.topics.count + 1 : g.topics.count
  672. case .detail:
  673. return 3
  674. case .member:
  675. return isAdmin ? g.members.count + 1 : g.members.count
  676. default:
  677. return 1
  678. }
  679. }
  680. override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
  681. switch sections[section] {
  682. case .description:
  683. return "Description".localized()
  684. case .topic:
  685. return "Topic".localized()
  686. case .detail:
  687. return "Detail".localized()
  688. case .member:
  689. return "Member".localized()
  690. default:
  691. return nil
  692. }
  693. }
  694. override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  695. switch sections[indexPath.section] {
  696. case .profile:
  697. let cell = tableView.dequeueReusableCell(withIdentifier: "profileCell", for: indexPath) as! ProfileCell
  698. cell.cover.image = UIImage(named: "Sofa", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)
  699. guard let g = group else {
  700. return cell
  701. }
  702. if let image = tempImage {
  703. cell.profile.image = image
  704. } else {
  705. getImage(name: g.profile, placeholderImage: UIImage(systemName: "person.2.circle.fill"), tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in
  706. cell.profile.image = image
  707. }
  708. }
  709. return cell
  710. case .description:
  711. let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
  712. cell.accessoryView = nil
  713. cell.accessoryType = .disclosureIndicator
  714. var content = cell.defaultContentConfiguration()
  715. if let g = group {
  716. content.text = g.quote.isEmpty ? "No description".localized() : g.quote
  717. }
  718. cell.contentConfiguration = content
  719. cell.selectionStyle = .default
  720. return cell
  721. case .access:
  722. let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
  723. var content = cell.defaultContentConfiguration()
  724. if let g = group {
  725. if g.isOpen.isEmpty || g.isOpen == "0" {
  726. content.text = "Private".localized()
  727. content.secondaryText = "Only members can be access this group".localized()
  728. } else if g.isOpen == "1" {
  729. content.text = "Public".localized()
  730. content.secondaryText = "All user can be access this group".localized()
  731. }
  732. if isAdmin && group?.official != "1" {
  733. let changeOpen = UISwitch()
  734. changeOpen.isUserInteractionEnabled = false
  735. if g.isOpen == "1" {
  736. changeOpen.setOn(true, animated: true)
  737. } else {
  738. changeOpen.setOn(false, animated: true)
  739. }
  740. cell.accessoryView = changeOpen
  741. }
  742. }
  743. content.textProperties.color = .mainColor
  744. cell.contentConfiguration = content
  745. cell.accessoryType = .none
  746. return cell
  747. case .topic:
  748. let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
  749. cell.accessoryView = nil
  750. cell.accessoryType = .none
  751. var content = cell.defaultContentConfiguration()
  752. if let g = group {
  753. if indexPath.row == 0, isAdmin {
  754. content.image = UIImage(systemName: "plus.circle")
  755. content.imageProperties.tintColor = .mainColor
  756. content.text = "Add Topic".localized()
  757. cell.accessoryType = .disclosureIndicator
  758. cell.selectionStyle = .default
  759. } else {
  760. let topic = g.topics[isAdmin ? indexPath.row - 1 : indexPath.row]
  761. getImage(name: topic.thumb, placeholderImage: UIImage(systemName: "message.fill"), isCircle: true, tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in
  762. content.image = image
  763. if !result {
  764. content.imageProperties.tintColor = .mainColor
  765. }
  766. }
  767. content.text = topic.title
  768. content.secondaryText = topic.description
  769. cell.selectionStyle = isAdmin ? .default : .none
  770. }
  771. }
  772. cell.contentConfiguration = content
  773. return cell
  774. case .detail:
  775. let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
  776. cell.accessoryView = nil
  777. cell.accessoryType = .none
  778. cell.selectionStyle = .none
  779. var content = cell.defaultContentConfiguration()
  780. content.prefersSideBySideTextAndSecondaryText = true
  781. if let g = group {
  782. switch indexPath.row {
  783. case 1:
  784. content.text = "Created date".localized()
  785. content.secondaryText = Date(milliseconds: Int64(g.date)!).format(dateFormat: "dd, MMM yyyy")
  786. case 2:
  787. content.text = "Members".localized()
  788. content.secondaryText = String(g.members.count)
  789. default:
  790. content.text = "Created by".localized()
  791. Database.shared.database?.inTransaction({ fmdb, rollback in
  792. if let cursor = Database.shared.getRecords(fmdb: fmdb, query: "select first_name || ' ' || ifnull(last_name, '') from BUDDY where f_pin = '\(g.by)'") {
  793. if cursor.next() {
  794. content.secondaryText = cursor.string(forColumnIndex: 0) ?? "Unknown".localized()
  795. }
  796. cursor.close()
  797. }
  798. })
  799. }
  800. }
  801. cell.contentConfiguration = content
  802. return cell
  803. case .member:
  804. let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
  805. cell.selectionStyle = isAdmin ? .default : .none
  806. cell.accessoryView = nil
  807. var content = cell.defaultContentConfiguration()
  808. content.prefersSideBySideTextAndSecondaryText = true
  809. if let g = group {
  810. if indexPath.row == 0, isAdmin {
  811. content.image = UIImage(systemName: "plus.circle")
  812. content.imageProperties.tintColor = .mainColor
  813. content.text = "Add Member".localized()
  814. cell.accessoryType = .disclosureIndicator
  815. } else {
  816. let member = g.members[isAdmin ? indexPath.row - 1 : indexPath.row]
  817. content.imageProperties.maximumSize = CGSize(width: 20, height: 20)
  818. getImage(name: member.thumb, placeholderImage: UIImage(systemName: "person.fill"), isCircle: true, tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in
  819. content.image = image
  820. if !result {
  821. content.imageProperties.tintColor = .mainColor
  822. }
  823. }
  824. if member.userType == "23" || member.official == "1" {
  825. content.attributedText = self.set(image: UIImage(named: "ic_internal", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " " + (member.firstName + " " + member.lastName).trimmingCharacters(in: .whitespaces), size: 15, y: 0)
  826. } else if member.userType == "24" {
  827. content.attributedText = self.set(image: UIImage(named: "pb_call_center", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: " " + (member.firstName + " " + member.lastName).trimmingCharacters(in: .whitespaces), size: 15, y: 0)
  828. } else {
  829. content.text = (member.firstName + " " + member.lastName).trimmingCharacters(in: .whitespaces)
  830. }
  831. if !checkIsFriend(pin: member.pin) {
  832. if member.position == "1" {
  833. content.secondaryAttributedText = self.set(image: UIImage(named: "pb_twsn_group_admin_11", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, image2: UIImage(named: "pb_add_contact", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "", size: 20, y: 0, moreImage: true)
  834. } else {
  835. content.secondaryAttributedText = self.set(image: UIImage(named: "pb_add_contact", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "", size: 20, y: 0)
  836. }
  837. } else {
  838. content.secondaryAttributedText = member.position == "1" ? self.set(image: UIImage(named: "pb_twsn_group_admin_11", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!, with: "", size: 20, y: 0) : NSAttributedString(string: "")
  839. }
  840. cell.accessoryType = .none
  841. }
  842. }
  843. cell.contentConfiguration = content
  844. return cell
  845. case .exit:
  846. let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
  847. if let g = group {
  848. let idMe = UserDefaults.standard.string(forKey: "me") as String?
  849. let admins = g.members.filter { member in
  850. return member.position == "1"
  851. }
  852. var isDeleted = false
  853. if admins.count == 1 {
  854. if admins.first?.pin == idMe {
  855. isDeleted = true
  856. }
  857. }
  858. cell.accessoryView = nil
  859. cell.accessoryType = .none
  860. var content = cell.defaultContentConfiguration()
  861. content.text = isDeleted ? "Delete Group".localized() : "Exit Group".localized()
  862. content.textProperties.color = .red
  863. cell.contentConfiguration = content
  864. cell.selectionStyle = .default
  865. return cell
  866. }
  867. return cell
  868. }
  869. }
  870. override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  871. switch sections[indexPath.section] {
  872. case .profile:
  873. return 200
  874. default:
  875. return UITableView.automaticDimension
  876. }
  877. }
  878. }
  879. // MARK: - Cell
  880. class ProfileCell: UITableViewCell {
  881. @IBOutlet weak var cover: UIImageView!
  882. @IBOutlet weak var profile: UIImageView!
  883. override func layoutSubviews() {
  884. super.layoutSubviews()
  885. profile.circle()
  886. }
  887. }
  888. // MARK: - Extension
  889. extension GroupDetailViewController: ImageVideoPickerDelegate {
  890. func didSelect(imagevideo: Any?) {
  891. if let info = imagevideo as? [UIImagePickerController.InfoKey: Any], let cell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? ProfileCell, let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
  892. if !CheckConnection.isConnectedToNetwork() || API.nGetCLXConnState() == 0 {
  893. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  894. imageView.tintColor = .white
  895. 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)
  896. banner.show()
  897. return
  898. }
  899. guard let g = group else {
  900. return
  901. }
  902. DispatchQueue.global().async {
  903. let resize = image.resize(target: CGSize(width: 800, height: 600))
  904. let documentDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
  905. let fileDir = documentDir.appendingPathComponent("THUMB_\(g.id)\(Date().currentTimeMillis().toHex())")
  906. if !FileManager.default.fileExists(atPath: fileDir.path), let data = resize.jpegData(compressionQuality: 0.8) {
  907. try! data.write(to: fileDir)
  908. DispatchQueue.main.async {
  909. Nexilis.showLoader()
  910. }
  911. Network().upload(name: fileDir.lastPathComponent) { result, progress in
  912. guard result, progress == 100 else {
  913. return
  914. }
  915. if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.getChangeGroupInfo(p_group_id: g.id, p_thumb_id: fileDir.lastPathComponent)), response.isOk() {
  916. Database.shared.database?.inTransaction({ fmdb, rollback in
  917. _ = Database.shared.updateRecord(fmdb: fmdb, table: "GROUPZ", cvalues: ["image_id": fileDir.lastPathComponent], _where: "group_id = '\(g.id)'")
  918. DispatchQueue.main.async {
  919. Nexilis.hideLoader(completion: {
  920. self.tempImage = image
  921. cell.profile.image = self.tempImage
  922. })
  923. }
  924. })
  925. } else {
  926. DispatchQueue.main.async {
  927. let imageView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
  928. imageView.tintColor = .white
  929. let banner = FloatingNotificationBanner(title: "Unable to access servers".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: .top)
  930. banner.show()
  931. }
  932. }
  933. }
  934. }
  935. }
  936. }
  937. }
  938. func set(image: UIImage, image2: UIImage = UIImage(), with text: String, size: CGFloat, y: CGFloat, moreImage: Bool = false) -> NSAttributedString {
  939. let attachment = NSTextAttachment()
  940. let attachment2 = NSTextAttachment()
  941. attachment.image = image
  942. attachment.bounds = CGRect(x: 0, y: y, width: size, height: size)
  943. attachment2.image = image2
  944. attachment2.bounds = CGRect(x: 0, y: y, width: size, height: size)
  945. let attachmentStr = NSAttributedString(attachment: attachment)
  946. let attachmentStr2 = NSAttributedString(attachment: attachment2)
  947. let mutableAttributedString = NSMutableAttributedString()
  948. if moreImage {
  949. mutableAttributedString.append(attachmentStr2)
  950. }
  951. mutableAttributedString.append(attachmentStr)
  952. let textString = NSAttributedString(string: text)
  953. mutableAttributedString.append(textString)
  954. return mutableAttributedString
  955. }
  956. }