This commit is contained in:
启星
2025-08-08 10:49:36 +08:00
parent 6400cf78bb
commit b5ce3d580a
8780 changed files with 978183 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
//
// InviteToJoinRoomManager.swift
// TUIRoomKit
//
// Created by janejntang on 2023/7/3.
// You can choose to invite members and send invitations.
import Foundation
import RTCRoomEngine
import TUICore
class InviteToJoinRoomManager {
class func startInviteToJoinRoom(message: RoomMessageModel, inviter: TUILoginUserInfo) {
let inviteJoinModel = InviteJoinModel(message: message, inviter: inviter)
pushSelectGroupMemberViewController(groupId: message.groupId) { responseData in
guard let modelList =
responseData[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_ResultUserList] as? [TUIUserModel]
else { return }
var invitedList: [String] = []
for userModel in modelList {
invitedList.append(userModel.userId)
}
inviteToJoinRoom(inviteJoinModel: inviteJoinModel, invitedList: invitedList)
}
}
class func pushSelectGroupMemberViewController(groupId: String, callback: @escaping TUIValueResultCallback) {
let param = [TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_GroupID: groupId]
if let navigateController = RoomMessageManager.shared.navigateController {
navigateController.push(TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Classic, param: param) { responseData in
callback(responseData)
}
} else {
let nav = UINavigationController()
let currentViewController = getCurrentWindowViewController()
currentViewController?.present(TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Classic,
param: param, embbedIn: nav,
forResult: { responseData in
callback(responseData)
})
}
}
class func inviteToJoinRoom(inviteJoinModel: InviteJoinModel, invitedList: [String]) {
guard invitedList.count > 0 else { return }
let dataDict = inviteJoinModel.getDicFromInviteJoinModel(inviteJoinModel: inviteJoinModel)
guard let dataString = dataDict.convertToString() else { return }
let pushInfo = V2TIMOfflinePushInfo()
invitedList.forEach { userId in
V2TIMManager.sharedInstance().invite(userId,
data: dataString,
onlineUserOnly: true,
offlinePushInfo: pushInfo,
timeout: 60) {
debugPrint("invite,success")
} fail: { code, message in
debugPrint("invite,code:\(code),message:\(String(describing: message))")
}
}
}
class private func getCurrentWindowViewController() -> UIViewController? {
var keyWindow: UIWindow?
for window in UIApplication.shared.windows {
if window.isMember(of: UIWindow.self), window.isKeyWindow {
keyWindow = window
break
}
}
guard let rootController = keyWindow?.rootViewController else {
return nil
}
func findCurrentController(from vc: UIViewController?) -> UIViewController? {
if let nav = vc as? UINavigationController {
return findCurrentController(from: nav.topViewController)
} else if let tabBar = vc as? UITabBarController {
return findCurrentController(from: tabBar.selectedViewController)
} else if let presented = vc?.presentedViewController {
return findCurrentController(from: presented)
}
return vc
}
let viewController = findCurrentController(from: rootController)
return viewController
}
}

View File

@@ -0,0 +1,125 @@
//
// RoomManager.swift
// TUIRoomKit
//
// Created by janejntang on 2023/7/3.
// Manage rooms, including room creation, entry, exit, destruction and conversion operations of the host
import Foundation
import RTCRoomEngine
import TUICore
class RoomManager {
static let shared = RoomManager()
private var engineManager: EngineManager {
EngineManager.shared
}
private var roomInfo: TUIRoomInfo {
engineManager.store.roomInfo
}
private lazy var userId: String = {
return TUILogin.getUserID() ?? engineManager.store.currentUser.userId
}()
private let messageManager = RoomMessageManager.shared
let roomObserver: RoomObserver = RoomObserver()
var roomId: String?
deinit {
debugPrint("deinit \(self)")
}
func isEnteredOtherRoom(roomId: String) -> Bool {
return roomInfo.roomId != roomId && roomInfo.roomId != ""
}
func createRoom(roomInfo: TUIRoomInfo) {
roomId = roomInfo.roomId
roomObserver.registerObserver()
engineManager.createRoom(roomInfo: roomInfo) { [weak self] in
guard let self = self else { return }
self.roomObserver.createdRoom()
self.enterRoom(roomId: roomInfo.roomId, isShownConferenceViewController: false)
} onError: { _, message in
RoomRouter.makeToast(toast: message)
}
}
func enterRoom(roomId: String, isShownConferenceViewController: Bool = true) {
roomObserver.registerObserver()
engineManager.store.isImAccess = true
self.roomId = roomId
engineManager.enterRoom(roomId: roomId, enableAudio: engineManager.store.isOpenMicrophone, enableVideo: engineManager.store.isOpenCamera, isSoundOnSpeaker: true) { [weak self] roomInfo in
guard let self = self else { return }
self.roomObserver.enteredRoom()
guard isShownConferenceViewController else { return }
let vc = ConferenceMainViewController()
RoomRouter.shared.push(viewController: vc)
} onError: { _, message in
RoomRouter.makeToast(toast: message)
}
}
func exitRoom(onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
engineManager.exitRoom { [weak self] in
guard let self = self else { return }
self.refreshSource()
self.messageManager.isReadyToSendMessage = true
onSuccess()
} onError: { [weak self] code, message in
guard let self = self else { return }
self.refreshSource()
if code.rawValue == -2_102 {
self.destroyRoom(onSuccess: onSuccess, onError: onError)
} else {
onError(code, message)
}
}
}
func destroyRoom(onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
engineManager.destroyRoom { [weak self] in
guard let self = self else { return }
self.roomObserver.messageModel.roomState = .destroyed
self.refreshSource()
self.messageManager.isReadyToSendMessage = true
onSuccess()
} onError: { [weak self] code, message in
guard let self = self else { return }
self.refreshSource()
onError(code, message)
}
}
private func refreshSource() {
roomId = nil
TUILogin.setCurrentBusinessScene(.None)
roomObserver.userList = []
roomObserver.unregisterObserver()
}
private func changeUserRole(userId: String, role: TUIRole, onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
engineManager.changeUserRole(userId: userId, role: .roomOwner) {
onSuccess()
} onError: { code, message in
onError(code, message)
}
}
func exitOrDestroyPreviousRoom(onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
if roomInfo.ownerId == userId {
if let userModel = engineManager.store.attendeeList.first(where: { $0.userId != userId }) {
changeUserRole(userId: userModel.userId, role: .roomOwner) { [weak self] in
guard let self = self else { return }
self.exitRoom(onSuccess: onSuccess, onError: onError)
} onError: { [weak self] code, message in
guard let self = self else { return }
self.destroyRoom(onSuccess: onSuccess, onError: onError)
}
} else {
destroyRoom(onSuccess: onSuccess, onError: onError)
}
} else {
exitRoom(onSuccess: onSuccess, onError: onError)
}
}
}

View File

@@ -0,0 +1,138 @@
//
// RoomMessageManager.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/8.
// Copyright © 2023 Tencent. All rights reserved.
// Manage messages, including sending messages and modifying messages
//
import Foundation
import TUICore
import RTCRoomEngine
class RoomMessageManager: NSObject {
static let shared = RoomMessageManager()
private var engineManager: EngineManager {
EngineManager.shared
}
private lazy var userId: String = {
return TUILogin.getUserID() ?? engineManager.store.currentUser.userId
}()
weak var navigateController: UINavigationController?
var isReadyToSendMessage: Bool = true
var groupId: String = ""
private override init() {
super.init()
TUICore.registerEvent(TUICore_TUIChatNotify, subKey: TUICore_TUIChatNotify_SendMessageSubKey, object: self)
}
func sendRoomMessageToGroup() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
guard BusinessSceneUtil.canJoinRoom() else { return }
if self.engineManager.store.isEnteredRoom {
RoomManager.shared.exitOrDestroyPreviousRoom() { [weak self] in
guard let self = self else { return }
self.sendMessage()
} onError: { [weak self] code, message in
guard let self = self else { return }
self.sendMessage()
debugPrint("exitRoom,code:\(code),message:\(message)")
}
} else {
self.sendMessage()
}
}
}
private func sendMessage() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
guard self.isReadyToSendMessage else {
self.changeReadyToSendMessage()
return
}
self.isReadyToSendMessage = false
FetchRoomId.getRoomId { [weak self] roomId in
guard let self = self else { return }
let messageModel = RoomMessageModel()
messageModel.groupId = self.groupId
messageModel.roomId = roomId
messageModel.ownerName = TUILogin.getNickName() ?? ""
messageModel.owner = self.userId
let messageDic = messageModel.getDictFromMessageModel()
guard let jsonString = messageDic.convertToString() else { return }
let jsonData = jsonString.data(using: String.Encoding.utf8)
let message = V2TIMManager.sharedInstance().createCustomMessage(jsonData)
message?.supportMessageExtension = true
let param = [TUICore_TUIChatService_SendMessageMethod_MsgKey: message]
TUICore.callService(TUICore_TUIChatService, method: TUICore_TUIChatService_SendMessageMethod, param: param as [AnyHashable : Any])
RoomManager.shared.roomId = roomId
}
}
}
func resendRoomMessage(message: RoomMessageModel,dic:[String: Any]) {
if message.messageId == "" {
self.modifyMessage(message: message, dic: dic)
return
}
V2TIMManager.sharedInstance().findMessages([message.messageId]) { [weak self] messageArray in
guard let self = self else { return }
guard let array = messageArray else { return }
for previousMessage in array where previousMessage.msgID == message.messageId {
self.modifyMessage(message: message, dic: dic)
}
} fail: { [weak self] code, messageString in
guard let self = self else { return }
self.modifyMessage(message: message, dic: dic)
}
}
private func modifyMessage(message: RoomMessageModel, dic:[String: Any]) {
guard let message = message.getMessage() else { return }
guard var customElemDic = TUITool.jsonData2Dictionary(message.customElem.data) as? [String: Any] else { return }
for (key, value) in dic {
customElemDic[key] = value
}
guard let jsonString = customElemDic.convertToString() else { return }
let jsonData = jsonString.data(using: String.Encoding.utf8)
message.customElem.data = jsonData
V2TIMManager.sharedInstance().modifyMessage(message) { code, desc, msg in
if code == 0 {
debugPrint("modifyMessage,success")
} else {
debugPrint("modifyMessage,code:\(code),message:\(String(describing: desc))")
}
}
}
deinit {
debugPrint("deinit \(self)")
}
}
extension RoomMessageManager {
private func changeReadyToSendMessage() {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 20) { [weak self] in
guard let self = self else { return }
self.isReadyToSendMessage = true
}
}
}
extension RoomMessageManager: TUINotificationProtocol {
func onNotifyEvent(_ key: String, subKey: String, object anObject: Any?, param: [AnyHashable : Any]?) {
guard key == TUICore_TUIChatNotify, subKey == TUICore_TUIChatNotify_SendMessageSubKey else { return }
guard let code = param?[TUICore_TUIChatNotify_SendMessageSubKey_Code] as? Int, code == 0 else { return }
guard let message = param?[TUICore_TUIChatNotify_SendMessageSubKey_Message] as? V2TIMMessage else { return }
let messageModel = RoomMessageModel()
messageModel.updateMessage(message: message)
guard messageModel.messageId.count > 0, messageModel.roomState == .creating, messageModel.roomId == RoomManager.shared.roomId else { return }
let roomInfo = TUIRoomInfo()
roomInfo.roomId = messageModel.roomId
RoomManager.shared.createRoom(roomInfo: roomInfo)
}
}

View File

@@ -0,0 +1,56 @@
//
// InviteJoinModel.swift
// TUIRoomKit
//
// Created by janejntang on 2023/7/3.
// Signaling Model for inviting others into the room
import Foundation
import TUICore
import RTCRoomEngine
class InviteJoinModel {
private var message: RoomMessageModel
private var inviter: TUILoginUserInfo
var platform: String = "iOS"
var version: Int = 1
var businessID: String = "ROOM_INVITE_ACTION"
var roomId: String = ""
var extInfo: String = ""
var data: [String:Any] = [:]
init(message: RoomMessageModel, inviter: TUILoginUserInfo) {
self.message = message
self.inviter = inviter
self.roomId = message.roomId
self.data = getInviteJoinModelDataDic()
}
func getDicFromInviteJoinModel(inviteJoinModel: InviteJoinModel) -> [String: Any] {
guard let dict = ["platform": inviteJoinModel.platform,
"version": inviteJoinModel.version,
"businessID": inviteJoinModel.businessID,
"roomId": inviteJoinModel.roomId,
"extInfo": inviteJoinModel.extInfo,
"data": inviteJoinModel.data,
] as? [String: Any] else { return [:] }
return dict
}
private func getInviteJoinModelDataDic() -> [String: Any] {
let messageDic = message.getDictFromMessageModel()
let inviterDic = getInviterUserInfoDic(inviter: inviter)
return ["inviter":inviterDic, "roomInfo": messageDic]
}
private func getInviterUserInfoDic(inviter: TUILoginUserInfo) -> [String: Any] {
return ["avatarUrl": inviter.avatarUrl,
"userId": inviter.userId,
"userName": inviter.userName,
]
}
deinit {
debugPrint("deinit \(self)")
}
}

View File

@@ -0,0 +1,90 @@
//
// RoomMessageModel.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/10.
//
import Foundation
import TUICore
class RoomMessageModel {
enum RoomState: String {
case creating
case created
case destroying
case destroyed
}
private var message: V2TIMMessage?
var version: Int = 1
var businessID: String = BussinessID_GroupRoomMessage
var groupId: String = ""
var messageId: String = ""
var roomId: String = ""
var owner: String = ""
var ownerName: String = ""
var roomState: RoomState = .creating
var memberCount: Int = 0
var userList: [[String:Any]] = []
init() {}
func updateMessage(message: V2TIMMessage) {
self.message = message
self.messageId = message.msgID ?? ""
guard var dict = getMessageCustomElemDic(message: message) else { return }
self.version = dict["version"] as? Int ?? 1
self.businessID = dict["businessID"] as? String ?? BussinessID_GroupRoomMessage
self.groupId = dict["groupId"] as? String ?? ""
self.roomId = dict["roomId"] as? String ?? ""
self.owner = dict["owner"] as? String ?? ""
self.ownerName = dict["ownerName"] as? String ?? ""
if let roomState = dict["roomState"] as? String {
self.roomState = RoomState(rawValue: roomState) ?? .creating
} else {
self.roomState = .creating
}
self.userList = dict["userList"] as? [[String:Any]] ?? []
self.memberCount = dict["memberCount"] as? Int ?? userList.count
dict["messageId"] = self.messageId
setMessageCustomElemData(dict: dict, message: message)
}
private func getMessageCustomElemDic(message: V2TIMMessage) -> [String: Any]? {
guard let customElem = message.customElem else { return nil}
guard let customData = customElem.data else { return nil}
guard let dataString = String(data: customData, encoding: String.Encoding.utf8) else { return nil }
guard let data = dataString.data(using: String.Encoding.utf8) else { return nil }
guard let dict = try? JSONSerialization.jsonObject(with: data,
options: .mutableContainers) as? [String : Any] else { return nil }
return dict
}
private func setMessageCustomElemData(dict: [String: Any], message: V2TIMMessage) {
guard let jsonString = dict.convertToString() else { return }
let jsonData = jsonString.data(using: String.Encoding.utf8)
message.customElem.data = jsonData
}
func getDictFromMessageModel() -> [String: Any] {
let dict = ["version": version,
"businessID": businessID,
"groupId": groupId,
"roomId": roomId,
"owner": owner,
"ownerName": ownerName,
"roomState": roomState.rawValue,
"memberCount": memberCount,
"messageId": messageId,
"userList": userList,
] as [String : Any]
return dict
}
func getMessage() -> V2TIMMessage? {
return message
}
deinit {
debugPrint("deinit \(self)")
}
}

View File

@@ -0,0 +1,210 @@
//
// RoomObserver.swift
// TUIRoomKit
//
// Created by janejntang on 2023/7/3.
import Foundation
import RTCRoomEngine
import TUICore
@objc public protocol RoomObserverListener {
@objc optional func onRoomEnter(messageId: String, code: Int, message: String) -> Void
@objc optional func onRoomExit(messageId: String) -> Void
}
class RoomObserver: NSObject {
var messageModel = RoomMessageModel()
private let messageManager = RoomMessageManager.shared
var engineManager: EngineManager {
EngineManager.shared
}
var roomEngine: TUIRoomEngine {
engineManager.roomEngine
}
lazy var userList: [[String: Any]] = {
return messageModel.userList
}()
private lazy var userId: String = {
return TUILogin.getUserID() ?? EngineManager.shared.store.currentUser.userId
}()
typealias Weak<T> = () -> T?
private var listenerArray: [Weak<RoomObserverListener>] = []
override init() {
super.init()
EngineEventCenter.shared.subscribeUIEvent(key: .TUIRoomKitService_RoomOwnerChanged, responder: self)
EngineEventCenter.shared.subscribeEngine(event: .onExitedRoom, observer: self)
EngineEventCenter.shared.subscribeEngine(event: .onDestroyedRoom, observer: self)
}
func registerObserver() {
roomEngine.addObserver(self)
}
func unregisterObserver() {
roomEngine.removeObserver(self)
}
func addListener(listener: RoomObserverListener) {
let weakObserver = { [weak listener] in return listener }
self.listenerArray.append(weakObserver)
}
func removeListener(listener: RoomObserverListener) {
listenerArray.removeAll(where: {$0() === listener})
}
private func refreshSource() {
RoomManager.shared.roomId = nil
TUILogin.setCurrentBusinessScene(.None)
engineManager.roomEngine.removeObserver(self)
userList = []
unregisterObserver()
}
func createdRoom() {
TUILogin.setCurrentBusinessScene(.InMeetingRoom)
messageModel.roomState = .created
let userInfo = TUIUserInfo()
userInfo.userId = userId
userInfo.avatarUrl = TUILogin.getFaceUrl() ?? ""
userInfo.userName = TUILogin.getNickName() ?? ""
addUserList(userInfo: userInfo)
let prefixUserList = Array(userList.prefix(5))
messageManager.resendRoomMessage(message: messageModel, dic: ["userList":prefixUserList,
"memberCount":userList.count,
"roomState":RoomMessageModel.RoomState.created.rawValue,])
}
func enteredRoom() {
TUILogin.setCurrentBusinessScene(.InMeetingRoom)
getUserList(nextSequence: 0)
}
func exitedRoom() {
RoomVideoFloatView.dismiss()
userList = userList.filter { [weak self] userDic in
guard let self = self, let userId = userDic["userId"] as? String else { return false }
return userId != self.userId
}
if messageModel.owner == userId {
let prefixUserList = Array(userList.prefix(5))
messageManager.resendRoomMessage(message: messageModel, dic: ["userList":prefixUserList, "memberCount":userList.count])
}
for weakObserver in listenerArray {
if let listener = weakObserver() {
listener.onRoomExit?(messageId: self.messageModel.messageId)
}
}
messageManager.isReadyToSendMessage = true
refreshSource()
}
func destroyedRoom() {
RoomVideoFloatView.dismiss()
messageModel.roomState = .destroyed
if messageModel.owner == userId {
messageManager.resendRoomMessage(message: messageModel, dic: ["roomState":RoomMessageModel.RoomState.destroyed.rawValue])
}
messageManager.isReadyToSendMessage = true
refreshSource()
}
deinit {
EngineEventCenter.shared.unsubscribeUIEvent(key: .TUIRoomKitService_RoomOwnerChanged, responder: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onExitedRoom, observer: self)
EngineEventCenter.shared.unsubscribeEngine(event: .onDestroyedRoom, observer: self)
debugPrint("deinit \(self)")
}
}
extension RoomObserver: TUIRoomObserver {
func onRemoteUserEnterRoom(roomId: String, userInfo: TUIUserInfo) {
addUserList(userInfo: userInfo)
guard userList.count > 1 else { return }
if messageModel.owner == userId {
let prefixUserList = Array(userList.prefix(5))
messageManager.resendRoomMessage(message: messageModel, dic: ["userList":prefixUserList,"memberCount":userList.count])
}
}
func onRemoteUserLeaveRoom(roomId: String, userInfo: TUIUserInfo) {
userList = userList.filter { userDic in
if let userId = userDic["userId"] as? String, userId != userInfo.userId {
return true
}
return false
}
if messageModel.owner == userId {
let prefixUserList = Array(userList.prefix(5))
messageManager.resendRoomMessage(message: messageModel, dic: ["memberCount":userList.count,"userList":prefixUserList])
}
}
func onRoomDismissed(roomId: String, reason: TUIRoomDismissedReason) {
RoomVideoFloatView.dismiss()
messageManager.isReadyToSendMessage = true
refreshSource()
}
func onKickedOutOfRoom(roomId: String, reason: TUIKickedOutOfRoomReason, message: String) {
RoomVideoFloatView.dismiss()
messageManager.isReadyToSendMessage = true
refreshSource()
}
}
extension RoomObserver {
private func getUserList(nextSequence: Int) {
engineManager.roomEngine.getUserList(nextSequence: nextSequence) { [weak self] list, nextSequence in
guard let self = self else { return }
list.forEach { userInfo in
self.addUserList(userInfo: userInfo)
}
if nextSequence != 0 {
self.getUserList(nextSequence: nextSequence)
}
} onError: { code, message in
debugPrint("getUserList:code:\(code),message:\(message)")
}
}
private func addUserList(userInfo: TUIUserInfo) {
if getUserItem(userInfo.userId) == nil {
let userDic: [String: Any] = ["userId":userInfo.userId,"userName":userInfo.userName,"faceUrl": userInfo.avatarUrl]
userList.append(userDic)
}
}
private func getUserItem(_ userId: String) -> String? {
for userDic in userList {
if let userIdString = userDic["userId"] as? String, userIdString == userId {
return userIdString
}
}
return nil
}
}
extension RoomObserver: RoomKitUIEventResponder {
func onNotifyUIEvent(key: EngineEventCenter.RoomUIEvent, Object: Any?, info: [AnyHashable : Any]?) {
switch key {
case .TUIRoomKitService_RoomOwnerChanged:
guard let userId = info?["owner"] as? String else { return }
messageManager.resendRoomMessage(message: messageModel, dic: ["owner": userId])
default: break
}
}
}
extension RoomObserver: RoomEngineEventResponder {
func onEngineEvent(name: EngineEventCenter.RoomEngineEvent, param: [String : Any]?) {
switch name {
case .onExitedRoom:
exitedRoom()
case .onDestroyedRoom:
destroyedRoom()
default: break
}
}
}

View File

@@ -0,0 +1,86 @@
//
// RoomMessageExtensionObserver.swift
// TUIRoomKit
//
// Created by janejntang on 2023/6/2.
//
import Foundation
import TUICore
import TIMCommon
class RoomMessageExtensionObserver: NSObject {
static let shared = RoomMessageExtensionObserver()
let roomMessageManager: RoomMessageManager = RoomMessageManager.shared
var settingMenuNavigationController: UINavigationController?
private override init() {
super.init()
}
@objc private func pushChatExtensionRoomSettingsViewController() {
if let nav = settingMenuNavigationController {
let vc = ChatExtensionRoomSettingsViewController(isOpenMicrophone: EngineManager.shared.store.isOpenMicrophone,
isOpenCamera: EngineManager.shared.store.isOpenCamera)
nav.pushViewController(vc, animated: true)
}
}
deinit {
debugPrint("deinit \(self)")
}
}
extension RoomMessageExtensionObserver: TUIExtensionProtocol {
func onGetExtension(_ key: String, param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? {
if key == TUICore_TUIChatExtension_InputViewMoreItem_ClassicExtensionID {
guard let groupID = param?[TUICore_TUIChatExtension_InputViewMoreItem_GroupID] as? String, groupID != "" else { return nil }
guard let isNeedRoom = param?[TUICore_TUIChatExtension_InputViewMoreItem_FilterRoom] as? Bool, !isNeedRoom else { return nil }
let info = TUIExtensionInfo()
info.weight = 200
info.text = .meetingText
let defaultImage = UIImage(named: "room_quick_meeting", in: tuiRoomKitBundle(), compatibleWith: nil) ?? UIImage()
info.icon = TUICoreThemeConvert.getTUIDynamicImage(imageKey: "room_quick_meeting_image", defaultImage: defaultImage)
info.onClicked = { [weak self] param in
guard let self = self else { return }
if let vc = param[TUICore_TUIChatExtension_InputViewMoreItem_PushVC] as? UINavigationController {
self.roomMessageManager.navigateController = vc
}
if let groupId = param[TUICore_TUIChatExtension_InputViewMoreItem_GroupID] as? String {
self.roomMessageManager.groupId = groupId
}
self.roomMessageManager.sendRoomMessageToGroup()
}
return [info]
}
if key == TUICore_TUIContactExtension_MeSettingMenu_ClassicExtensionID {
if let nav = param?[TUICore_TUIContactExtension_MeSettingMenu_Nav] as? UINavigationController {
self.settingMenuNavigationController = nav
}
let data = TUICommonTextCellData()
data.key = .roomDeviceSetText
data.showAccessory = true
let cell = TUICommonTextCell()
cell.fill(with: data)
cell.mm_h = 60
cell.mm_w = UIScreen.main.bounds.width
let tap = UITapGestureRecognizer(target: self, action: #selector(pushChatExtensionRoomSettingsViewController))
cell.addGestureRecognizer(tap)
let info = TUIExtensionInfo()
let param = [TUICore_TUIContactExtension_MeSettingMenu_Weight: 460,
TUICore_TUIContactExtension_MeSettingMenu_View: cell,
TUICore_TUIContactExtension_MeSettingMenu_Data: data,
] as [String : Any]
info.data = param
return [info]
}
return nil
}
}
private extension String {
static var meetingText: String {
localized("Quick meeting")
}
static var roomDeviceSetText: String {
localized("Meeting Settings")
}
}

View File

@@ -0,0 +1,14 @@
//
// RoomSetListItemData.swift
// TUIRoomKit
//
// Created by janejntang on 2023/6/27.
//
import Foundation
class RoomSetListItemData {
var titleText: String = ""
var isSwitchOn: Bool = false
var action: ((Any)->Void)?
}

View File

@@ -0,0 +1,35 @@
//
// TUIRoomImAccessFactory.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/10.
// Copyright © 2023 Tencent. All rights reserved.
//
import Foundation
import TUICore
class TUIRoomImAccessFactory: NSObject {
static let shared = TUIRoomImAccessFactory()
private override init() {
super.init()
}
deinit {
debugPrint("deinit \(self)")
}
}
extension TUIRoomImAccessFactory: TUIObjectProtocol {
func onCreateObject(_ method: String, param: [AnyHashable : Any]?) -> Any? {
if method == TUICore_TUIRoomImAccessFactory_GetRoomMessageViewMethod {
guard let message = param?[TUICore_TUIRoomImAccessFactory_GetRoomMessageViewMethod_Message] as?
V2TIMMessage else { return UIView(frame: .zero) }
let roomMessageModel = RoomMessageModel()
roomMessageModel.updateMessage(message: message)
let viewModel = RoomMessageViewModel(message: roomMessageModel)
let view = RoomMessageView(viewModel: viewModel)
return view
}
return nil
}
}

View File

@@ -0,0 +1,68 @@
//
// TUIRoomImAccessService.swift
// TUIRoomKit
//
// Created by janejntang on 2023/6/2.
//
import Foundation
import TUICore
class TUIRoomImAccessService: NSObject, TUIServiceProtocol {
static let shared = TUIRoomImAccessService()
var isShownInvitedToJoinRoomView: Bool = false
weak var inviteViewController: UIViewController?
var inviteWindow: UIWindow?
private override init() {
super.init()
initRoomMessage()
initSignalingListener()
initThemeResource()
}
func initRoomMessage() {
TUICore.callService(TUICore_TUIChatService, method: TUICore_TUIChatService_AppendCustomMessageMethod, param:
[BussinessID: BussinessID_GroupRoomMessage, TMessageCell_Name: "RoomMessageBubbleCell",
TMessageCell_Data_Name:"RoomMessageBubbleCellData",])
}
func initSignalingListener() {
V2TIMManager.sharedInstance().addSignalingListener(listener: self)
}
func initThemeResource() {
TUICoreThemeConvert.initThemeResource()
}
}
extension TUIRoomImAccessService: V2TIMSignalingListener {
func onReceiveNewInvitation(_ inviteID: String, inviter: String, groupID: String, inviteeList: [String], data: String?) {
guard let data = data else { return }
let dict = data.convertToDic()
guard let businessID = dict?["businessID"] as? String else { return }
guard businessID == "ROOM_INVITE_ACTION" else { return }
guard let roomId = dict?["roomId"] as? String else { return }
guard let userId = TUILogin.getUserID() else { return }
let dataDic = dict?["data"] as? NSDictionary ?? [:]
let inviter = dataDic["inviter"] as? NSDictionary ?? [:]
let avatarUrl = inviter["avatarUrl"] as? String ?? ""
let inviterUserName = inviter["userName"] as? String ?? ""
guard inviteeList.contains(userId) else { return }
let businessScene = TUILogin.getCurrentBusinessScene()
guard businessScene == .None || businessScene == .InMeetingRoom else { return }
showInvitedToJoinRoomView(inviterUserName: inviterUserName, inviteUserAvatarUrl: avatarUrl, roomId: roomId)
}
private func showInvitedToJoinRoomView(inviterUserName: String, inviteUserAvatarUrl: String, roomId: String) {
if isShownInvitedToJoinRoomView {
return
}
isShownInvitedToJoinRoomView = true
let inviteViewController = InvitedToJoinRoomViewController(inviteUserName: inviterUserName,inviteUserAvatarUrl:
inviteUserAvatarUrl, roomId: roomId)
let nav = UINavigationController(rootViewController: inviteViewController)
nav.setNavigationBarHidden(true, animated: true)
inviteWindow = UIWindow(frame: UIScreen.main.bounds)
inviteWindow?.windowLevel = .alert - 1
guard let inviteWindow = inviteWindow else { return }
inviteWindow.rootViewController = nav
inviteWindow.isHidden = false
inviteWindow.makeKeyAndVisible()
}
}

View File

@@ -0,0 +1,24 @@
//
// BusinessSceneUtil.swift
// TUIRoomKit
//
// Created by janejntang on 2023/7/3.
// Determine the current scene and set the current scene
import Foundation
import TUICore
class BusinessSceneUtil {
class func canJoinRoom() -> Bool {
let businessScene = TUILogin.getCurrentBusinessScene()
return businessScene == .InMeetingRoom || businessScene == .None
}
class func setJoinRoomFlag() {
TUILogin.setCurrentBusinessScene(.InMeetingRoom)
}
class func clearJoinRoomFlag() {
TUILogin.setCurrentBusinessScene(.None)
}
}

View File

@@ -0,0 +1,25 @@
//
// TUICoreThemeConvert.swift
// TUIRoomKit
//
// Created by janejntang on 2024/1/29.
//
import Foundation
import TUICore
class TUICoreThemeConvert {
static func initThemeResource() {
TUIThemeManager.share().registerThemeResourcePath(getTUIRoomKitThemePath(), for: .roomKit)
}
static func getTUIRoomKitThemePath() -> String {
return getTUIGetBundlePath("TUIRoomKitTheme", TUICore_TUIRoomImAccessService)
}
static func getTUIDynamicImage(imageKey: String, defaultImage: UIImage) -> UIImage? {
return TUITheme.dynamicImage(imageKey, module: .roomKit, defaultImage: defaultImage)
}
}