Files
2025-09-22 18:48:29 +08:00

229 lines
8.0 KiB
Swift

//
// JoinInGroupCallViewModel.swift
// TUICallKit-Swift
//
// Created by noah on 2024/1/23.
//
import UIKit
import TUICallEngine
import ImSDK_Plus
import TUICore
class JoinInGroupCallViewModel: NSObject, V2TIMGroupListener, JoinInGroupCallViewDelegate {
private let callStatusObserver = Observer()
private var joinGroupCallView = JoinInGroupCallView()
private var roomId = TUIRoomId()
private var groupId: String = ""
private var callMediaType: TUICallMediaType = .unknown
private var recordExpansionStatus: Bool = false
override init() {
super.init()
V2TIMManager.sharedInstance().addGroupListener(listener: self)
registerCallStatusObserver()
}
deinit {
TUICallState.instance.selfUser.value.callStatus.removeObserver(callStatusObserver)
}
func getGroupAttributes(_ groupID: String) {
groupId = groupID
recordExpansionStatus = false
guard TUICallState.instance.selfUser.value.callStatus.value == .none else {
return
}
V2TIMManager.sharedInstance().getGroupAttributes(groupID, keys: nil) { [weak self] groupAttributeList in
guard let self = self, let attributeList = groupAttributeList as? [String : String] else {
return
}
self.processGroupAttributeData(attributeList)
} fail: { code, message in
}
}
func setJoinGroupCallView(_ joinGroupView: JoinInGroupCallView) {
joinGroupCallView = joinGroupView
joinGroupCallView.delegate = self
joinGroupCallView.isHidden = true
}
func registerCallStatusObserver() {
TUICallState.instance.selfUser.value.callStatus.addObserver(callStatusObserver, closure: { [weak self] newValue, _ in
guard let self = self else { return }
if newValue == .none && !self.groupId.isEmpty && self.groupId.count > 0 {
self.getGroupAttributes(self.groupId)
}
})
}
// MARK: - Private Method
private func processGroupAttributeData(_ groupAttributeList: [String: String]) {
guard let jsonStr = groupAttributeList["inner_attr_kit_info"], jsonStr.count > 0,
let jsonData = jsonStr.data(using: .utf8),
let groupAttributeDic = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any],
checkBusinessType(groupAttributeDic) else {
hiddenJoinGroupCallView()
return
}
handleRoomId(groupAttributeDic)
handleCallMediaType(groupAttributeDic)
guard let userIdList = getUserIdList(groupAttributeDic), userIdList.count > 0 else {
hiddenJoinGroupCallView()
return
}
if userIdList.contains(TUICallState.instance.selfUser.value.id.value) {
hiddenJoinGroupCallView()
return
}
handleUsersInfo(userIdList)
}
private func checkBusinessType(_ groupAttributeValue: [String: Any]) -> Bool {
guard let businessType = groupAttributeValue["business_type"] as? String else {
return false
}
return businessType == "callkit"
}
private func handleRoomId(_ groupAttributeValue: [String: Any]) {
guard let strRoomId = groupAttributeValue["room_id"] as? String, strRoomId.count > 0 else {
return
}
if groupAttributeValue["room_id_type"] as? Int == 2 {
roomId.strRoomId = strRoomId
return
}
if let intRoomId = UInt32(strRoomId) {
roomId.intRoomId = intRoomId
} else {
roomId.strRoomId = strRoomId
}
}
private func handleCallMediaType(_ groupAttributeValue: [String: Any]) {
guard let callMediaType = groupAttributeValue["call_media_type"] as? String, callMediaType.count > 0 else {
return
}
if callMediaType == "audio" {
self.callMediaType = TUICallMediaType.audio
} else if callMediaType == "video" {
self.callMediaType = TUICallMediaType.video
}
}
private func getUserIdList(_ groupAttributeValue: [String: Any]) -> [String]? {
guard let userInfoList = groupAttributeValue["user_list"] as? [[String: Any]] else {
return nil
}
var userIdList = [String]()
for userInfoDic in userInfoList {
guard let userId = userInfoDic["userid"] as? String else {
break
}
userIdList.append(userId)
}
return userIdList
}
private func handleUsersInfo(_ userIdList: [String]) {
V2TIMManager.sharedInstance().getUsersInfo(userIdList) { [weak self] infoList in
guard let self = self, let userInfoList = infoList else { return }
var userModelList: [User] = Array()
for userInfo in userInfoList {
let userModel = User()
userModel.id.value = userInfo.userID ?? ""
userModel.avatar.value = userInfo.faceURL ?? ""
userModelList.append(userModel)
}
if userModelList.count > 1 {
self.showJoinGroupCallView()
self.joinGroupCallView.updateView(with: userModelList, callMediaType:self.callMediaType)
} else {
self.hiddenJoinGroupCallView()
}
} fail: { code, message in
}
}
private func showJoinGroupCallView() {
joinGroupCallView.isHidden = false
updatePageContent()
postUpdateNotification()
}
func hiddenJoinGroupCallView() {
joinGroupCallView.isHidden = true
if let parentView = joinGroupCallView.superview {
parentView.frame = CGRect(x: 0, y: 0, width: parentView.bounds.size.width, height: 0)
postUpdateNotification()
}
}
func updatePageContent() {
DispatchQueue.main.async {
let joinGroupCallViewHeight = self.recordExpansionStatus ? kJoinGroupCallViewExpandHeight : kJoinGroupCallViewDefaultHeight
self.joinGroupCallView.frame = CGRect(x: self.joinGroupCallView.frame.origin.x,
y: self.joinGroupCallView.frame.origin.y,
width: self.joinGroupCallView.bounds.size.width,
height: joinGroupCallViewHeight)
if let parentView = self.joinGroupCallView.superview {
parentView.frame = CGRect(x: 0,
y: 0,
width: parentView.bounds.size.width,
height: self.joinGroupCallView.bounds.size.height)
}
}
}
func postUpdateNotification() {
DispatchQueue.main.async {
NotificationCenter.default.post(name: Notification.Name(TUICore_TUIChatExtension_ChatViewTopArea_ChangedNotification), object: nil)
}
}
// MARK: - TUICallKitJoinGroupCallViewDelegate
func updatePageContent(isExpand: Bool) {
if recordExpansionStatus != isExpand {
recordExpansionStatus = isExpand
}
updatePageContent()
postUpdateNotification()
}
func joinInGroupCall() {
hiddenJoinGroupCallView()
TUICallKit.createInstance().joinInGroupCall(roomId: roomId, groupId: groupId, callMediaType: callMediaType)
}
// MARK: - V2TIMGroupListener
func onGroupAttributeChanged(_ groupID: String!, attributes: NSMutableDictionary!) {
guard let attributes = attributes as? [String: String],
groupId == groupID else {
return
}
if TUICallState.instance.selfUser.value.callStatus.value != .none {
self.hiddenJoinGroupCallView()
return
}
processGroupAttributeData(attributes)
}
}