587 lines
24 KiB
Swift
587 lines
24 KiB
Swift
//
|
|
// 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()
|
|
}
|
|
}
|