WhiteboardViewController.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. //
  2. // WhiteboardViewController.swift
  3. // NexilisLite
  4. //
  5. // Created by Kevin Maulana on 31/03/22.
  6. //
  7. // Rn
  8. // onalphachanged
  9. import UIKit
  10. class WhiteboardViewController: UIViewController, WhiteboardDelegate {
  11. func draw(x: String, y: String, w: String, h: String, fc: String, sw: String, xo: String, yo: String, data: String) {
  12. wb!.draw(x: x, y: y, w: w, h: h, fc: fc, sw: sw, xo: xo, yo: yo, data: data)
  13. }
  14. @objc func clear(){
  15. wb?.clear()
  16. }
  17. var wbc : WhiteboardCanvas?
  18. var wbcConstraintTop = NSLayoutConstraint()
  19. var wbcConstraintBottom = NSLayoutConstraint()
  20. var wbcConstraintLeft = NSLayoutConstraint()
  21. var wbcConstraintRight = NSLayoutConstraint()
  22. var wb : Whiteboard?
  23. var roomId = ""
  24. var destinations = [String]()
  25. var incoming = false
  26. var fromContact: Int?
  27. let myImage = UIImageView()
  28. let name = UILabel()
  29. let profileImage = UIImageView()
  30. let labelIncomingOutgoing = UILabel()
  31. var user: User?
  32. let buttonDecline = UIButton()
  33. let buttonAccept = UIButton()
  34. var constraintLeadingButtonDecline = NSLayoutConstraint()
  35. var constraintBottomButtonDecline = NSLayoutConstraint()
  36. required init?(coder: NSCoder) {
  37. super.init(coder: coder)
  38. wb = Whiteboard(delegated: true)
  39. }
  40. override func viewDidLoad() {
  41. super.viewDidLoad()
  42. if fromContact != nil {
  43. addBackgroundIncoming()
  44. addProfileNameCalling()
  45. Calling()
  46. addToolbar()
  47. } else {
  48. initWhiteboard()
  49. }
  50. self.title = "Whiteboard".localized()
  51. let center: NotificationCenter = NotificationCenter.default
  52. center.addObserver(self, selector: #selector(wbSession(notification:)), name: NSNotification.Name(rawValue: "wbSession"), object: nil)
  53. // navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close".localized(), style: .plain, target: self, action: #selector(close))
  54. // navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Clear".localized(), style: .plain,target: self, action: #selector(clear))
  55. // Do any additional setup after loading the view.
  56. }
  57. func addBackgroundIncoming() {
  58. view.addSubview(myImage)
  59. myImage.translatesAutoresizingMaskIntoConstraints = false
  60. NSLayoutConstraint.activate([
  61. myImage.topAnchor.constraint(equalTo: view.topAnchor),
  62. myImage.bottomAnchor.constraint(equalTo: view.bottomAnchor),
  63. myImage.leadingAnchor.constraint(equalTo: view.leadingAnchor),
  64. myImage.trailingAnchor.constraint(equalTo: view.trailingAnchor),
  65. ])
  66. myImage.backgroundColor = .lightGray
  67. myImage.tintColor = .secondaryColor
  68. let image = user!.thumb
  69. if image.isEmpty {
  70. myImage.image = UIImage(systemName: "person")
  71. myImage.contentMode = .scaleAspectFit
  72. } else {
  73. myImage.setImage(name: image)
  74. myImage.contentMode = .scaleAspectFill
  75. }
  76. }
  77. func addProfileNameCalling() {
  78. view.addSubview(profileImage)
  79. profileImage.translatesAutoresizingMaskIntoConstraints = false
  80. profileImage.frame.size = CGSize(width: 60.0, height: 60.0)
  81. NSLayoutConstraint.activate([
  82. profileImage.topAnchor.constraint(equalTo: view.topAnchor, constant: 40.0),
  83. profileImage.centerXAnchor.constraint(equalTo: view.centerXAnchor),
  84. profileImage.widthAnchor.constraint(equalToConstant: 60.0),
  85. profileImage.heightAnchor.constraint(equalToConstant: 63.0)
  86. ])
  87. profileImage.backgroundColor = .lightGray
  88. profileImage.tintColor = .secondaryColor
  89. profileImage.circle()
  90. let image = user!.thumb
  91. if image.isEmpty {
  92. profileImage.image = UIImage(systemName: "person")
  93. profileImage.contentMode = .scaleAspectFit
  94. profileImage.layer.borderWidth = 1
  95. profileImage.layer.borderColor = UIColor.secondaryColor.cgColor
  96. } else {
  97. profileImage.setImage(name: image)
  98. profileImage.contentMode = .scaleAspectFill
  99. }
  100. view.addSubview(name)
  101. name.translatesAutoresizingMaskIntoConstraints = false
  102. NSLayoutConstraint.activate([
  103. name.topAnchor.constraint(equalTo: profileImage.bottomAnchor, constant: 5.0),
  104. name.centerXAnchor.constraint(equalTo: view.centerXAnchor)
  105. ])
  106. name.font = UIFont.systemFont(ofSize: 12)
  107. name.backgroundColor = .black.withAlphaComponent(0.05)
  108. name.layer.cornerRadius = 5.0
  109. name.clipsToBounds = true
  110. name.textColor = .mainColor
  111. name.text = user?.fullName.trimmingCharacters(in: .whitespaces)
  112. }
  113. func Calling() {
  114. view.addSubview(labelIncomingOutgoing)
  115. labelIncomingOutgoing.translatesAutoresizingMaskIntoConstraints = false
  116. NSLayoutConstraint.activate([
  117. labelIncomingOutgoing.topAnchor.constraint(equalTo: name.bottomAnchor, constant: 40.0),
  118. labelIncomingOutgoing.centerXAnchor.constraint(equalTo: view.centerXAnchor)
  119. ])
  120. if fromContact == 0 {
  121. labelIncomingOutgoing.text = "Waiting for answer".localized() + "..."
  122. _ = Nexilis.write(message: CoreMessage_TMessageBank.wbCreate(l_pin: user!.pin))
  123. } else {
  124. labelIncomingOutgoing.text = "Incoming Whiteboard".localized() + "..."
  125. }
  126. labelIncomingOutgoing.font = UIFont.systemFont(ofSize: 12)
  127. labelIncomingOutgoing.backgroundColor = .black.withAlphaComponent(0.05)
  128. labelIncomingOutgoing.layer.cornerRadius = 5.0
  129. labelIncomingOutgoing.clipsToBounds = true
  130. labelIncomingOutgoing.textColor = .mainColor
  131. }
  132. func addToolbar() {
  133. view.addSubview(buttonDecline)
  134. buttonDecline.translatesAutoresizingMaskIntoConstraints = false
  135. buttonDecline.frame.size = CGSize(width: 70.0, height: 70.0)
  136. if fromContact == 0 {
  137. constraintLeadingButtonDecline = buttonDecline.centerXAnchor.constraint(equalTo: view.centerXAnchor)
  138. } else {
  139. constraintLeadingButtonDecline = buttonDecline.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: view.frame.width * 0.2)
  140. }
  141. constraintBottomButtonDecline = buttonDecline.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -60.0)
  142. NSLayoutConstraint.activate([
  143. constraintBottomButtonDecline,
  144. constraintLeadingButtonDecline,
  145. buttonDecline.widthAnchor.constraint(equalToConstant: 70.0),
  146. buttonDecline.heightAnchor.constraint(equalToConstant: 70.0)
  147. ])
  148. buttonDecline.backgroundColor = .red
  149. buttonDecline.circle()
  150. buttonDecline.setImage(UIImage(systemName: "xmark", withConfiguration: UIImage.SymbolConfiguration(pointSize: 30, weight: .medium, scale: .default)), for: .normal)
  151. buttonDecline.tintColor = .white
  152. buttonDecline.addTarget(self, action: #selector(didTapDeclineCallButton(sender:)), for: .touchUpInside)
  153. if fromContact == 1 {
  154. view.addSubview(buttonAccept)
  155. buttonAccept.translatesAutoresizingMaskIntoConstraints = false
  156. buttonAccept.frame.size = CGSize(width: 70.0, height: 70.0)
  157. NSLayoutConstraint.activate([
  158. buttonAccept.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -60.0),
  159. buttonAccept.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -(view.frame.width * 0.2)),
  160. buttonAccept.widthAnchor.constraint(equalToConstant: 70.0),
  161. buttonAccept.heightAnchor.constraint(equalToConstant: 70.0)
  162. ])
  163. buttonAccept.backgroundColor = .greenColor
  164. buttonAccept.circle()
  165. buttonAccept.setImage(UIImage(systemName: "checkmark", withConfiguration: UIImage.SymbolConfiguration(pointSize: 30, weight: .medium, scale: .default)), for: .normal)
  166. buttonAccept.tintColor = .white
  167. buttonAccept.addTarget(self, action: #selector(didTapAcceptCallButton), for: .touchUpInside)
  168. }
  169. }
  170. @objc func didTapDeclineCallButton(sender: Any) {
  171. let alert = UIAlertController(title: "End Whiteboard Session".localized(), message: "Are you sure you want to end whiteboard session?".localized(), preferredStyle: .alert)
  172. alert.addAction(UIAlertAction(title: "No".localized(), style: UIAlertAction.Style.default, handler: nil))
  173. alert.addAction(UIAlertAction(title: "Yes".localized(), style: UIAlertAction.Style.default, handler: {(_) in
  174. if self.fromContact == 0 {
  175. _ = Nexilis.write(message: CoreMessage_TMessageBank.wbEnded(l_pin: self.user!.pin))
  176. } else {
  177. _ = Nexilis.write(message: CoreMessage_TMessageBank.wbReject(l_pin: self.user!.pin))
  178. }
  179. self.dismiss(animated: true, completion: nil)
  180. }))
  181. self.present(alert, animated: true, completion: nil)
  182. }
  183. @objc func didTapAcceptCallButton() {
  184. _ = Nexilis.write(message: CoreMessage_TMessageBank.wbAccept(l_pin: user!.pin))
  185. self.myImage.removeFromSuperview()
  186. self.name.removeFromSuperview()
  187. self.profileImage.removeFromSuperview()
  188. self.labelIncomingOutgoing.removeFromSuperview()
  189. self.buttonDecline.removeFromSuperview()
  190. self.buttonAccept.removeFromSuperview()
  191. NSLayoutConstraint.deactivate([
  192. self.constraintLeadingButtonDecline,
  193. self.constraintBottomButtonDecline
  194. ])
  195. self.initWhiteboard()
  196. let tid = CoreMessage_TMessageUtil.getTID()
  197. self.roomId = "\(user!.pin)WB\(tid)"
  198. let idMe = UserDefaults.standard.string(forKey: "me")!
  199. UserDefaults.standard.set("\(user!.pin),\(idMe)", forKey: "wb_vc")
  200. self.sendJoin()
  201. }
  202. @objc func wbSession(notification: NSNotification) {
  203. DispatchQueue.main.async { [self] in
  204. let data:[AnyHashable : Any] = notification.userInfo!
  205. if let message = data["message"] as? TMessage {
  206. let status = message.getBody(key: CoreMessage_TMessageKey.STATUS, default_value: "")
  207. switch (Int(status)) {
  208. case CoreMessage_TMessageCode.WB_ACCEPT_INCOMING:
  209. print("WB_ACCEPT_INCOMING")
  210. let f_pin = message.getBody(key: CoreMessage_TMessageKey.F_USER_ID, default_value: "")
  211. _ = Nexilis.write(message: CoreMessage_TMessageBank.wbOffhook(l_pin: f_pin))
  212. DispatchQueue.main.async {
  213. let l_pin = message.getBody(key: CoreMessage_TMessageKey.L_PIN, default_value: "")
  214. self.myImage.removeFromSuperview()
  215. self.name.removeFromSuperview()
  216. self.profileImage.removeFromSuperview()
  217. self.labelIncomingOutgoing.removeFromSuperview()
  218. self.buttonDecline.removeFromSuperview()
  219. NSLayoutConstraint.deactivate([
  220. self.constraintLeadingButtonDecline,
  221. self.constraintBottomButtonDecline
  222. ])
  223. self.initWhiteboard()
  224. let tid = CoreMessage_TMessageUtil.getTID()
  225. self.roomId = "\(f_pin)WB\(tid)"
  226. self.destinations = [l_pin]
  227. self.sendInit()
  228. }
  229. case CoreMessage_TMessageCode.WB_REJECT_INCOMING,CoreMessage_TMessageCode.WB_END:
  230. print("WB_REJECT_INCOMING \(status)")
  231. if self.labelIncomingOutgoing.isDescendant(of: self.view) {
  232. self.labelIncomingOutgoing.text = "WhiteBoard session is over".localized()
  233. }
  234. if self.buttonDecline.isDescendant(of: self.view) {
  235. self.buttonDecline.removeFromSuperview()
  236. }
  237. DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
  238. self.dismiss(animated: true, completion: nil)
  239. }
  240. case CoreMessage_TMessageCode.WB_OFFHOOK:
  241. print("WB_OFFHOOK")
  242. case CoreMessage_TMessageCode.WB_RINGING:
  243. print("WB_RINGING")
  244. default:
  245. print("default")
  246. }
  247. }
  248. }
  249. }
  250. func initWhiteboard(){
  251. let wbHeight = self.view.frame.width * 20.0 / 9.0
  252. let rect = CGRect(x: 0.0, y: 0.0, width: self.view.frame.width, height: self.view.frame.height)
  253. wbc = WhiteboardCanvas(frame: rect)
  254. // wbc?.translatesAutoresizingMaskIntoConstraints = false
  255. // wbcConstraintTop = (wbc?.topAnchor.constraint(equalTo: self.view.topAnchor))!
  256. // wbcConstraintBottom = (wbc?.bottomAnchor.constraint(equalTo: self.view.bottomAnchor))!
  257. // wbcConstraintRight = (wbc?.rightAnchor.constraint(equalTo: self.view.rightAnchor))!
  258. // wbcConstraintLeft = (wbc?.leftAnchor.constraint(equalTo: self.view.leftAnchor))!
  259. // NSLayoutConstraint.activate([wbcConstraintTop, wbcConstraintBottom, wbcConstraintLeft, wbcConstraintRight])
  260. wb?.canvas = wbc
  261. self.view.addSubview(wbc!)
  262. Nexilis.setWhiteboardDelegate(delegate: self)
  263. }
  264. func sendInit(){
  265. let d = destinations.joined(separator: ",")
  266. // roomId = "\(me)\(tid)"
  267. wb?.setRoomId(roomId: roomId)
  268. wb!.sendInit(destinations: d)
  269. }
  270. func sendJoin(){
  271. wb?.setRoomId(roomId: roomId)
  272. wb!.sendJoin()
  273. }
  274. var close : (() -> Void)?
  275. func terminate(){
  276. wb?.sendTerminate()
  277. Nexilis.setWhiteboardDelegate(delegate: nil)
  278. close?()
  279. }
  280. @IBAction func didTapClose(_ sender: Any) {
  281. if fromContact != nil {
  282. didTapDeclineCallButton(sender: 0)
  283. return
  284. }
  285. close?()
  286. }
  287. @IBAction func didTapClear(_ sender: Any) {
  288. wb?.clear()
  289. wb?.sendClear()
  290. }
  291. @IBAction func onAlphaChanged(_ sender: UISlider) {
  292. let alp = sender.value / 100.0
  293. view.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: CGFloat(alp))
  294. }
  295. /*
  296. // MARK: - Navigation
  297. // In a storyboard-based application, you will often want to do a little preparation before navigation
  298. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  299. // Get the new view controller using segue.destination.
  300. // Pass the selected object to the new view controller.
  301. }
  302. */
  303. }