提交
This commit is contained in:
@@ -0,0 +1,586 @@
|
||||
//
|
||||
// TUIVideoSeatPresenter.swift
|
||||
// TUIVideoSeat
|
||||
//
|
||||
// Created by WesleyLei on 2022/9/28.
|
||||
// Copyright © 2022 Tencent. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RTCRoomEngine
|
||||
#if canImport(TXLiteAVSDK_TRTC)
|
||||
import TXLiteAVSDK_TRTC
|
||||
#elseif canImport(TXLiteAVSDK_Professional)
|
||||
import TXLiteAVSDK_Professional
|
||||
#endif
|
||||
|
||||
protocol TUIVideoSeatViewModelResponder: AnyObject {
|
||||
func reloadData()
|
||||
func insertItems(at indexPaths: [IndexPath])
|
||||
func deleteItems(at indexPaths: [IndexPath])
|
||||
|
||||
func getVideoVisibleCell(_ item: VideoSeatItem) -> VideoSeatCell?
|
||||
func getMoveMiniscreen() -> TUIVideoSeatDragCell
|
||||
|
||||
func updateMiniscreen(_ item: VideoSeatItem?)
|
||||
func updateMiniscreenVolume(_ item: VideoSeatItem)
|
||||
|
||||
func updateVideoSeatCellUI(_ item: VideoSeatItem)
|
||||
|
||||
func updateSeatVolume(_ item: VideoSeatItem)
|
||||
|
||||
func showScreenCaptureMaskView(isShow: Bool)
|
||||
|
||||
func destroyVideoSeatResponder()
|
||||
}
|
||||
|
||||
enum TUIVideoSeatViewType {
|
||||
case unknown
|
||||
case singleType
|
||||
case pureAudioType
|
||||
case largeSmallWindowType
|
||||
case speechType
|
||||
case equallyDividedType
|
||||
}
|
||||
|
||||
class TUIVideoSeatViewModel: NSObject {
|
||||
private var videoSeatItems: [VideoSeatItem] = []
|
||||
private var shareItem: VideoSeatItem?
|
||||
private var speakerItem: VideoSeatItem?
|
||||
|
||||
private var isSwitchPosition: Bool = false
|
||||
|
||||
private var speakerUpdateTimer: Int = 0
|
||||
private let speakerUpdateTimeInterval = 5
|
||||
private var itemStreamType: TUIVideoStreamType {
|
||||
if listSeatItem.filter({ $0.hasVideoStream }).count > 5 {
|
||||
return .cameraStreamLow
|
||||
} else {
|
||||
return .cameraStream
|
||||
}
|
||||
}
|
||||
|
||||
var listSeatItem: [VideoSeatItem] = []
|
||||
|
||||
private var isHasVideoStream: Bool {
|
||||
return videoSeatItems.firstIndex(where: { $0.isHasVideoStream }) != nil
|
||||
}
|
||||
|
||||
private var isHasScreenStream: Bool {
|
||||
return shareItem != nil
|
||||
}
|
||||
|
||||
weak var viewResponder: TUIVideoSeatViewModelResponder?
|
||||
var videoSeatViewType: TUIVideoSeatViewType = .unknown
|
||||
var engineManager: EngineManager {
|
||||
EngineManager.shared
|
||||
}
|
||||
var store: RoomStore {
|
||||
engineManager.store
|
||||
}
|
||||
var roomInfo: TUIRoomInfo {
|
||||
store.roomInfo
|
||||
}
|
||||
var currentUserId: String {
|
||||
store.currentUser.userId
|
||||
}
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
initVideoSeatItems()
|
||||
subscribeUIEvent()
|
||||
}
|
||||
|
||||
private func initVideoSeatItems() {
|
||||
videoSeatItems = []
|
||||
let videoItems = store.roomInfo.isSeatEnabled ? store.seatList : store.attendeeList
|
||||
guard videoItems.count > 0 else { return }
|
||||
videoItems.forEach { userInfo in
|
||||
let userItem = VideoSeatItem()
|
||||
userItem.update(userInfo: userInfo)
|
||||
videoSeatItems.append(userItem)
|
||||
}
|
||||
if let shareInfo = videoItems.first(where: { $0.hasScreenStream }) {
|
||||
updateShareItem(userInfo: shareInfo)
|
||||
}
|
||||
sortSeatItems()
|
||||
reloadSeatItems()
|
||||
}
|
||||
|
||||
private func subscribeUIEvent() {
|
||||
EngineEventCenter.shared.subscribeUIEvent(key: .TUIRoomKitService_RenewVideoSeatView, responder: self)
|
||||
EngineEventCenter.shared.subscribeEngine(event: .onUserAudioStateChanged, observer: self)
|
||||
EngineEventCenter.shared.subscribeEngine(event: .onUserVideoStateChanged, observer: self)
|
||||
EngineEventCenter.shared.subscribeEngine(event: .onUserVoiceVolumeChanged, observer: self)
|
||||
EngineEventCenter.shared.subscribeEngine(event: .onUserScreenCaptureStopped, observer: self)
|
||||
EngineEventCenter.shared.subscribeEngine(event: .onRemoteUserEnterRoom, observer: self)
|
||||
EngineEventCenter.shared.subscribeEngine(event: .onRemoteUserLeaveRoom, observer: self)
|
||||
EngineEventCenter.shared.subscribeEngine(event: .onUserRoleChanged, observer: self)
|
||||
EngineEventCenter.shared.subscribeEngine(event: .onSeatListChanged, observer: self)
|
||||
EngineEventCenter.shared.subscribeUIEvent(key: .TUIRoomKitService_DismissConferenceViewController, responder: self)
|
||||
}
|
||||
|
||||
private func unsubscribeUIEvent() {
|
||||
EngineEventCenter.shared.unsubscribeUIEvent(key: .TUIRoomKitService_RenewVideoSeatView, responder: self)
|
||||
EngineEventCenter.shared.unsubscribeEngine(event: .onUserAudioStateChanged, observer: self)
|
||||
EngineEventCenter.shared.unsubscribeEngine(event: .onUserVideoStateChanged, observer: self)
|
||||
EngineEventCenter.shared.unsubscribeEngine(event: .onUserVoiceVolumeChanged, observer: self)
|
||||
EngineEventCenter.shared.unsubscribeEngine(event: .onUserScreenCaptureStopped, observer: self)
|
||||
EngineEventCenter.shared.unsubscribeEngine(event: .onRemoteUserEnterRoom, observer: self)
|
||||
EngineEventCenter.shared.unsubscribeEngine(event: .onRemoteUserLeaveRoom, observer: self)
|
||||
EngineEventCenter.shared.unsubscribeEngine(event: .onUserRoleChanged, observer: self)
|
||||
EngineEventCenter.shared.unsubscribeEngine(event: .onSeatListChanged, observer: self)
|
||||
EngineEventCenter.shared.unsubscribeUIEvent(key: .TUIRoomKitService_DismissConferenceViewController, responder: self)
|
||||
}
|
||||
|
||||
func updateShareItem(userInfo: UserEntity) {
|
||||
guard userInfo.hasScreenStream, shareItem == nil else { return }
|
||||
let item = VideoSeatItem()
|
||||
item.update(userInfo: userInfo)
|
||||
item.videoStreamType = .screenStream
|
||||
shareItem = item
|
||||
}
|
||||
|
||||
deinit {
|
||||
unsubscribeUIEvent()
|
||||
debugPrint("deinit:\(self)")
|
||||
}
|
||||
}
|
||||
|
||||
extension TUIVideoSeatViewModel {
|
||||
|
||||
private func startPlayVideo(item: VideoSeatItem, renderView: UIView?) {
|
||||
guard let renderView = renderView else { return }
|
||||
if item.userId == currentUserId {
|
||||
engineManager.setLocalVideoView(streamType: item.videoStreamType, view: renderView)
|
||||
} else {
|
||||
item.videoStreamType = item.videoStreamType == .screenStream ? .screenStream : itemStreamType
|
||||
engineManager.setRemoteVideoView(userId: item.userId, streamType: item.videoStreamType, view: renderView)
|
||||
engineManager.startPlayRemoteVideo(userId: item.userId, streamType: item.videoStreamType)
|
||||
}
|
||||
guard let seatCell = viewResponder?.getVideoVisibleCell(item) else { return }
|
||||
seatCell.updateUI(item: item)
|
||||
}
|
||||
|
||||
private func stopPlayVideo(item: VideoSeatItem) {
|
||||
if item.userId == currentUserId {
|
||||
engineManager.setLocalVideoView(streamType: item.videoStreamType, view: nil)
|
||||
} else {
|
||||
engineManager.setRemoteVideoView(userId: item.userId, streamType: item.videoStreamType, view: nil)
|
||||
engineManager.stopPlayRemoteVideo(userId: item.userId, streamType: item.videoStreamType)
|
||||
}
|
||||
guard let seatCell = viewResponder?.getVideoVisibleCell(item) else { return }
|
||||
seatCell.updateUI(item: item)
|
||||
}
|
||||
|
||||
private func addUserInfo(_ userId: String) {
|
||||
guard !videoSeatItems.contains(where: { $0.userId == userId }) else { return }
|
||||
guard let userInfo = getUserInfo(userId: userId) else { return }
|
||||
let seatItem = VideoSeatItem()
|
||||
seatItem.update(userInfo: userInfo)
|
||||
videoSeatItems.append(seatItem)
|
||||
if checkNeededSort() {
|
||||
refreshListSeatItem()
|
||||
viewResponder?.reloadData()
|
||||
resetMiniscreen()
|
||||
} else {
|
||||
reloadSeatItems()
|
||||
}
|
||||
}
|
||||
|
||||
private func getUserInfo(userId: String) -> UserEntity? {
|
||||
return store.attendeeList.first(where: { $0.userId == userId })
|
||||
}
|
||||
|
||||
private func removeSeatItem(_ userId: String) {
|
||||
if shareItem?.userId == userId, let seatItem = shareItem {
|
||||
stopPlayVideo(item: seatItem)
|
||||
}
|
||||
if speakerItem?.userId == userId, let seatItem = speakerItem {
|
||||
stopPlayVideo(item: seatItem)
|
||||
}
|
||||
if let seatItem = videoSeatItems.first(where: { $0.userId == userId }) {
|
||||
stopPlayVideo(item: seatItem)
|
||||
}
|
||||
videoSeatItems.removeAll(where: { $0.userId == userId })
|
||||
var deleteIndex: [IndexPath] = []
|
||||
if let index = listSeatItem.firstIndex(where: { $0.userId == userId && $0.videoStreamType != .screenStream }) {
|
||||
deleteIndex.append(IndexPath(item: index, section: 0))
|
||||
}
|
||||
refreshListSeatItem()
|
||||
if videoSeatViewType == .largeSmallWindowType {
|
||||
viewResponder?.reloadData()
|
||||
} else {
|
||||
viewResponder?.deleteItems(at: deleteIndex)
|
||||
}
|
||||
resetMiniscreen()
|
||||
}
|
||||
|
||||
private func changeUserRole(userId: String, userRole: TUIRole) {
|
||||
if let item = getSeatItem(userId) {
|
||||
item.userRole = userRole
|
||||
viewResponder?.updateVideoSeatCellUI(item)
|
||||
}
|
||||
if let shareItem = shareItem, shareItem.userId == userId {
|
||||
shareItem.userRole = userRole
|
||||
viewResponder?.updateVideoSeatCellUI(shareItem)
|
||||
}
|
||||
if let speakerItem = speakerItem, speakerItem.userId == userId {
|
||||
speakerItem.userRole = userRole
|
||||
viewResponder?.updateVideoSeatCellUI(speakerItem)
|
||||
}
|
||||
guard userRole == .roomOwner else { return }
|
||||
refreshListSeatItem()
|
||||
viewResponder?.reloadData()
|
||||
resetMiniscreen()
|
||||
}
|
||||
|
||||
private func getSeatItem(_ userId: String) -> VideoSeatItem? {
|
||||
return videoSeatItems.first(where: { $0.userId == userId })
|
||||
}
|
||||
|
||||
private func sortSeatItems() {
|
||||
guard checkNeededSort() else { return }
|
||||
// I'm second
|
||||
if let currentItemIndex = videoSeatItems.firstIndex(where: { $0.userId == self.currentUserId }) {
|
||||
let currentItem = videoSeatItems.remove(at: currentItemIndex)
|
||||
videoSeatItems.insert(currentItem, at: 0)
|
||||
}
|
||||
// Homeowners always come first
|
||||
if let roomOwnerItemIndex = videoSeatItems.firstIndex(where: { $0.userId == roomInfo.ownerId }) {
|
||||
let roomOwnerItem = videoSeatItems.remove(at: roomOwnerItemIndex)
|
||||
videoSeatItems.insert(roomOwnerItem, at: 0)
|
||||
}
|
||||
}
|
||||
|
||||
private func checkNeededSort() -> Bool {
|
||||
var isSort = false
|
||||
if let roomOwnerItemIndex = videoSeatItems.firstIndex(where: { $0.userId == roomInfo.ownerId }) {
|
||||
isSort = roomOwnerItemIndex != 0
|
||||
}
|
||||
if let currentItemIndex = videoSeatItems.firstIndex(where: { $0.userId == self.currentUserId }) {
|
||||
if currentUserId == roomInfo.ownerId {
|
||||
isSort = isSort || (currentItemIndex != 0)
|
||||
} else {
|
||||
isSort = isSort || (currentItemIndex != 1)
|
||||
}
|
||||
}
|
||||
return isSort
|
||||
}
|
||||
|
||||
private func findCurrentSpeaker(list: [VideoSeatItem]) -> VideoSeatItem? {
|
||||
if let shareItem = shareItem {
|
||||
return list.first(where: { $0.hasAudioStream && $0.userVoiceVolume > 10 && $0.userId != shareItem.userId })
|
||||
} else if let speech = listSeatItem.first {
|
||||
return list.first(where:{ $0.hasAudioStream && $0.userVoiceVolume > 10 && $0.userId != speech.userId })
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private func refreshListSeatItem() {
|
||||
sortSeatItems()
|
||||
listSeatItem = Array(videoSeatItems)
|
||||
if videoSeatItems.count == 1 {
|
||||
videoSeatViewType = .singleType
|
||||
if isHasScreenStream {
|
||||
refreshMultiVideo()
|
||||
}
|
||||
} else if videoSeatItems.count == 2, isHasVideoStream, !isHasScreenStream {
|
||||
videoSeatViewType = .largeSmallWindowType
|
||||
if isSwitchPosition {
|
||||
let first = listSeatItem[0]
|
||||
listSeatItem[0] = listSeatItem[1]
|
||||
listSeatItem[1] = first
|
||||
}
|
||||
} else if videoSeatItems.count >= 2, !isHasVideoStream, !isHasScreenStream {
|
||||
videoSeatViewType = .pureAudioType
|
||||
} else {
|
||||
refreshMultiVideo()
|
||||
}
|
||||
}
|
||||
|
||||
private func refreshMultiVideo() {
|
||||
let videoResult = videoSeatItems.filter({ $0.hasVideoStream })
|
||||
var speechItem: VideoSeatItem?
|
||||
if let item = shareItem {
|
||||
speechItem = item
|
||||
} else if videoResult.count == 1, let item = videoResult.first {
|
||||
speechItem = item
|
||||
}
|
||||
if let item = speechItem, let seatItemIndex = videoSeatItems.firstIndex(where: { $0.userId == item.userId }) {
|
||||
videoSeatViewType = .speechType
|
||||
if item.videoStreamType == .screenStream, item.userId != currentUserId {
|
||||
listSeatItem.insert(item, at: 0)
|
||||
} else {
|
||||
listSeatItem.remove(at: seatItemIndex)
|
||||
listSeatItem.insert(item, at: 0)
|
||||
if item.userId == speakerItem?.userId {
|
||||
speakerItem = nil
|
||||
}
|
||||
}
|
||||
if let currentSpeakerItem = findCurrentSpeaker(list: listSeatItem) {
|
||||
speakerItem = currentSpeakerItem
|
||||
} else {
|
||||
if let item = speakerItem, videoSeatItems.firstIndex(where: { $0.userId == item.userId }) == nil {
|
||||
speakerItem = nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
videoSeatViewType = .equallyDividedType
|
||||
}
|
||||
}
|
||||
|
||||
private func reloadSeatItems() {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
let type = self.videoSeatViewType
|
||||
let lastListSeatItem = Array(self.listSeatItem)
|
||||
self.refreshListSeatItem()
|
||||
self.updateCollectionView(type, lastListSeatItem)
|
||||
self.resetMiniscreen()
|
||||
}
|
||||
}
|
||||
|
||||
private func resetMiniscreen() {
|
||||
if self.videoSeatViewType == .speechType {
|
||||
self.viewResponder?.updateMiniscreen(self.speakerItem)
|
||||
} else {
|
||||
self.speakerItem = nil
|
||||
self.viewResponder?.updateMiniscreen(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateSeatVolume(item: VideoSeatItem) {
|
||||
viewResponder?.updateSeatVolume(item)
|
||||
if let shareItem = shareItem, shareItem.userId == item.userId {
|
||||
shareItem.hasAudioStream = item.hasAudioStream
|
||||
shareItem.userVoiceVolume = item.userVoiceVolume
|
||||
viewResponder?.updateSeatVolume(shareItem)
|
||||
}
|
||||
if let speakerItem = speakerItem, speakerItem.userId == item.userId {
|
||||
speakerItem.hasAudioStream = item.hasAudioStream
|
||||
speakerItem.userVoiceVolume = item.userVoiceVolume
|
||||
viewResponder?.updateMiniscreenVolume(speakerItem)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateCollectionView(_ type: TUIVideoSeatViewType, _ lastList: [VideoSeatItem]) {
|
||||
if type != videoSeatViewType {
|
||||
viewResponder?.reloadData()
|
||||
} else {
|
||||
let count = lastList.count
|
||||
let diffItem = listSeatItem.count - count
|
||||
var indexPaths: [IndexPath] = []
|
||||
if diffItem > 0 {
|
||||
for i in count ... (count + diffItem - 1) {
|
||||
indexPaths.append(IndexPath(item: i, section: 0))
|
||||
}
|
||||
viewResponder?.insertItems(at: indexPaths)
|
||||
}
|
||||
for i in 0 ... min(max(count - 1, 0), max(listSeatItem.count - 1, 0)) {
|
||||
guard lastList.count > i && listSeatItem.count > i && lastList[i] != listSeatItem[i] else { continue }
|
||||
guard let item = listSeatItem[safe: i] else { continue }
|
||||
viewResponder?.updateVideoSeatCellUI(item)
|
||||
guard let cell = viewResponder?.getVideoVisibleCell(item) else { continue }
|
||||
if item.hasVideoStream {
|
||||
startPlayVideo(item: item, renderView: cell.renderView)
|
||||
} else {
|
||||
stopPlayVideo(item: item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func isConformedSpeakerTimeInterval() -> Bool {
|
||||
let currentTime: TimeInterval = Date().timeIntervalSince1970
|
||||
let timeStamp = Int(currentTime)
|
||||
let totalTime: UInt = UInt(labs(timeStamp - speakerUpdateTimer))
|
||||
return totalTime > speakerUpdateTimeInterval
|
||||
}
|
||||
}
|
||||
|
||||
extension TUIVideoSeatViewModel: RoomKitUIEventResponder {
|
||||
func onNotifyUIEvent(key: EngineEventCenter.RoomUIEvent, Object: Any?, info: [AnyHashable : Any]?) {
|
||||
switch key {
|
||||
case .TUIRoomKitService_RenewVideoSeatView:
|
||||
initVideoSeatItems()
|
||||
case .TUIRoomKitService_DismissConferenceViewController:
|
||||
viewResponder?.destroyVideoSeatResponder()
|
||||
viewResponder = nil
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TUIVideoSeatViewModel: RoomEngineEventResponder {
|
||||
func onEngineEvent(name: EngineEventCenter.RoomEngineEvent, param: [String : Any]?) {
|
||||
switch name {
|
||||
case .onUserAudioStateChanged:
|
||||
guard let userId = param?["userId"] as? String else { return }
|
||||
guard let hasAudio = param?["hasAudio"] as? Bool else { return }
|
||||
guard let seatItem = getSeatItem(userId) else { return }
|
||||
seatItem.hasAudioStream = hasAudio
|
||||
updateSeatVolume(item: seatItem)
|
||||
case .onUserVoiceVolumeChanged:
|
||||
guard let volumeMap = param as? [String: NSNumber] else { return }
|
||||
userVoiceVolumeChanged(volumeMap: volumeMap)
|
||||
case .onUserVideoStateChanged:
|
||||
guard let userId = param?["userId"] as? String else { return }
|
||||
guard let streamType = param?["streamType"] as? TUIVideoStreamType else { return }
|
||||
guard let hasVideo = param?["hasVideo"] as? Bool else { return }
|
||||
userVideoStateChanged(userId: userId, streamType: streamType, hasVideo: hasVideo)
|
||||
case .onUserScreenCaptureStopped:
|
||||
userScreenCaptureStopped()
|
||||
case .onRemoteUserEnterRoom:
|
||||
guard let userInfo = param?["userInfo"] as? TUIUserInfo else { return }
|
||||
guard !roomInfo.isSeatEnabled else { return }
|
||||
addUserInfo(userInfo.userId)
|
||||
case .onRemoteUserLeaveRoom:
|
||||
guard let userInfo = param?["userInfo"] as? TUIUserInfo else { return }
|
||||
removeSeatItem(userInfo.userId)
|
||||
case .onUserRoleChanged:
|
||||
guard let userId = param?["userId"] as? String else { return }
|
||||
guard let userRole = param?["userRole"] as? TUIRole else { return }
|
||||
engineManager.fetchRoomInfo(roomId: roomInfo.roomId) { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
self.changeUserRole(userId: userId, userRole: userRole)
|
||||
}
|
||||
case .onSeatListChanged:
|
||||
guard let left = param?["left"] as? [TUISeatInfo] else { return }
|
||||
guard let seated = param?["seated"] as? [TUISeatInfo] else { return }
|
||||
seatListChanged(seated: seated, left: left)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TUIVideoSeatViewModel: TUIRoomObserver {
|
||||
private func userVoiceVolumeChanged(volumeMap: [String: NSNumber]) {
|
||||
if volumeMap.count <= 0 {
|
||||
return
|
||||
}
|
||||
for (userId, volume) in volumeMap {
|
||||
guard let seatItem = getSeatItem(userId) else { continue }
|
||||
seatItem.userVoiceVolume = volume.intValue
|
||||
updateSeatVolume(item: seatItem)
|
||||
}
|
||||
|
||||
guard videoSeatViewType == .speechType else { return }
|
||||
guard let currentSpeakerItem = findCurrentSpeaker(list: listSeatItem) else { return }
|
||||
if viewResponder?.getMoveMiniscreen().seatItem != nil, speakerItem?.userId == currentSpeakerItem.userId {
|
||||
viewResponder?.updateMiniscreenVolume(currentSpeakerItem)
|
||||
} else {
|
||||
guard isConformedSpeakerTimeInterval() else { return }
|
||||
viewResponder?.updateMiniscreen(currentSpeakerItem)
|
||||
speakerUpdateTimer = Int(Date().timeIntervalSince1970)
|
||||
}
|
||||
speakerItem = currentSpeakerItem
|
||||
}
|
||||
|
||||
private func userVideoStateChanged(userId: String, streamType: TUIVideoStreamType, hasVideo: Bool) {
|
||||
if streamType == .screenStream, userId == currentUserId {
|
||||
viewResponder?.showScreenCaptureMaskView(isShow: hasVideo)
|
||||
return
|
||||
}
|
||||
guard let seatItem = getSeatItem(userId) else { return }
|
||||
if streamType == .cameraStream || streamType == .cameraStreamLow {
|
||||
seatItem.hasVideoStream = hasVideo
|
||||
if hasVideo {
|
||||
setRemoteRenderParams(userId: userId, streamType: streamType)
|
||||
startPlayVideo(item: seatItem, renderView: viewResponder?.getVideoVisibleCell(seatItem)?.renderView)
|
||||
} else {
|
||||
stopPlayVideo(item: seatItem)
|
||||
}
|
||||
reloadSeatItems()
|
||||
} else {
|
||||
updateScreenStreamView(seatItem: seatItem, hasVideo: hasVideo)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateScreenStreamView(seatItem: VideoSeatItem, hasVideo: Bool) {
|
||||
let screenIndexPath = IndexPath(item: 0, section: 0)
|
||||
if hasVideo {
|
||||
guard let shareUserInfo = getUserInfo(userId: seatItem.userId) else { return }
|
||||
updateShareItem(userInfo: shareUserInfo)
|
||||
refreshListSeatItem()
|
||||
viewResponder?.insertItems(at: [screenIndexPath])
|
||||
} else {
|
||||
shareItem = nil
|
||||
refreshListSeatItem()
|
||||
if videoSeatViewType == .largeSmallWindowType {
|
||||
viewResponder?.reloadData()
|
||||
} else {
|
||||
viewResponder?.deleteItems(at: [screenIndexPath])
|
||||
}
|
||||
}
|
||||
speakerItem = nil
|
||||
viewResponder?.updateMiniscreen(nil)
|
||||
}
|
||||
|
||||
private func setRemoteRenderParams(userId: String, streamType: TUIVideoStreamType) {
|
||||
let renderParams = TRTCRenderParams()
|
||||
renderParams.fillMode = (streamType == .screenStream) ? .fit : .fill
|
||||
let trtcStreamType: TRTCVideoStreamType = (streamType == .screenStream) ? .sub : .big
|
||||
engineManager.setRemoteRenderParams(userId: userId, streamType: trtcStreamType, params: renderParams)
|
||||
}
|
||||
|
||||
private func seatListChanged(seated: [TUISeatInfo], left: [TUISeatInfo]) {
|
||||
for leftSeat in left {
|
||||
if let userId = leftSeat.userId {
|
||||
removeSeatItem(userId)
|
||||
}
|
||||
}
|
||||
for seatInfo in seated {
|
||||
if let userId = seatInfo.userId {
|
||||
addUserInfo(userId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func userScreenCaptureStopped() {
|
||||
viewResponder?.showScreenCaptureMaskView(isShow: false)
|
||||
if shareItem?.userId == currentUserId {
|
||||
shareItem = nil
|
||||
}
|
||||
reloadSeatItems()
|
||||
}
|
||||
}
|
||||
|
||||
extension TUIVideoSeatViewModel: TUIVideoSeatViewResponder {
|
||||
func switchPosition() {
|
||||
guard videoSeatViewType == .largeSmallWindowType else { return }
|
||||
isSwitchPosition = !isSwitchPosition
|
||||
refreshListSeatItem()
|
||||
viewResponder?.reloadData()
|
||||
resetMiniscreen()
|
||||
}
|
||||
|
||||
func clickVideoSeat() {
|
||||
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_ChangeToolBarHiddenState, param: [:])
|
||||
guard RoomRouter.shared.hasChatWindow() else { return }
|
||||
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_HiddenChatWindow, param: [:])
|
||||
}
|
||||
|
||||
func startPlayVideoStream(item: VideoSeatItem, renderView: UIView?) {
|
||||
startPlayVideo(item: item, renderView: renderView)
|
||||
}
|
||||
|
||||
func stopPlayVideoStream(item: VideoSeatItem) {
|
||||
stopPlayVideo(item: item)
|
||||
}
|
||||
|
||||
func updateSpeakerPlayVideoState(currentPageIndex: Int) {
|
||||
guard videoSeatViewType != .speechType else { return }
|
||||
if currentPageIndex == 0 {
|
||||
viewResponder?.updateMiniscreen(speakerItem)
|
||||
} else if let item = videoSeatItems.first(where: { $0.userId == speakerItem?.userId }),
|
||||
let renderView = viewResponder?.getVideoVisibleCell(item)?.renderView {
|
||||
startPlayVideo(item: item, renderView: renderView)
|
||||
}
|
||||
}
|
||||
|
||||
func stopScreenCapture() {
|
||||
EngineEventCenter.shared.notifyEngineEvent(event: .onUserScreenCaptureStopped, param: [:])
|
||||
engineManager.stopScreenCapture()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user