CreateRoomViewController.swift 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. //
  2. // TUIRoomViewController.swift
  3. // TUIRoom
  4. //
  5. // Created by WesleyLei on 2021/12/16.
  6. // Copyright © 2021 Tencent. All rights reserved.
  7. //
  8. import SnapKit
  9. import UIKit
  10. import RTCRoomEngine
  11. import TUIRoomKit
  12. import TUICore
  13. class CreateRoomViewController: UIViewController {
  14. weak var rootView: CreateRoomView?
  15. private(set) var inputViewItems: [ListCellItemData] = []
  16. private(set) var switchViewItems: [ListCellItemData] = []
  17. private(set) var isSeatEnable: Bool = false
  18. private let currentUserName: String = TUILogin.getNickName() ?? ""
  19. private let currentUserId: String = TUILogin.getUserID() ?? ""
  20. private let roomInfo: TUIRoomInfo = TUIRoomInfo()
  21. private var enableLocalAudio: Bool = true
  22. private var enableLocalVideo: Bool = true
  23. private var isSoundOnSpeaker: Bool = true
  24. let roomHashNumber: Int = 0x3B9AC9FF
  25. var roomId: String?
  26. let backButton: UIButton = {
  27. let button = UIButton(type: .custom)
  28. let normalIcon = UIImage(named: "room_back_white")
  29. button.setImage(normalIcon, for: .normal)
  30. button.setTitleColor(UIColor(0xD1D9EC), for: .normal)
  31. return button
  32. }()
  33. override var shouldAutorotate: Bool {
  34. return false
  35. }
  36. override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
  37. return .portrait
  38. }
  39. init() {
  40. super.init(nibName: nil, bundle: nil)
  41. createItems()
  42. backButton.addTarget(self, action: #selector(backButtonClick(sender:)), for: .touchUpInside)
  43. }
  44. required init?(coder: NSCoder) {
  45. fatalError("init(coder:) has not been implemented")
  46. }
  47. override func loadView() {
  48. let rootView = CreateRoomView()
  49. rootView.rootViewController = self
  50. view = rootView
  51. self.rootView = rootView
  52. }
  53. override func viewDidLoad() {
  54. super.viewDidLoad()
  55. ConferenceSession.sharedInstance.addObserver(observer: self)
  56. }
  57. override func viewWillAppear(_ animated: Bool) {
  58. super.viewWillAppear(animated)
  59. navigationController?.setNavigationBarHidden(false, animated: false)
  60. navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
  61. UIApplication.shared.isIdleTimerDisabled = false
  62. setupRoomId()
  63. }
  64. @objc
  65. func backButtonClick(sender: UIButton) {
  66. navigationController?.popViewController(animated: true)
  67. }
  68. deinit {
  69. ConferenceSession.sharedInstance.removeObserver(observer: self)
  70. debugPrint("deinit \(self)")
  71. }
  72. }
  73. extension CreateRoomViewController {
  74. private func createItems() {
  75. let roomTypeItem = ListCellItemData()
  76. roomTypeItem.titleText = .roomTypeText
  77. roomTypeItem.messageText = .freedomSpeakText
  78. roomTypeItem.hasOverAllAction = true
  79. roomTypeItem.hasButton = true
  80. roomTypeItem.action = { [weak self] sender in
  81. guard let self = self else { return }
  82. self.switchRoomTypeClick()
  83. }
  84. inputViewItems.append(roomTypeItem)
  85. let userNameItem = ListCellItemData()
  86. userNameItem.titleText = .userNameText
  87. userNameItem.messageText = currentUserName
  88. userNameItem.hasDownLineView = false
  89. inputViewItems.append(userNameItem)
  90. let openMicItem = ListCellItemData()
  91. openMicItem.titleText = .openMicText
  92. openMicItem.hasSwitch = true
  93. openMicItem.isSwitchOn = enableLocalAudio
  94. openMicItem.action = { [weak self] sender in
  95. guard let self = self, let view = sender as? UISwitch else { return }
  96. self.enableLocalAudio = view.isOn
  97. }
  98. switchViewItems.append(openMicItem)
  99. let openSpeakerItem = ListCellItemData()
  100. openSpeakerItem.titleText = .openSpeakerText
  101. openSpeakerItem.hasSwitch = true
  102. openSpeakerItem.isSwitchOn = isSoundOnSpeaker
  103. openSpeakerItem.action = { [weak self] sender in
  104. guard let self = self, let view = sender as? UISwitch else { return }
  105. self.isSoundOnSpeaker = view.isOn
  106. }
  107. switchViewItems.append(openSpeakerItem)
  108. let openCameraItem = ListCellItemData()
  109. openCameraItem.titleText = .openCameraText
  110. openCameraItem.hasSwitch = true
  111. openCameraItem.isSwitchOn = enableLocalVideo
  112. openCameraItem.hasDownLineView = false
  113. openCameraItem.action = { [weak self] sender in
  114. guard let self = self, let view = sender as? UISwitch else { return }
  115. self.enableLocalVideo = view.isOn
  116. }
  117. switchViewItems.append(openCameraItem)
  118. }
  119. func enterButtonClick(sender: UIButton) {
  120. guard let roomId = self.roomId else {
  121. self.view.makeToast(.generatingRoomIdText)
  122. return
  123. }
  124. quickStartConference(roomId: roomId)
  125. }
  126. private func quickStartConference(roomId: String) {
  127. let vc = ConferenceMainViewController()
  128. let params = StartConferenceParams(roomId: roomId)
  129. params.isSeatEnabled = isSeatEnable
  130. params.isOpenMicrophone = enableLocalAudio
  131. params.isOpenCamera = enableLocalVideo
  132. params.isOpenSpeaker = isSoundOnSpeaker
  133. vc.setStartConferenceParams(params: params)
  134. navigationController?.pushViewController(vc, animated: true)
  135. }
  136. func switchRoomTypeClick() {
  137. rootView?.showSpeechModeControlView()
  138. }
  139. func freedomAction(sender: UIButton, view: RoomTypeView) {
  140. sender.isSelected = !sender.isSelected
  141. view.raiseHandButton.isSelected = false
  142. isSeatEnable = false
  143. view.isHidden = true
  144. guard let itemData = inputViewItems.first(where: { $0.titleText == .roomTypeText }) else { return }
  145. itemData.messageText = isSeatEnable ? .raiseHandSpeakText : .freedomSpeakText
  146. rootView?.updateInputStackView(item: itemData, index: 0)
  147. }
  148. func raiseHandAction(sender: UIButton, view: RoomTypeView) {
  149. sender.isSelected = !sender.isSelected
  150. view.freedomButton.isSelected = false
  151. isSeatEnable = true
  152. view.isHidden = true
  153. guard let itemData = inputViewItems.first(where: { $0.titleText == .roomTypeText }) else { return }
  154. itemData.messageText = isSeatEnable ? .raiseHandSpeakText : .freedomSpeakText
  155. rootView?.updateInputStackView(item: itemData, index: 0)
  156. }
  157. private func setupRoomId() {
  158. let roomId = getRandomRoomId(numberOfDigits: 6)
  159. checkIfRoomIdExists(roomId: roomId) { [weak self] in
  160. guard let self = self else { return }
  161. self.setupRoomId()
  162. } onNotExist: { [weak self] in
  163. guard let self = self else { return }
  164. self.roomId = roomId
  165. }
  166. }
  167. private func getRandomRoomId(numberOfDigits: Int) -> String {
  168. var numberOfDigit = numberOfDigits > 0 ? numberOfDigits : 1
  169. numberOfDigit = numberOfDigit < 10 ? numberOfDigit : 9
  170. let minNumber = Int(truncating: NSDecimalNumber(decimal: pow(10, numberOfDigit - 1)))
  171. let maxNumber = Int(truncating: NSDecimalNumber(decimal: pow(10, numberOfDigit))) - 1
  172. let randomNumber = arc4random_uniform(UInt32(maxNumber - minNumber)) + UInt32(minNumber)
  173. return String(randomNumber)
  174. }
  175. private func checkIfRoomIdExists(roomId: String, onExist: @escaping () -> (), onNotExist: @escaping () -> ()) {
  176. V2TIMManager.sharedInstance().getGroupsInfo([roomId]) { infoResult in
  177. if infoResult?.first?.resultCode == 0 {
  178. onExist()
  179. } else {
  180. onNotExist()
  181. }
  182. } fail: { code, message in
  183. onNotExist()
  184. }
  185. }
  186. }
  187. extension CreateRoomViewController: ConferenceObserver {
  188. func onConferenceStarted(roomInfo: TUIRoomInfo, error: TUIError, message: String) {
  189. guard error != .success else { return }
  190. navigationController?.popViewController(animated: true)
  191. guard !message.isEmpty else { return }
  192. SceneDelegate.getCurrentWindow()?.makeToast(message, duration: 1, position:TUICSToastPositionCenter)
  193. }
  194. func onConferenceFinished(roomInfo: TUIRoomInfo, reason: ConferenceFinishedReason) {
  195. debugPrint("onConferenceFinished")
  196. }
  197. func onConferenceExited(roomInfo: TUIRoomInfo, reason: ConferenceExitedReason) {
  198. debugPrint("onConferenceExited")
  199. }
  200. }
  201. private extension String {
  202. static var userNameText: String {
  203. RoomDemoLocalize("Your Name")
  204. }
  205. static var roomTypeText: String {
  206. RoomDemoLocalize("Conference Type")
  207. }
  208. static var openCameraText: String {
  209. RoomDemoLocalize("Video")
  210. }
  211. static var openMicText: String {
  212. RoomDemoLocalize("Mic")
  213. }
  214. static var openSpeakerText: String {
  215. RoomDemoLocalize("Speaker")
  216. }
  217. static var freedomSpeakText: String {
  218. RoomDemoLocalize("Free Speech Conference")
  219. }
  220. static var raiseHandSpeakText: String {
  221. RoomDemoLocalize("On-stage Speech Conference")
  222. }
  223. static var generatingRoomIdText: String {
  224. RoomDemoLocalize("Generating room number, please try again later")
  225. }
  226. func truncateUtf8String(maxByteLength: Int) -> String {
  227. let length = self.utf8.count
  228. if length <= maxByteLength {
  229. return self
  230. } else {
  231. var byteLen = 0
  232. var result = ""
  233. for c in self {
  234. byteLen += String(c).utf8.count
  235. if byteLen > maxByteLength {
  236. break
  237. }
  238. result.append(c)
  239. }
  240. return result
  241. }
  242. }
  243. }