Files
featherVoice/TUIKit/TUIRoomKit/Source/View/Model/RoomEventDispatcher.swift
2025-08-08 10:49:36 +08:00

283 lines
11 KiB
Swift

//
// RoomEventDispatcher.swift
// TUIRoomKit
//
// Created by janejntang on 2023/8/14.
//
import Foundation
import RTCRoomEngine
class RoomEventDispatcher: NSObject {
var engineManager: EngineManager {
EngineManager.shared
}
var store: RoomStore {
engineManager.store
}
var roomInfo: TUIRoomInfo {
store.roomInfo
}
var currentUser: UserEntity {
store.currentUser
}
deinit {
debugPrint("deinit")
}
}
extension RoomEventDispatcher: TUIRoomObserver {
// MARK: - Room event callback
func onAllUserMicrophoneDisableChanged(roomId: String, isDisable: Bool) {
roomInfo.isMicrophoneDisableForAllUser = isDisable
let param = [
"roomId" : roomId,
"isDisable" : isDisable,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onAllUserMicrophoneDisableChanged, param: param)
}
func onAllUserCameraDisableChanged(roomId: String, isDisable: Bool) {
roomInfo.isCameraDisableForAllUser = isDisable
let param = [
"roomId" : roomId,
"isDisable" : isDisable,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onAllUserCameraDisableChanged, param: param)
}
func onSendMessageForAllUserDisableChanged(roomId: String, isDisable: Bool) {
roomInfo.isMessageDisableForAllUser = isDisable
}
func onRoomDismissed(roomId: String) {
EngineEventCenter.shared.notifyEngineEvent(event: .onRoomDismissed, param: ["roomId" : roomId,])
}
func onKickedOutOfRoom(roomId: String, reason: TUIKickedOutOfRoomReason, message: String) {
let param = [
"roomId" : roomId,
"reason" : reason,
"message" : message,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onKickedOutOfRoom, param: param)
}
func onRoomNameChanged(roomId: String, roomName: String) {
roomInfo.name = roomName
}
// MARK: - User event callback in the room
func onRemoteUserEnterRoom(roomId: String, userInfo: TUIUserInfo) {
store.remoteUserEnterRoom(userInfo: userInfo)
let param = [
"roomId" : roomId,
"userInfo" : userInfo,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onRemoteUserEnterRoom, param: param)
}
func onRemoteUserLeaveRoom(roomId: String, userInfo: TUIUserInfo) {
store.remoteUserLeaveRoom(userInfo: userInfo)
let param = [
"roomId" : roomId,
"userInfo" : userInfo,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onRemoteUserLeaveRoom, param: param)
}
func onUserRoleChanged(userId: String, userRole: TUIRole) {
userRoleChanged(userId: userId, userRole: userRole)
let param = [
"userId" : userId,
"userRole" : userRole,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onUserRoleChanged, param: param)
}
func onUserVideoStateChanged(userId: String, streamType: TUIVideoStreamType, hasVideo: Bool, reason: TUIChangeReason) {
userVideoStateChanged(userId: userId, streamType: streamType, hasVideo: hasVideo, reason: reason)
let param = [
"userId" : userId,
"streamType" : streamType,
"hasVideo" : hasVideo,
"reason" : reason,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onUserVideoStateChanged, param: param)
}
func onUserAudioStateChanged(userId: String, hasAudio: Bool, reason: TUIChangeReason) {
userAudioStateChanged(userId: userId, hasAudio: hasAudio, reason: reason)
let param = [
"userId" : userId,
"hasAudio" : hasAudio,
"reason" : reason,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onUserAudioStateChanged, param: param)
}
func onUserVoiceVolumeChanged(volumeMap: [String : NSNumber]) {
userVoiceVolumeChanged(volumeMap: volumeMap)
EngineEventCenter.shared.notifyEngineEvent(event: .onUserVoiceVolumeChanged, param: volumeMap)
}
func onUserScreenCaptureStopped(reason: Int) {
userScreenCaptureStopped()
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_SomeoneSharing, param: ["userId":currentUser.userId, "hasVideo": false])
}
func onSeatListChanged(seatList: [TUISeatInfo], seated seatedList: [TUISeatInfo], left leftList: [TUISeatInfo]) {
seatListChanged(seatList: seatList,seated: seatedList, left: leftList)
let param = [
"seatList": seatList,
"seated": seatedList,
"left": leftList,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onSeatListChanged, param: param)
}
func OnSendMessageForUserDisableChanged(roomId: String, userId: String, isDisable muted: Bool) {
store.updateUserDisableSendingMessage(userId: userId, isDisable: muted)
let param = [
"roomId": roomId,
"userId": userId,
"muted": muted,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onSendMessageForUserDisableChanged, param: param)
}
// MARK: - Signaling request related callbacks
func onRequestReceived(request: TUIRequest) {
requestReceived(request: request)
EngineEventCenter.shared.notifyEngineEvent(event: .onRequestReceived, param: ["request": request,])
}
func onRequestCancelled(requestId: String, userId: String) {
store.deleteTakeSeatRequest(requestId: requestId)
}
func onRequestProcessed(requestId: String, userId: String) {
store.deleteTakeSeatRequest(requestId: requestId)
}
func onKickedOffSeat(userId: String) {
let param = [
"userId": userId,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onKickedOffSeat, param: param)
}
func onKickedOffLine(message: String) {
kickedOffLine()
let param = [
"message": message,
] as [String : Any]
EngineEventCenter.shared.notifyEngineEvent(event: .onKickedOffLine, param: param)
}
}
extension RoomEventDispatcher {
private func seatListChanged(seatList: [TUISeatInfo], seated: [TUISeatInfo], left leftList: [TUISeatInfo]) {
store.updateLeftSeatList(leftList: leftList)
store.updateSeatedList(seatList: seated)
}
private func userAudioStateChanged(userId: String, hasAudio: Bool, reason: TUIChangeReason) {
if userId == currentUser.userId {
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_CurrentUserHasAudioStream, param: ["hasAudio": hasAudio, "reason": reason])
currentUser.hasAudioStream = hasAudio
}
guard let userModel = store.attendeeList.first(where: { $0.userId == userId }) else { return }
userModel.hasAudioStream = hasAudio
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewUserList, param: [:])
}
private func userVideoStateChanged(userId: String, streamType: TUIVideoStreamType, hasVideo: Bool, reason: TUIChangeReason) {
switch streamType {
case .screenStream:
if userId == currentUser.userId {
currentUser.hasScreenStream = hasVideo
}
guard let userModel = store.attendeeList.first(where: { $0.userId == userId }) else { return }
userModel.hasScreenStream = hasVideo
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_SomeoneSharing, param: ["userId": userId, "hasVideo": hasVideo])
case .cameraStream:
if userId == currentUser.userId {
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_CurrentUserHasVideoStream,
param: ["hasVideo": hasVideo, "reason": reason])
currentUser.hasVideoStream = hasVideo
store.videoSetting.isCameraOpened = hasVideo
}
guard let userModel = store.attendeeList.first(where: { $0.userId == userId }) else { return }
userModel.hasVideoStream = hasVideo
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewUserList, param: [:])
default: break
}
}
private func userRoleChanged(userId: String, userRole: TUIRole) {
let isSelfRoleChanged = userId == currentUser.userId
let isRoomOwnerChanged = userRole == .roomOwner
if let userInfo = store.attendeeList.first(where: { $0.userId == userId }) {
userInfo.userRole = userRole
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewUserList, param: ["userRole": userRole])
}
if isSelfRoleChanged {
store.currentUser.userRole = userRole
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_CurrentUserRoleChanged, param: ["userRole": userRole])
}
if isRoomOwnerChanged {
EngineManager.shared.fetchRoomInfo(roomId: roomInfo.roomId) { _ in
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RoomOwnerChanged, param: ["owner": userId])
}
}
if checkAutoTakeSeatForOwner(userId: userId, userRole: userRole) {
let _ = engineManager.takeSeat()
}
if checkAutoSendingMessageForOwner(userId: userId, userRole: userRole) {
engineManager.disableSendingMessageByAdmin(userId: userId, isDisable: false)
}
if isSelfRoleChanged, userRole != .generalUser {
engineManager.updateSeatApplicationList()
}
}
private func checkAutoTakeSeatForOwner(userId: String, userRole: TUIRole) -> Bool {
let isSelfRoleChanged = userId == currentUser.userId
let isRoomOwnerChanged = userRole == .roomOwner
return isSelfRoleChanged && isRoomOwnerChanged && roomInfo.isSeatEnabled && !currentUser.isOnSeat
}
private func checkAutoSendingMessageForOwner(userId: String, userRole: TUIRole) -> Bool {
let isSelfRoleChanged = userId == currentUser.userId
let isRoomOwnerChanged = userRole == .roomOwner
return isSelfRoleChanged && isRoomOwnerChanged && currentUser.disableSendingMessage
}
private func requestReceived(request: TUIRequest) {
switch request.requestAction {
case .takeSeat:
store.addInviteSeatUser(request: request)
default: break
}
}
private func userVoiceVolumeChanged(volumeMap: [String : NSNumber]) {
for (userId, volume) in volumeMap {
guard let userModel = store.attendeeList.first(where: { $0.userId == userId}) else { continue }
userModel.userVoiceVolume = volume.intValue
}
}
private func userScreenCaptureStopped() {
currentUser.hasScreenStream = false
guard let userModel = store.attendeeList.first(where: { $0.userId == currentUser.userId }) else { return }
userModel.hasScreenStream = false
}
private func kickedOffLine() {
engineManager.destroyEngineManager()
}
}