RoomStore.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. //
  2. // RoomStore.swift
  3. // TUIRoomKit
  4. //
  5. // Created by aby on 2022/12/28.
  6. // Copyright © 2022 Tencent. All rights reserved.
  7. //
  8. import Foundation
  9. import TUICore
  10. import RTCRoomEngine
  11. import Factory
  12. let roomHashNumber: Int = 0x3B9AC9FF
  13. class RoomStore: NSObject {
  14. var currentUser: UserEntity = UserEntity()
  15. var roomInfo: TUIRoomInfo = TUIRoomInfo()
  16. var videoSetting: VideoModel = VideoModel()
  17. var audioSetting: AudioModel = AudioModel()
  18. @Published var attendeeList: [UserEntity] = [] // User list
  19. @Published var seatList: [UserEntity] = [] // List of users who have taken the stage
  20. var offSeatList: [UserEntity] = [] // List of users who not on stage
  21. var inviteSeatList: [RequestEntity] = [] // List of users who apply to be on stage
  22. var isEnteredRoom: Bool = false
  23. var timeStampOnEnterRoom: Int = 0 // Timestamp of entering the meeting
  24. var isImAccess: Bool = false // Whether TUIRoomKit is entered by IM
  25. var selfTakeSeatRequestId: String? // Self ID for applying on stage
  26. var shouldShowFloatChatView = true
  27. private let openCameraKey = "isOpenCamera"
  28. private let openMicrophoneKey = "isOpenMicrophone"
  29. private let shownRaiseHandNoticeKey = "isShownRaiseHandNotice"
  30. weak var conferenceObserver: ConferenceObserver?
  31. @WeakLazyInjected(\.conferenceStore) private var operation
  32. var isOpenMicrophone: Bool {
  33. didSet {
  34. UserDefaults.standard.set(isOpenMicrophone, forKey: openMicrophoneKey)
  35. UserDefaults.standard.synchronize()
  36. }
  37. }
  38. var isOpenCamera: Bool {
  39. didSet {
  40. UserDefaults.standard.set(isOpenCamera, forKey: openCameraKey)
  41. UserDefaults.standard.synchronize()
  42. }
  43. }
  44. var isShownRaiseHandNotice: Bool {
  45. didSet {
  46. UserDefaults.standard.set(isShownRaiseHandNotice, forKey: shownRaiseHandNoticeKey)
  47. UserDefaults.standard.synchronize()
  48. }
  49. }
  50. override init() {
  51. if let isOpenMicrophoneValue = UserDefaults.standard.object(forKey: openMicrophoneKey) as? Bool {
  52. isOpenMicrophone = isOpenMicrophoneValue
  53. } else {
  54. isOpenMicrophone = true
  55. }
  56. if let isOpenCameraValue = UserDefaults.standard.object(forKey: openCameraKey) as? Bool {
  57. isOpenCamera = isOpenCameraValue
  58. } else {
  59. isOpenCamera = true
  60. }
  61. if let isShownRaiseHandNoticeValue = UserDefaults.standard.object(forKey: shownRaiseHandNoticeKey) as? Bool {
  62. isShownRaiseHandNotice = isShownRaiseHandNoticeValue
  63. } else {
  64. isShownRaiseHandNotice = true
  65. }
  66. }
  67. func initialRoomInfo(_ roomInfo: TUIRoomInfo) {
  68. self.roomInfo = roomInfo
  69. EngineEventCenter.shared.notifyEngineEvent(event: .onInitialRoomInfo, param: ["roomInfo": roomInfo])
  70. }
  71. func initalEnterRoomMessage() {
  72. isEnteredRoom = true
  73. timeStampOnEnterRoom = Int(Date().timeIntervalSince1970)
  74. }
  75. func initialRoomCurrentUser() {
  76. currentUser.userId = TUILogin.getUserID() ?? ""
  77. currentUser.userName = TUILogin.getNickName() ?? ""
  78. EngineManager.shared.getUserInfo(currentUser.userId) { [weak self] userInfo in
  79. guard let self = self else { return }
  80. guard let userInfo = userInfo else { return }
  81. self.currentUser.update(userInfo: userInfo)
  82. EngineEventCenter.shared.notifyEngineEvent(event: .onInitialSelfUserInfo, param: [:])
  83. self.operation?.dispatch(action: UserActions.updateSelfInfo(payload: UserInfo(userInfo: userInfo)))
  84. } onError: { code, message in
  85. debugPrint("getUserInfo,code:\(code),message:\(message)")
  86. }
  87. }
  88. func initialSeatList(seatList: [TUISeatInfo]) {
  89. var localSeatList = [UserEntity]()
  90. for seatInfo in seatList {
  91. guard let userId = seatInfo.userId, userId != "" else { continue }
  92. guard let userModel = getUserItem(userId) else { continue }
  93. userModel.isOnSeat = true
  94. localSeatList.append(userModel)
  95. }
  96. self.seatList = localSeatList
  97. if seatList.contains(where: { $0.userId == currentUser.userId }) {
  98. updateSelfOnSeatState(isOnSeat: true)
  99. }
  100. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewSeatList, param: [:])
  101. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewVideoSeatView, param: [:])
  102. }
  103. func initialOffSeatList() {
  104. offSeatList = attendeeList.filter({ !$0.isOnSeat })
  105. }
  106. func updateSelfOnSeatState(isOnSeat: Bool) {
  107. currentUser.isOnSeat = isOnSeat
  108. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_UserOnSeatChanged, param: ["isOnSeat": isOnSeat])
  109. }
  110. func updateUserDisableSendingMessage(userId: String, isDisable: Bool) {
  111. if userId == currentUser.userId {
  112. currentUser.disableSendingMessage = isDisable
  113. }
  114. guard let userItem = getUserItem(userId) else { return }
  115. userItem.disableSendingMessage = isDisable
  116. guard let operation = operation else { return }
  117. var disableMessageUsers = operation.selectCurrent(UserSelectors.getDisableMessageUsers)
  118. if isDisable {
  119. disableMessageUsers.insert(userId)
  120. } else {
  121. disableMessageUsers.remove(userId)
  122. }
  123. operation.dispatch(action: UserActions.updateDisableMessageUsers(payload: disableMessageUsers))
  124. }
  125. func deleteTakeSeatRequest(requestId: String) {
  126. let requestUserId = inviteSeatList.first(where: { $0.requestId == requestId })?.userId
  127. inviteSeatList = inviteSeatList.filter { requestItem in
  128. requestItem.requestId != requestId
  129. }
  130. EngineEventCenter.shared.notifyEngineEvent(event: .onDeletedTakeSeatRequest, param: ["userId": requestUserId ?? ""])
  131. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewSeatList, param: [:])
  132. }
  133. func deleteInviteSeatUser(_ userId: String) {
  134. inviteSeatList = inviteSeatList.filter { requestItem in
  135. requestItem.userId != userId
  136. }
  137. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewSeatList, param: [:])
  138. }
  139. func addInviteSeatUser(request: TUIRequest) {
  140. guard !inviteSeatList.contains(where: { $0.userId == request.userId }) else { return }
  141. let requestEntity = RequestEntity(requestId: request.requestId, userId: request.userId)
  142. inviteSeatList.append(requestEntity)
  143. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewSeatList, param: [:])
  144. }
  145. func setCameraOpened(_ isCameraOpened: Bool) {
  146. videoSetting.isCameraOpened = isCameraOpened
  147. }
  148. func setSoundOnSpeaker(_ isSoundOnSpeaker: Bool) {
  149. audioSetting.isSoundOnSpeaker = isSoundOnSpeaker
  150. }
  151. func setConferenceObserver(_ observer: ConferenceObserver?) {
  152. conferenceObserver = observer
  153. }
  154. func setInviteSeatList(list: [TUIRequest]) {
  155. inviteSeatList = []
  156. for request in list {
  157. let requestEntity = RequestEntity(requestId: request.requestId, userId: request.userId)
  158. inviteSeatList.append(requestEntity)
  159. }
  160. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewSeatList, param: [:])
  161. }
  162. func updateLeftSeatList(leftList: [TUISeatInfo]) {
  163. guard leftList.count > 0 else { return }
  164. if leftList.contains(where: { $0.userId == currentUser.userId }) {
  165. currentUser.isOnSeat = false
  166. audioSetting.isMicOpened = false
  167. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_UserOnSeatChanged,
  168. param: ["isOnSeat":false])
  169. }
  170. for seatInfo: TUISeatInfo in leftList {
  171. guard let userId = seatInfo.userId else { continue }
  172. if let userItem = attendeeList.first(where: { $0.userId == userId }) {
  173. userItem.isOnSeat = false
  174. addOffSeatItem(userItem)
  175. }
  176. deleteOnSeatItem(userId)
  177. }
  178. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewSeatList, param: [:])
  179. }
  180. func updateSeatedList(seatList: [TUISeatInfo]) {
  181. guard seatList.count > 0 else { return }
  182. if seatList.contains(where: { $0.userId == currentUser.userId }) {
  183. currentUser.isOnSeat = true
  184. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_UserOnSeatChanged,
  185. param: ["isOnSeat":true])
  186. }
  187. for seatInfo: TUISeatInfo in seatList {
  188. guard let userId = seatInfo.userId else { continue }
  189. guard let userInfo = attendeeList.first(where: { $0.userId == userId }) else { continue }
  190. userInfo.isOnSeat = true
  191. addOnSeatItem(userInfo)
  192. deleteOffSeatItem(userId)
  193. }
  194. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewSeatList, param: [:])
  195. }
  196. func remoteUserEnterRoom(userInfo: TUIUserInfo) {
  197. let userItem = UserEntity()
  198. userItem.update(userInfo: userInfo)
  199. addUserItem(userItem)
  200. if roomInfo.isSeatEnabled, !userItem.isOnSeat {
  201. addOffSeatItem(userItem)
  202. }
  203. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewUserList, param: [:])
  204. }
  205. func remoteUserLeaveRoom(userInfo: TUIUserInfo) {
  206. deleteUserItem(userInfo.userId)
  207. deleteOffSeatItem(userInfo.userId)
  208. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewUserList, param: [:])
  209. }
  210. func updateFloatChatShowState(shouldShow: Bool) {
  211. shouldShowFloatChatView = shouldShow
  212. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_ShowFloatChatView, param: ["shouldShow": shouldShow])
  213. }
  214. func changeUserName(userId: String, userName: String) {
  215. if currentUser.userId == userId {
  216. currentUser.userName = userName
  217. }
  218. if let userItem = getUserItem(userId) {
  219. userItem.userName = userName
  220. }
  221. if let seatItem = seatList.first(where: { $0.userId == userId }) {
  222. seatItem.userName = userName
  223. } else if let offseatItem = offSeatList.first(where: { $0.userId == userId }) {
  224. offseatItem.userName = userName
  225. }
  226. if let inviteSeatItem = inviteSeatList.first(where: { $0.userId == userId }) {
  227. inviteSeatItem.userName = userName
  228. }
  229. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewUserList, param: [:])
  230. EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewSeatList, param: [:])
  231. }
  232. func reset() {
  233. currentUser = UserEntity()
  234. roomInfo = TUIRoomInfo()
  235. videoSetting = VideoModel()
  236. audioSetting = AudioModel()
  237. attendeeList = []
  238. seatList = []
  239. offSeatList = []
  240. inviteSeatList = []
  241. isEnteredRoom = false
  242. timeStampOnEnterRoom = 0
  243. isImAccess = false
  244. selfTakeSeatRequestId = nil
  245. shouldShowFloatChatView = true
  246. conferenceObserver = nil
  247. }
  248. deinit {
  249. debugPrint("self:\(self),deinit")
  250. }
  251. }
  252. extension RoomStore {
  253. private func getUserItem(_ userId: String) -> UserEntity? {
  254. return attendeeList.first(where: {$0.userId == userId})
  255. }
  256. private func addUserItem(_ userItem: UserEntity) {
  257. guard getUserItem(userItem.userId) == nil else { return }
  258. if userItem.userName.isEmpty {
  259. userItem.userName = userItem.userId
  260. }
  261. attendeeList.append(userItem)
  262. }
  263. private func deleteUserItem(_ userId: String) {
  264. attendeeList.removeAll(where: { $0.userId == userId })
  265. }
  266. private func addOnSeatItem(_ userItem: UserEntity) {
  267. guard !seatList.contains(where: { $0.userId == userItem.userId }) else { return }
  268. seatList.append(userItem)
  269. }
  270. private func deleteOnSeatItem(_ userId: String) {
  271. seatList.removeAll(where: { $0.userId == userId })
  272. }
  273. private func addOffSeatItem(_ userItem: UserEntity) {
  274. guard !offSeatList.contains(where: { $0.userId == userItem.userId }) else { return }
  275. offSeatList.append(userItem)
  276. }
  277. private func deleteOffSeatItem(_ userId: String) {
  278. offSeatList.removeAll(where: { $0.userId == userId })
  279. }
  280. }