| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- //
- // MultiStreamsSorter.swift
- // TUIRoomKit
- //
- // Created by CY zhao on 2024/12/18.
- //
- import Foundation
- class MultiStreamsSorter {
- private let currentUserId: String
- private var roomOwnerId: String = ""
-
- init(currentUserId: String) {
- self.currentUserId = currentUserId
- }
-
- func sortStreams(_ videoItems: [UserInfo]) -> [UserInfo] {
- guard needSorting(videoItems) else { return videoItems }
- var sortedItems = videoItems
-
- if let ownerIndex = sortedItems.firstIndex(where: { $0.userRole == .roomOwner }) {
- let owner = sortedItems.remove(at: ownerIndex)
- roomOwnerId = owner.userId
- sortedItems.insert(owner, at: 0)
- }
-
- if currentUserId != roomOwnerId,
- let currentUserIndex = sortedItems.firstIndex(where: { $0.userId == currentUserId }) {
- let currentUser = sortedItems.remove(at: currentUserIndex)
- sortedItems.insert(currentUser, at: 1)
- }
-
- let sortedOthers = sortedItems
- .dropFirst(currentUserId == roomOwnerId ? 1 : 2)
- .sorted { first, second in
- let firstStatus = StreamStatus(hasAudio: first.hasAudioStream,
- hasVideo: first.hasVideoStream)
- let secondStatus = StreamStatus(hasAudio: second.hasAudioStream,
- hasVideo: second.hasVideoStream)
- return firstStatus.priority < secondStatus.priority
- }
-
- return Array(sortedItems.prefix(currentUserId == roomOwnerId ? 1 : 2)) + sortedOthers
- }
-
- private func needSorting(_ videoItems: [UserInfo]) -> Bool {
- guard videoItems.count > 1 else { return false }
-
- if let firstUser = videoItems.first,
- firstUser.userRole != .roomOwner,
- videoItems.contains(where: { $0.userRole == .roomOwner}) {
- return true
- }
-
- if currentUserId != roomOwnerId {
- let currentUserExpectedPosition = 1
- if videoItems.count > currentUserExpectedPosition,
- videoItems[currentUserExpectedPosition].userId != currentUserId,
- videoItems.contains(where: { $0.userId == currentUserId }) {
- return true
- }
- }
-
- let startIndex = currentUserId == roomOwnerId ? 1 : 2
- guard videoItems.count > startIndex + 1 else { return false }
-
- let otherStreams = Array(videoItems[startIndex...])
- for i in 0..<(otherStreams.count - 1) {
- let current = otherStreams[i]
- let next = otherStreams[i + 1]
- let currentStreamState = StreamStatus(hasAudio: current.hasAudioStream, hasVideo: current.hasVideoStream)
- let nexdtStreamState = StreamStatus(hasAudio: next.hasAudioStream, hasVideo: next.hasVideoStream)
- if currentStreamState.priority > nexdtStreamState.priority {
- return true
- }
- }
-
- return false
- }
- }
- enum StreamStatus {
- case videoAndAudio
- case videoOnly
- case audioOnly
- case none
-
- init(hasAudio: Bool, hasVideo: Bool) {
- switch(hasAudio, hasVideo) {
- case(true, true): self = .videoAndAudio
- case(false, true): self = .videoOnly
- case(true, false): self = .audioOnly
- case(false, false): self = .none
- }
- }
-
- var priority: Int {
- switch self {
- case .videoAndAudio: return 0
- case .videoOnly: return 1
- case .audioOnly: return 2
- case .none: return 3
- }
- }
- }
|