diff --git a/CHANGELOG.md b/CHANGELOG.md index d89fe0505..cbcf8b770 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### 🔄 Changed - Factory method for creating `LocalParticipantViewModifier` +- `availableSize` has been replaced by `availableFrame` in most Views. # [0.3.0](https://github.com/GetStream/stream-video-swift/releases/tag/0.3.0) _August 25, 2023_ diff --git a/DemoApp/Sources/Components/DemoAppViewFactory.swift b/DemoApp/Sources/Components/DemoAppViewFactory.swift index 58c107d50..25f87a4de 100644 --- a/DemoApp/Sources/Components/DemoAppViewFactory.swift +++ b/DemoApp/Sources/Components/DemoAppViewFactory.swift @@ -64,14 +64,14 @@ final class DemoAppViewFactory: ViewFactory { func makeVideoCallParticipantModifier( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) -> some ViewModifier { DemoVideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: showAllInfo ) diff --git a/DemoApp/Sources/Examples/Examples.swift b/DemoApp/Sources/Examples/Examples.swift index 461e960ad..6e5b400ad 100644 --- a/DemoApp/Sources/Examples/Examples.swift +++ b/DemoApp/Sources/Examples/Examples.swift @@ -73,7 +73,7 @@ struct CustomVideoCallParticipantView: View { let participant: CallParticipant var id: String - var availableSize: CGSize + var availableFrame: CGRect var contentMode: UIView.ContentMode var edgesIgnoringSafeArea: Edge.Set var onViewUpdate: (CallParticipant, VideoRenderer) -> Void @@ -81,14 +81,14 @@ struct CustomVideoCallParticipantView: View { public init( participant: CallParticipant, id: String? = nil, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, edgesIgnoringSafeArea: Edge.Set = .all, onViewUpdate: @escaping (CallParticipant, VideoRenderer) -> Void ) { self.participant = participant self.id = id ?? participant.id - self.availableSize = availableSize + self.availableFrame = availableFrame self.contentMode = contentMode self.edgesIgnoringSafeArea = edgesIgnoringSafeArea self.onViewUpdate = onViewUpdate @@ -97,7 +97,7 @@ struct CustomVideoCallParticipantView: View { public var body: some View { VideoRendererView( id: id, - size: availableSize, + size: availableFrame.size, contentMode: contentMode ) { view in onViewUpdate(participant, view) @@ -113,7 +113,7 @@ struct CustomVideoCallParticipantView: View { startPoint: .top, endPoint: .bottom ) - .frame(width: availableSize.width) + .frame(width: availableFrame.width) .opacity(showVideo ? 0 : 1) ZStack { @@ -142,26 +142,26 @@ struct CustomParticipantModifier: ViewModifier { var participant: CallParticipant @Binding var pinnedParticipant: CallParticipant? var participantCount: Int - var availableSize: CGSize + var availableFrame: CGRect var ratio: CGFloat public init( participant: CallParticipant, pinnedParticipant: Binding, participantCount: Int, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat ) { self.participant = participant _pinnedParticipant = pinnedParticipant self.participantCount = participantCount - self.availableSize = availableSize + self.availableFrame = availableFrame self.ratio = ratio } public func body(content: Content) -> some View { content - .adjustVideoFrame(to: availableSize.width, ratio: ratio) + .adjustVideoFrame(to: availableFrame.width, ratio: ratio) .overlay( ZStack { VStack { diff --git a/DemoApp/Sources/Views/VideoCallParticipantModifier/DemoVideoCallParticipantModifier.swift b/DemoApp/Sources/Views/VideoCallParticipantModifier/DemoVideoCallParticipantModifier.swift index 8fe80f986..ba513a8a2 100644 --- a/DemoApp/Sources/Views/VideoCallParticipantModifier/DemoVideoCallParticipantModifier.swift +++ b/DemoApp/Sources/Views/VideoCallParticipantModifier/DemoVideoCallParticipantModifier.swift @@ -14,27 +14,27 @@ struct DemoVideoCallParticipantModifier: ViewModifier { var participant: CallParticipant var call: Call? - var availableSize: CGSize + var availableFrame: CGRect var ratio: CGFloat var showAllInfo: Bool init( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) { self.participant = participant self.call = call - self.availableSize = availableSize + self.availableFrame = availableFrame self.ratio = ratio self.showAllInfo = showAllInfo } func body(content: Content) -> some View { content - .adjustVideoFrame(to: availableSize.width, ratio: ratio) + .adjustVideoFrame(to: availableFrame.size.width, ratio: ratio) .overlay( ZStack { BottomView(content: { @@ -83,7 +83,7 @@ struct DemoVideoCallParticipantModifier: ViewModifier { } } ) - .modifier(ReactionsViewModifier(participant: participant, availableSize: availableSize)) + .modifier(ReactionsViewModifier(participant: participant, availableSize: availableFrame.size)) .onTapGesture(count: 2, perform: { popoverShown = true }) diff --git a/Sources/StreamVideo/WebRTC/StreamVideoCaptureHandler.swift b/Sources/StreamVideo/WebRTC/StreamVideoCaptureHandler.swift index d83b6aab0..7731a5efb 100644 --- a/Sources/StreamVideo/WebRTC/StreamVideoCaptureHandler.swift +++ b/Sources/StreamVideo/WebRTC/StreamVideoCaptureHandler.swift @@ -3,10 +3,10 @@ // import Foundation -import WebRTC +@preconcurrency import WebRTC + +final class StreamVideoCaptureHandler: NSObject, RTCVideoCapturerDelegate { -class StreamVideoCaptureHandler: NSObject, RTCVideoCapturerDelegate { - let source: RTCVideoSource let filters: [VideoFilter] let context: CIContext @@ -107,3 +107,5 @@ class StreamVideoCaptureHandler: NSObject, RTCVideoCapturerDelegate { ) } } + +extension StreamVideoCaptureHandler: @unchecked Sendable {} diff --git a/Sources/StreamVideoSwiftUI/CallView/CallView.swift b/Sources/StreamVideoSwiftUI/CallView/CallView.swift index 0235e6cdd..9c4215722 100644 --- a/Sources/StreamVideoSwiftUI/CallView/CallView.swift +++ b/Sources/StreamVideoSwiftUI/CallView/CallView.swift @@ -36,10 +36,10 @@ public struct CallView: View { viewFactory.makeScreenSharingView( viewModel: viewModel, screensharingSession: screenSharingSession, - availableSize: videoFeedProxy.size + availableFrame: videoFeedProxy.frame(in: .global) ) } else { - participantsView(size: videoFeedProxy.size) + participantsView(bounds: videoFeedProxy.frame(in: .global)) } } @@ -53,7 +53,7 @@ public struct CallView: View { if (viewModel.call?.state.screenSharingSession == nil || viewModel.call?.state.isCurrentUserScreensharing == true), viewModel.participantsLayout == .grid, viewModel.participants.count <= 3 { CornerDragableView( - content: contentDragableView(size: reader.size), + content: contentDragableView(bounds: reader.frame(in: .global)), proxy: reader ) { withAnimation { @@ -90,7 +90,7 @@ public struct CallView: View { if viewModel.participantsShown { viewFactory.makeParticipantsListView( viewModel: viewModel, - availableSize: reader.size + availableFrame: reader.frame(in: .global) ) .opacity(viewModel.hideUIElements ? 0 : 1) .accessibility(identifier: "trailingTopView") @@ -108,22 +108,22 @@ public struct CallView: View { } @ViewBuilder - private func contentDragableView(size: CGSize) -> some View { + private func contentDragableView(bounds: CGRect) -> some View { if !viewModel.localVideoPrimary { localVideoView .cornerRadius(16) .padding(.horizontal) } else { - minimizedView(size: size) + minimizedView(bounds: bounds) } } - private func minimizedView(size: CGSize) -> some View { + private func minimizedView(bounds: CGRect) -> some View { Group { if !viewModel.participants.isEmpty { VideoCallParticipantView( participant: viewModel.participants[0], - availableSize: size, + availableFrame: bounds, contentMode: .scaleAspectFill, customData: [:], call: viewModel.call @@ -155,11 +155,10 @@ public struct CallView: View { } } - private func participantsView(size: CGSize) -> some View { + private func participantsView(bounds: CGRect) -> some View { viewFactory.makeVideoParticipantsView( viewModel: viewModel, - availableSize: size, - onViewRendering: handleViewRendering(_:participant:), + availableFrame: bounds, onChangeTrackVisibility: viewModel.changeTrackVisibility(for:isVisible:) ) } @@ -167,10 +166,4 @@ public struct CallView: View { private var participants: [CallParticipant] { viewModel.participants } - - private func handleViewRendering(_ view: VideoRenderer, participant: CallParticipant) { - view.handleViewRendering(for: participant) { size, participant in - viewModel.updateTrackSize(size, for: participant) - } - } } diff --git a/Sources/StreamVideoSwiftUI/CallView/MinimizedCallView.swift b/Sources/StreamVideoSwiftUI/CallView/MinimizedCallView.swift index d7e8cb5f2..d3be18f82 100644 --- a/Sources/StreamVideoSwiftUI/CallView/MinimizedCallView.swift +++ b/Sources/StreamVideoSwiftUI/CallView/MinimizedCallView.swift @@ -33,7 +33,7 @@ public struct MinimizedCallView: View { if !viewModel.participants.isEmpty { VideoCallParticipantView( participant: viewModel.participants[0], - availableSize: proxy.size, + availableFrame: proxy.frame(in: .global), contentMode: .scaleAspectFill, customData: [:], call: viewModel.call diff --git a/Sources/StreamVideoSwiftUI/CallView/Participants/CallParticipantsInfoView.swift b/Sources/StreamVideoSwiftUI/CallView/Participants/CallParticipantsInfoView.swift index 460270bb9..666193a95 100644 --- a/Sources/StreamVideoSwiftUI/CallView/Participants/CallParticipantsInfoView.swift +++ b/Sources/StreamVideoSwiftUI/CallView/Participants/CallParticipantsInfoView.swift @@ -13,11 +13,11 @@ public struct CallParticipantsInfoView: View { @StateObject var viewModel: CallParticipantsInfoViewModel @ObservedObject var callViewModel: CallViewModel - var availableSize: CGSize - - public init(callViewModel: CallViewModel, availableSize: CGSize) { + var availableFrame: CGRect + + public init(callViewModel: CallViewModel, availableFrame: CGRect) { self.callViewModel = callViewModel - self.availableSize = availableSize + self.availableFrame = availableFrame _viewModel = StateObject( wrappedValue: CallParticipantsInfoViewModel( call: callViewModel.call @@ -30,7 +30,7 @@ public struct CallParticipantsInfoView: View { CallParticipantsView( viewModel: viewModel, callViewModel: callViewModel, - maxHeight: availableSize.height - padding + maxHeight: availableFrame.size.height - padding ) .padding() .padding(.vertical, padding / 2) diff --git a/Sources/StreamVideoSwiftUI/CallView/ParticipantsFullScreenLayout.swift b/Sources/StreamVideoSwiftUI/CallView/ParticipantsFullScreenLayout.swift index c7f451d33..49ceab068 100644 --- a/Sources/StreamVideoSwiftUI/CallView/ParticipantsFullScreenLayout.swift +++ b/Sources/StreamVideoSwiftUI/CallView/ParticipantsFullScreenLayout.swift @@ -11,20 +11,20 @@ public struct ParticipantsFullScreenLayout: View { var viewFactory: Factory var participant: CallParticipant var call: Call? - var size: CGSize + var frame: CGRect var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void public init( viewFactory: Factory, participant: CallParticipant, call: Call?, - size: CGSize, + frame: CGRect, onChangeTrackVisibility: @escaping @MainActor (CallParticipant, Bool) -> Void ) { self.viewFactory = viewFactory self.participant = participant self.call = call - self.size = size + self.frame = frame self.onChangeTrackVisibility = onChangeTrackVisibility } @@ -32,7 +32,7 @@ public struct ParticipantsFullScreenLayout: View { viewFactory.makeVideoParticipantView( participant: participant, id: participant.id, - availableSize: size, + availableFrame: frame, contentMode: .scaleAspectFit, customData: [:], call: call @@ -41,7 +41,7 @@ public struct ParticipantsFullScreenLayout: View { viewFactory.makeVideoCallParticipantModifier( participant: participant, call: call, - availableSize: size, + availableFrame: frame, ratio: ratio, showAllInfo: true ) @@ -57,7 +57,7 @@ public struct ParticipantsFullScreenLayout: View { } private var ratio: CGFloat { - size.width / size.height + frame.size.width / frame.size.height } } diff --git a/Sources/StreamVideoSwiftUI/CallView/ParticipantsGridLayout.swift b/Sources/StreamVideoSwiftUI/CallView/ParticipantsGridLayout.swift index 45c287c18..971aa56a8 100644 --- a/Sources/StreamVideoSwiftUI/CallView/ParticipantsGridLayout.swift +++ b/Sources/StreamVideoSwiftUI/CallView/ParticipantsGridLayout.swift @@ -11,7 +11,7 @@ public struct ParticipantsGridLayout: View { var viewFactory: Factory var call: Call? var participants: [CallParticipant] - var availableSize: CGSize + var availableFrame: CGRect var orientation: UIInterfaceOrientation var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void @@ -19,13 +19,13 @@ public struct ParticipantsGridLayout: View { viewFactory: Factory, call: Call?, participants: [CallParticipant], - availableSize: CGSize, + availableFrame: CGRect, orientation: UIInterfaceOrientation, onChangeTrackVisibility: @escaping @MainActor(CallParticipant, Bool) -> Void ) { self.viewFactory = viewFactory self.participants = participants - self.availableSize = availableSize + self.availableFrame = availableFrame self.onChangeTrackVisibility = onChangeTrackVisibility self.orientation = orientation self.call = call @@ -38,7 +38,7 @@ public struct ParticipantsGridLayout: View { viewFactory: viewFactory, call: call, participants: participants, - availableSize: availableSize, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } else { @@ -46,7 +46,7 @@ public struct ParticipantsGridLayout: View { viewFactory: viewFactory, call: call, participants: participants, - availableSize: availableSize, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } @@ -60,7 +60,7 @@ struct VideoParticipantsViewPortrait: View { var viewFactory: Factory var call: Call? var participants: [CallParticipant] - var availableSize: CGSize + var availableFrame: CGRect var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void var body: some View { @@ -70,7 +70,7 @@ struct VideoParticipantsViewPortrait: View { viewFactory: viewFactory, call: call, participants: participants, - availableSize: availableSize, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } else if participants.count == 4 { @@ -79,7 +79,7 @@ struct VideoParticipantsViewPortrait: View { call: call, leftColumnParticipants: [participants[0], participants[2]], rightColumnParticipants: [participants[1], participants[3]], - availableSize: availableSize, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } else if participants.count == 5 { @@ -88,7 +88,7 @@ struct VideoParticipantsViewPortrait: View { call: call, leftColumnParticipants: [participants[0], participants[2]], rightColumnParticipants: [participants[1], participants[3], participants[4]], - availableSize: availableSize, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } else { @@ -96,7 +96,7 @@ struct VideoParticipantsViewPortrait: View { viewFactory: viewFactory, call: call, participants: participants, - availableSize: availableSize, + availableFrame: availableFrame, isPortrait: true, participantVisibilityChanged: { participant, isVisible in onChangeTrackVisibility(participant, isVisible) @@ -112,7 +112,7 @@ struct VideoParticipantsViewLandscape: View { var viewFactory: Factory var call: Call? var participants: [CallParticipant] - var availableSize: CGSize + var availableFrame: CGRect var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void var body: some View { @@ -122,7 +122,7 @@ struct VideoParticipantsViewLandscape: View { viewFactory: viewFactory, call: call, participants: participants, - availableSize: availableSize, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } else if participants.count == 4 { @@ -131,7 +131,7 @@ struct VideoParticipantsViewLandscape: View { call: call, firstRowParticipants: [participants[0], participants[1]], secondRowParticipants: [participants[2], participants[3]], - availableSize: availableSize, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } else if participants.count == 5 { @@ -140,7 +140,7 @@ struct VideoParticipantsViewLandscape: View { call: call, firstRowParticipants: [participants[0], participants[1]], secondRowParticipants: [participants[2], participants[3], participants[4]], - availableSize: availableSize, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } else { @@ -148,7 +148,7 @@ struct VideoParticipantsViewLandscape: View { viewFactory: viewFactory, call: call, participants: participants, - availableSize: availableSize, + availableFrame: availableFrame, isPortrait: false, participantVisibilityChanged: { participant, isVisible in onChangeTrackVisibility(participant, isVisible) @@ -167,7 +167,7 @@ struct TwoColumnParticipantsView: View { var call: Call? var leftColumnParticipants: [CallParticipant] var rightColumnParticipants: [CallParticipant] - var availableSize: CGSize + var availableFrame: CGRect var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void var body: some View { @@ -176,26 +176,29 @@ struct TwoColumnParticipantsView: View { viewFactory: viewFactory, call: call, participants: leftColumnParticipants, - availableSize: size, + availableFrame: bounds, onChangeTrackVisibility: onChangeTrackVisibility ) - .adjustVideoFrame(to: size.width) - + .adjustVideoFrame(to: bounds.size.width) + VerticalParticipantsView( viewFactory: viewFactory, call: call, participants: rightColumnParticipants, - availableSize: size, + availableFrame: bounds, onChangeTrackVisibility: onChangeTrackVisibility ) - .adjustVideoFrame(to: size.width) + .adjustVideoFrame(to: bounds.size.width) } - .frame(maxWidth: availableSize.width, maxHeight: .infinity) + .frame(maxWidth: availableFrame.size.width, maxHeight: .infinity) .edgesIgnoringSafeArea(.all) } - private var size: CGSize { - CGSize(width: availableSize.width / 2, height: availableSize.height) + private var bounds: CGRect { + CGRect( + origin: .zero, + size: CGSize(width: availableFrame.size.width / 2, height: availableFrame.size.height) + ) } } @@ -207,7 +210,7 @@ struct TwoRowParticipantsView: View { var call: Call? var firstRowParticipants: [CallParticipant] var secondRowParticipants: [CallParticipant] - var availableSize: CGSize + var availableFrame: CGRect var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void var body: some View { @@ -216,7 +219,7 @@ struct TwoRowParticipantsView: View { viewFactory: viewFactory, call: call, participants: firstRowParticipants, - availableSize: size, + availableFrame: bounds, onChangeTrackVisibility: onChangeTrackVisibility ) @@ -224,16 +227,19 @@ struct TwoRowParticipantsView: View { viewFactory: viewFactory, call: call, participants: secondRowParticipants, - availableSize: size, + availableFrame: bounds, onChangeTrackVisibility: onChangeTrackVisibility ) } - .frame(maxWidth: availableSize.width, maxHeight: .infinity) + .frame(maxWidth: availableFrame.width, maxHeight: .infinity) .edgesIgnoringSafeArea(.all) } - private var size: CGSize { - CGSize(width: availableSize.width, height: availableSize.height / 2) + private var bounds: CGRect { + .init( + origin: .zero, + size: CGSize(width: availableFrame.width, height: availableFrame.height / 2) + ) } } @@ -242,7 +248,7 @@ struct VerticalParticipantsView: View { var viewFactory: Factory var call: Call? var participants: [CallParticipant] - var availableSize: CGSize + var availableFrame: CGRect var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void var body: some View { @@ -251,7 +257,7 @@ struct VerticalParticipantsView: View { viewFactory.makeVideoParticipantView( participant: participant, id: participant.id, - availableSize: availableSize, + availableFrame: availableFrame, contentMode: .scaleAspectFill, customData: [:], call: call @@ -260,7 +266,7 @@ struct VerticalParticipantsView: View { viewFactory.makeVideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: true ) @@ -273,11 +279,11 @@ struct VerticalParticipantsView: View { } private var ratio: CGFloat { - availableSize.width / availableHeight + availableFrame.width / availableHeight } private var availableHeight: CGFloat { - availableSize.height / CGFloat(participants.count) + availableFrame.height / CGFloat(participants.count) } } @@ -287,7 +293,7 @@ struct HorizontalParticipantsView: View { var viewFactory: Factory var call: Call? var participants: [CallParticipant] - var availableSize: CGSize + var availableFrame: CGRect var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void var body: some View { @@ -296,7 +302,7 @@ struct HorizontalParticipantsView: View { viewFactory.makeVideoParticipantView( participant: participant, id: participant.id, - availableSize: size, + availableFrame: bounds, contentMode: .scaleAspectFill, customData: [:], call: call @@ -305,7 +311,7 @@ struct HorizontalParticipantsView: View { viewFactory.makeVideoCallParticipantModifier( participant: participant, call: call, - availableSize: size, + availableFrame: bounds, ratio: ratio, showAllInfo: true ) @@ -317,15 +323,18 @@ struct HorizontalParticipantsView: View { } } - private var size: CGSize { - CGSize(width: availableWidth, height: availableSize.height) + private var bounds: CGRect { + .init( + origin: .zero, + size: CGSize(width: availableWidth, height: availableFrame.height) + ) } private var ratio: CGFloat { - availableWidth / availableSize.height + availableWidth / availableFrame.height } private var availableWidth: CGFloat { - availableSize.width / CGFloat(participants.count) + availableFrame.width / CGFloat(participants.count) } } diff --git a/Sources/StreamVideoSwiftUI/CallView/ParticipantsGridView.swift b/Sources/StreamVideoSwiftUI/CallView/ParticipantsGridView.swift index e588c376c..5913b8121 100644 --- a/Sources/StreamVideoSwiftUI/CallView/ParticipantsGridView.swift +++ b/Sources/StreamVideoSwiftUI/CallView/ParticipantsGridView.swift @@ -8,14 +8,14 @@ import WebRTC @MainActor struct ParticipantsGridView: View { - + var viewFactory: Factory var call: Call? var participants: [CallParticipant] - var availableSize: CGSize + var availableFrame: CGRect var isPortrait: Bool var participantVisibilityChanged: (CallParticipant, Bool) -> Void - + var body: some View { ScrollView { if #available(iOS 14.0, *) { @@ -25,25 +25,26 @@ struct ParticipantsGridView: View { ], spacing: 0 ) { - participantsContent + participantsContent(availableFrame) } - .frame(width: availableSize.width) + .frame(width: availableFrame.width) } else { VStack { - participantsContent + participantsContent(availableFrame) } } } .edgesIgnoringSafeArea(.all) .accessibility(identifier: "gridScrollView") } - - private var participantsContent: some View { + + @ViewBuilder + private func participantsContent(_ bounds: CGRect) -> some View { ForEach(participants) { participant in viewFactory.makeVideoParticipantView( participant: participant, id: participant.id, - availableSize: size, + availableFrame: .init(origin: .zero, size: size), contentMode: .scaleAspectFill, customData: [:], call: call @@ -52,41 +53,37 @@ struct ParticipantsGridView: View { viewFactory.makeVideoCallParticipantModifier( participant: participant, call: call, - availableSize: size, + availableFrame: .init(origin: .zero, size: size), ratio: ratio, showAllInfo: true ) ) - .onAppear { - log.debug("Participant \(participant.name) is visible") - participantVisibilityChanged(participant, true) - } - .onDisappear { - log.debug("Participant \(participant.name) is not visible") - participantVisibilityChanged(participant, false) + .visibilityObservation(in: bounds) { + log.debug("Participant \(participant.name) is \($0 ? "visible" : "not visible.")") + participantVisibilityChanged(participant, $0) } } } - + var ratio: CGFloat { if isPortrait { - let width = availableSize.width / 2 - let height = availableSize.height / 3 + let width = availableFrame.width / 2 + let height = availableFrame.height / 3 return width / height } else { - let width = availableSize.width / 3 - let height = availableSize.height / 2 + let width = availableFrame.width / 3 + let height = availableFrame.height / 2 return width / height } } - + private var size: CGSize { if #available(iOS 14.0, *) { let dividerWidth: CGFloat = isPortrait ? 2 : 3 let dividerHeight: CGFloat = isPortrait ? 3 : 2 - return CGSize(width: availableSize.width / dividerWidth, height: availableSize.height / dividerHeight) + return CGSize(width: availableFrame.width / dividerWidth, height: availableFrame.height / dividerHeight) } else { - return CGSize(width: availableSize.width, height: availableSize.height / 2) + return CGSize(width: availableFrame.width, height: availableFrame.height / 2) } } } diff --git a/Sources/StreamVideoSwiftUI/CallView/ParticipantsSpotlightLayout.swift b/Sources/StreamVideoSwiftUI/CallView/ParticipantsSpotlightLayout.swift index 79a5e1d7d..9abfff664 100644 --- a/Sources/StreamVideoSwiftUI/CallView/ParticipantsSpotlightLayout.swift +++ b/Sources/StreamVideoSwiftUI/CallView/ParticipantsSpotlightLayout.swift @@ -13,7 +13,7 @@ public struct ParticipantsSpotlightLayout: View { var viewFactory: Factory var participant: CallParticipant var participants: [CallParticipant] - var size: CGSize + var frame: CGRect var call: Call? var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void @@ -22,13 +22,13 @@ public struct ParticipantsSpotlightLayout: View { participant: CallParticipant, call: Call?, participants: [CallParticipant], - size: CGSize, + frame: CGRect, onChangeTrackVisibility: @escaping @MainActor (CallParticipant, Bool) -> Void ) { self.viewFactory = viewFactory self.participant = participant self.participants = participants - self.size = size + self.frame = frame self.call = call self.onChangeTrackVisibility = onChangeTrackVisibility } @@ -39,7 +39,7 @@ public struct ParticipantsSpotlightLayout: View { viewFactory.makeVideoParticipantView( participant: participant, id: "\(participant.id)-spotlight", - availableSize: .init(width: thumbnailSize, height: thumbnailSize), + availableFrame: .init(origin: .zero, size: .init(width: thumbnailSize, height: thumbnailSize)), contentMode: .scaleAspectFill, customData: [:], call: call @@ -48,15 +48,11 @@ public struct ParticipantsSpotlightLayout: View { viewFactory.makeVideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: true ) ) - .onAppear { - log.debug("Participant \(participant.name) is visible") - onChangeTrackVisibility(participant, true) - } .modifier(ParticipantChangeModifier( participant: participant, onChangeTrackVisibility: onChangeTrackVisibility) @@ -68,17 +64,12 @@ public struct ParticipantsSpotlightLayout: View { viewFactory.makeVideoParticipantView( participant: participant, id: participant.id, - availableSize: .init(width: thumbnailSize, height: thumbnailSize), + availableFrame: .init(origin: .zero, size: .init(width: thumbnailSize, height: thumbnailSize)), contentMode: .scaleAspectFill, customData: [:], call: call ) - .onAppear { - onChangeTrackVisibility(participant, true) - } - .onDisappear { - onChangeTrackVisibility(participant, false) - } + .visibilityObservation(in: availableFrame) { onChangeTrackVisibility(participant, $0) } .adjustVideoFrame(to: thumbnailSize, ratio: 1) .cornerRadius(8) .accessibility(identifier: "spotlightParticipantView") @@ -94,11 +85,14 @@ public struct ParticipantsSpotlightLayout: View { } - private var availableSize: CGSize { - CGSize(width: size.width, height: size.height - thumbnailSize - 64) + private var availableFrame: CGRect { + .init( + origin: frame.origin, + size: CGSize(width: frame.size.width, height: frame.size.height - thumbnailSize - 64) + ) } private var ratio: CGFloat { - availableSize.width / availableSize.height + availableFrame.size.width / availableFrame.size.height } } diff --git a/Sources/StreamVideoSwiftUI/CallView/ScreenSharing/ScreenSharingView.swift b/Sources/StreamVideoSwiftUI/CallView/ScreenSharing/ScreenSharingView.swift index 6b589b467..d11ef1135 100644 --- a/Sources/StreamVideoSwiftUI/CallView/ScreenSharing/ScreenSharingView.swift +++ b/Sources/StreamVideoSwiftUI/CallView/ScreenSharing/ScreenSharingView.swift @@ -9,22 +9,22 @@ public struct ScreenSharingView: View { @ObservedObject var viewModel: CallViewModel var screenSharing: ScreenSharingSession - var availableSize: CGSize + var availableFrame: CGRect var viewFactory: Factory - private var thumbnailSize: CGSize { - CGSize(width: 120, height: 120) + private var thumbnailBounds: CGRect { + CGRect(x: 0, y: 0, width: 120, height: 120) } public init( viewModel: CallViewModel, screenSharing: ScreenSharingSession, - availableSize: CGSize, + availableFrame: CGRect, viewFactory: Factory = DefaultViewFactory.shared ) { self.viewModel = viewModel self.screenSharing = screenSharing - self.availableSize = availableSize + self.availableFrame = availableFrame self.viewFactory = viewFactory } @@ -53,7 +53,7 @@ public struct ScreenSharingView: View { viewFactory.makeVideoParticipantView( participant: participant, id: "\(participant.id)-screenshare-participant", - availableSize: thumbnailSize, + availableFrame: thumbnailBounds, contentMode: .scaleAspectFill, customData: [:], call: viewModel.call @@ -62,7 +62,7 @@ public struct ScreenSharingView: View { viewFactory.makeVideoCallParticipantModifier( participant: participant, call: viewModel.call, - availableSize: thumbnailSize, + availableFrame: thumbnailBounds, ratio: 1, showAllInfo: false ) @@ -77,7 +77,7 @@ public struct ScreenSharingView: View { } } } - .frame(height: thumbnailSize.height) + .frame(height: thumbnailBounds.size.height) .cornerRadius(8) } .padding() @@ -86,8 +86,8 @@ public struct ScreenSharingView: View { } } .frame( - width: viewModel.hideUIElements ? availableSize.width : nil, - height: viewModel.hideUIElements ? availableSize.height : nil + width: viewModel.hideUIElements ? availableFrame.size.width : nil, + height: viewModel.hideUIElements ? availableFrame.size.height : nil ) .background(Color.black) } @@ -111,9 +111,9 @@ public struct ScreenSharingView: View { private var videoSize: CGSize { if viewModel.hideUIElements { - return .init(width: availableSize.height, height: availableSize.width) + return .init(width: availableFrame.size.height, height: availableFrame.size.width) } else { - return availableSize + return availableFrame.size } } } diff --git a/Sources/StreamVideoSwiftUI/CallView/VideoParticipantsView.swift b/Sources/StreamVideoSwiftUI/CallView/VideoParticipantsView.swift index 9b4f52900..fcc728211 100644 --- a/Sources/StreamVideoSwiftUI/CallView/VideoParticipantsView.swift +++ b/Sources/StreamVideoSwiftUI/CallView/VideoParticipantsView.swift @@ -10,8 +10,7 @@ public struct VideoParticipantsView: View { var viewFactory: Factory @ObservedObject var viewModel: CallViewModel - var availableSize: CGSize - var onViewRendering: (VideoRenderer, CallParticipant) -> Void + var availableFrame: CGRect var onChangeTrackVisibility: @MainActor(CallParticipant, Bool) -> Void @State private var orientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? .unknown @@ -19,14 +18,12 @@ public struct VideoParticipantsView: View { public init( viewFactory: Factory, viewModel: CallViewModel, - availableSize: CGSize, - onViewRendering: @escaping (VideoRenderer, CallParticipant) -> Void, + availableFrame: CGRect, onChangeTrackVisibility: @escaping @MainActor(CallParticipant, Bool) -> Void ) { self.viewFactory = viewFactory self.viewModel = viewModel - self.availableSize = availableSize - self.onViewRendering = onViewRendering + self.availableFrame = availableFrame self.onChangeTrackVisibility = onChangeTrackVisibility } @@ -37,7 +34,7 @@ public struct VideoParticipantsView: View { viewFactory: viewFactory, participant: first, call: viewModel.call, - size: availableSize, + frame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } else if viewModel.participantsLayout == .spotlight, let first = viewModel.participants.first { @@ -46,7 +43,7 @@ public struct VideoParticipantsView: View { participant: first, call: viewModel.call, participants: Array(viewModel.participants.dropFirst()), - size: availableSize, + frame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } else { @@ -54,7 +51,7 @@ public struct VideoParticipantsView: View { viewFactory: viewFactory, call: viewModel.call, participants: viewModel.participants, - availableSize: availableSize, + availableFrame: availableFrame, orientation: orientation, onChangeTrackVisibility: onChangeTrackVisibility ) @@ -72,27 +69,27 @@ public struct VideoCallParticipantModifier: ViewModifier { var participant: CallParticipant var call: Call? - var availableSize: CGSize + var availableFrame: CGRect var ratio: CGFloat var showAllInfo: Bool public init( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) { self.participant = participant self.call = call - self.availableSize = availableSize + self.availableFrame = availableFrame self.ratio = ratio self.showAllInfo = showAllInfo } public func body(content: Content) -> some View { content - .adjustVideoFrame(to: availableSize.width, ratio: ratio) + .adjustVideoFrame(to: availableFrame.size.width, ratio: ratio) .overlay( ZStack { BottomView(content: { @@ -150,7 +147,7 @@ public struct VideoCallParticipantView: View { let participant: CallParticipant var id: String - var availableSize: CGSize + var availableFrame: CGRect var contentMode: UIView.ContentMode var edgesIgnoringSafeArea: Edge.Set var customData: [String: RawJSON] @@ -159,7 +156,7 @@ public struct VideoCallParticipantView: View { public init( participant: CallParticipant, id: String? = nil, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, edgesIgnoringSafeArea: Edge.Set = .all, customData: [String: RawJSON], @@ -167,7 +164,7 @@ public struct VideoCallParticipantView: View { ) { self.participant = participant self.id = id ?? participant.id - self.availableSize = availableSize + self.availableFrame = availableFrame self.contentMode = contentMode self.edgesIgnoringSafeArea = edgesIgnoringSafeArea self.customData = customData @@ -177,7 +174,7 @@ public struct VideoCallParticipantView: View { public var body: some View { VideoRendererView( id: id, - size: availableSize, + size: availableFrame.size, contentMode: contentMode, handleRendering: { [weak call] view in guard call != nil else { return } @@ -198,7 +195,7 @@ public struct VideoCallParticipantView: View { name: participant.name, imageURL: participant.profileImageURL ) - .frame(width: availableSize.width) + .frame(width: availableFrame.size.width) .opacity(showVideo ? 0 : 1) ) } diff --git a/Sources/StreamVideoSwiftUI/CallView/VideoRenderer.swift b/Sources/StreamVideoSwiftUI/CallView/VideoRenderer.swift index b0f727db7..745e13ae9 100644 --- a/Sources/StreamVideoSwiftUI/CallView/VideoRenderer.swift +++ b/Sources/StreamVideoSwiftUI/CallView/VideoRenderer.swift @@ -38,7 +38,7 @@ public struct LocalVideoView: View { viewFactory.makeVideoParticipantView( participant: participant, id: "\(streamVideo.user.id)-\(idSuffix)", - availableSize: reader.size, + availableFrame: reader.frame(in: .global), contentMode: .scaleAspectFill, customData: ["videoOn": .bool(callSettings.videoOn)], call: call diff --git a/Sources/StreamVideoSwiftUI/CallView/VisibilityThresholdModifier.swift b/Sources/StreamVideoSwiftUI/CallView/VisibilityThresholdModifier.swift new file mode 100644 index 000000000..0f7b5a223 --- /dev/null +++ b/Sources/StreamVideoSwiftUI/CallView/VisibilityThresholdModifier.swift @@ -0,0 +1,114 @@ +// +// Copyright © 2023 Stream.io Inc. All rights reserved. +// + +import StreamVideo +import SwiftUI + +/// The modifier designed to dynamically track and respond to the visibility status of a view within its parent +/// bounds or viewport. It utilises a user-defined visibility threshold, represented as a percentage, to +/// determine how much of the view should be visible (both vertically and horizontally) before it's considered +/// "on screen". +/// +/// When the visibility state of the view changes (i.e., it transitions between being "on screen" and "off screen"), +/// a callback is triggered to notify the user of this change. This can be particularly useful in scenarios where +/// resource management is crucial, such as video playback or dynamic content loading, where actions might +/// be triggered based on whether a view is currently visible to the user. +/// +/// By default, the threshold is set to 30%, meaning 30% of the view's dimensions must be within the parent's +/// bounds for it to be considered visible. +struct VisibilityThresholdModifier: ViewModifier { + /// State to track if the content view is on screen. + @State private var isOnScreen = false { + didSet { + // Check if the visibility state has changed. + guard isOnScreen != oldValue else { return } + // Notify the caller about the visibility state change. + changeHandler(isOnScreen) + } + } + + /// The bounds of the parent view or viewport. + var bounds: CGRect + /// The threshold percentage of the view that must be visible. + var threshold: CGFloat + /// Closure to handle visibility changes. + var changeHandler: (Bool) -> Void + + init(in bounds: CGRect, + threshold: CGFloat, + changeHandler: @escaping (Bool) -> Void + ) { + self.bounds = bounds + self.threshold = threshold + self.changeHandler = changeHandler + } + + func body(content: Content) -> some View { + content + .background( + GeometryReader { geometry -> Color in + /// Convert the local frame of the content to a global frame. + let geometryInGlobal = geometry.frame(in: .global) + + let (verticalVisible, horizontalVisible) = calculateVisibilityInBothAxis(in: geometryInGlobal) + + /// Update the isOnScreen state based on visibility calculations. + DispatchQueue.main.async { + self.isOnScreen = verticalVisible && horizontalVisible + } + + /// Use a clear color for the background to not affect the appearance. + return Color.clear + } + ) + } + + func calculateVisibilityInBothAxis(in rect: CGRect) -> (verticalVisible: Bool, horizontalVisible: Bool) { + /// Calculate the global minY, maxY, minX, and maxX of the content view. + let minY = rect.minY + let maxY = rect.maxY + let minX = rect.minX + let maxX = rect.maxX + + /// Calculate required height and width based on visibility threshold. + let requiredHeight = rect.size.height * threshold + let requiredWidth = rect.size.width * threshold + + /// Check if the content view is vertically within the parent's bounds. + let verticalVisible = (minY + requiredHeight < bounds.maxY && minY > bounds.minY) || + (maxY - requiredHeight > bounds.minY && maxY < bounds.maxY) + /// Check if the content view is horizontally within the parent's bounds. + let horizontalVisible = (minX + requiredWidth < bounds.maxX && minX > bounds.minX) || + (maxX - requiredWidth > bounds.minX && maxX < bounds.maxX) + + return (verticalVisible, horizontalVisible) + } +} + +extension View { + /// Attaches a visibility observation modifier to the view. + /// + /// - Parameters: + /// - bounds: The bounds of the parent view or viewport within which the visibility of the view will + /// be tracked. + /// - threshold: A percentage value (defaulted to 0.3 or 30%) representing how much of the view + /// should be visible within the `bounds` before it's considered "on screen". + /// - changeHandler: A closure that gets triggered with a Boolean value indicating the visibility + /// state of the view whenever it changes. + /// + /// - Returns: A modified view that observes its visibility status within the specified bounds. + func visibilityObservation( + in bounds: CGRect, + threshold: CGFloat = 0.3, + changeHandler: @escaping (Bool) -> Void + ) -> some View { + modifier( + VisibilityThresholdModifier( + in: bounds, + threshold: threshold, + changeHandler: changeHandler + ) + ) + } +} diff --git a/Sources/StreamVideoSwiftUI/Livestreaming/LivestreamPlayer.swift b/Sources/StreamVideoSwiftUI/Livestreaming/LivestreamPlayer.swift index 9a1dbf727..05110f3b8 100644 --- a/Sources/StreamVideoSwiftUI/Livestreaming/LivestreamPlayer.swift +++ b/Sources/StreamVideoSwiftUI/Livestreaming/LivestreamPlayer.swift @@ -47,7 +47,7 @@ public struct LivestreamPlayer: View { if let participant = state.participants.first { VideoCallParticipantView( participant: participant, - availableSize: reader.size, + availableFrame: reader.frame(in: .global), contentMode: .scaleAspectFit, customData: [:], call: viewModel.call diff --git a/Sources/StreamVideoSwiftUI/ViewFactory.swift b/Sources/StreamVideoSwiftUI/ViewFactory.swift index 99b178079..3b099b679 100644 --- a/Sources/StreamVideoSwiftUI/ViewFactory.swift +++ b/Sources/StreamVideoSwiftUI/ViewFactory.swift @@ -42,14 +42,12 @@ public protocol ViewFactory: AnyObject { /// Creates the video participants view, shown during a call. /// - Parameters: /// - viewModel: The view model used for the call. - /// - availableSize: the size available for rendering. - /// - onViewRendering: called when the video view is rendered. + /// - availableFrame: the frame available for rendering. /// - onChangeTrackVisibility: called when a track changes its visibility. /// - Returns: view shown in the video participants slot. func makeVideoParticipantsView( viewModel: CallViewModel, - availableSize: CGSize, - onViewRendering: @escaping (VideoRenderer, CallParticipant) -> Void, + availableFrame: CGRect, onChangeTrackVisibility: @escaping @MainActor(CallParticipant, Bool) -> Void ) -> ParticipantsViewType @@ -58,7 +56,7 @@ public protocol ViewFactory: AnyObject { /// - Parameters: /// - participant: The participant to display. /// - id: id of the participant. - /// - availableSize: The available size for the participant's video view. + /// - availableFrame: The available frame for the participant's video view. /// - contentMode: The content mode for the participant's video view. /// - customData: Any custom data passed to the view. /// - onViewUpdate: A closure to be called whenever the participant's video view is updated. @@ -66,7 +64,7 @@ public protocol ViewFactory: AnyObject { func makeVideoParticipantView( participant: CallParticipant, id: String, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, customData: [String: RawJSON], call: Call? @@ -78,13 +76,13 @@ public protocol ViewFactory: AnyObject { /// - participant: The participant to modify. /// - participantCount: The total number of participants in the call. /// - pinnedParticipant: A binding to the participant that is currently pinned in the call. - /// - availableSize: The available size for the participant's video. + /// - availableFrame: The available frame for the participant's video. /// - ratio: The aspect ratio of the participant's video. /// - Returns: A view modifier that modifies the appearance of the video call participant. func makeVideoCallParticipantModifier( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) -> ParticipantViewModifierType @@ -105,11 +103,11 @@ public protocol ViewFactory: AnyObject { /// Creates a view that shows a list of the participants in the call. /// - Parameters: /// - viewModel: The view model used for the call. - /// - availableSize: The size available to display the view. + /// - availableFrame: The frame available to display the view. /// - Returns: view shown in the participants list slot. func makeParticipantsListView( viewModel: CallViewModel, - availableSize: CGSize + availableFrame: CGRect ) -> CallParticipantsListViewType associatedtype ScreenSharingViewType: View @@ -117,12 +115,12 @@ public protocol ViewFactory: AnyObject { /// - Parameters: /// - viewModel: The view model used for the call. /// - screensharingSession: The current screensharing session. - /// - availableSize: The size available to display the view. + /// - availableFrame: The frame available to display the view. /// - Returns: view shown in the screensharing slot. func makeScreenSharingView( viewModel: CallViewModel, screensharingSession: ScreenSharingSession, - availableSize: CGSize + availableFrame: CGRect ) -> ScreenSharingViewType associatedtype LobbyViewType: View @@ -194,15 +192,13 @@ extension ViewFactory { public func makeVideoParticipantsView( viewModel: CallViewModel, - availableSize: CGSize, - onViewRendering: @escaping (VideoRenderer, CallParticipant) -> Void, + availableFrame: CGRect, onChangeTrackVisibility: @escaping @MainActor(CallParticipant, Bool) -> Void ) -> some View { VideoParticipantsView( viewFactory: self, viewModel: viewModel, - availableSize: availableSize, - onViewRendering: onViewRendering, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } @@ -210,7 +206,7 @@ extension ViewFactory { public func makeVideoParticipantView( participant: CallParticipant, id: String, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, customData: [String: RawJSON], call: Call? @@ -218,7 +214,7 @@ extension ViewFactory { VideoCallParticipantView( participant: participant, id: id, - availableSize: availableSize, + availableFrame: availableFrame, contentMode: contentMode, customData: customData, call: call @@ -228,14 +224,14 @@ extension ViewFactory { public func makeVideoCallParticipantModifier( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) -> some ViewModifier { VideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: showAllInfo ) @@ -251,10 +247,10 @@ extension ViewFactory { public func makeParticipantsListView( viewModel: CallViewModel, - availableSize: CGSize + availableFrame: CGRect ) -> some View { if #available(iOS 14.0, *) { - return CallParticipantsInfoView(callViewModel: viewModel, availableSize: availableSize) + return CallParticipantsInfoView(callViewModel: viewModel, availableFrame: availableFrame) } else { return EmptyView() } @@ -263,12 +259,12 @@ extension ViewFactory { public func makeScreenSharingView( viewModel: CallViewModel, screensharingSession: ScreenSharingSession, - availableSize: CGSize + availableFrame: CGRect ) -> some View { ScreenSharingView( viewModel: viewModel, screenSharing: screensharingSession, - availableSize: availableSize + availableFrame: availableFrame ) } @@ -333,7 +329,7 @@ extension ViewFactory { } public class DefaultViewFactory: ViewFactory { - + private init() { /* Private init. */ } public static let shared = DefaultViewFactory() diff --git a/StreamVideo.xcodeproj/project.pbxproj b/StreamVideo.xcodeproj/project.pbxproj index 9d9d5695f..1ac2c6455 100644 --- a/StreamVideo.xcodeproj/project.pbxproj +++ b/StreamVideo.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 401A64B12A9DF83200534ED1 /* TokenResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A64B02A9DF83200534ED1 /* TokenResponse.swift */; }; 401A64B32A9DF86200534ED1 /* URL+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A64B22A9DF86200534ED1 /* URL+Convenience.swift */; }; 401A64B52A9DF88C00534ED1 /* String+Unique.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401A64B42A9DF88C00534ED1 /* String+Unique.swift */; }; + 401EDBAC2ACD646000520215 /* VisibilityThresholdModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401EDBAA2ACD5F1700520215 /* VisibilityThresholdModifier.swift */; }; 4029A6222AB068EC0065DAFB /* CallButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445DD2A9E22B9004BE3DA /* CallButtonView.swift */; }; 4029A6232AB068FC0065DAFB /* DemoControls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445EC2A9E2A24004BE3DA /* DemoControls.swift */; }; 4029A6242AB069100065DAFB /* DemoChatViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 402EE12F2AA8861B00312632 /* DemoChatViewModel.swift */; }; @@ -70,6 +71,7 @@ 406A8EB52AA1D91E001F598A /* JoinCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F445C12A9E1449004BE3DA /* JoinCallView.swift */; }; 406A8EB62AA1D922001F598A /* DebugMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4046DEF12A9F510C00CA6D2F /* DebugMenu.swift */; }; 406A8EB72AA1D92D001F598A /* ReadableContentGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 409BFA422A9F7BBB003341EF /* ReadableContentGuide.swift */; }; + 407D5D3D2ACEF0C500B5044E /* VisibilityThresholdModifier_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 407D5D3C2ACEF0C500B5044E /* VisibilityThresholdModifier_Tests.swift */; }; 407F29FF2AA6011500C3EAF8 /* MemoryLogViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4093861E2AA0A21800FF5AF4 /* MemoryLogViewer.swift */; }; 407F2A002AA6011B00C3EAF8 /* LogQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4093861B2AA0A11500FF5AF4 /* LogQueue.swift */; }; 4093861A2AA09E4A00FF5AF4 /* MemoryLogDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 409386192AA09E4A00FF5AF4 /* MemoryLogDestination.swift */; }; @@ -886,6 +888,7 @@ 401A64B02A9DF83200534ED1 /* TokenResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenResponse.swift; sourceTree = ""; }; 401A64B22A9DF86200534ED1 /* URL+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Convenience.swift"; sourceTree = ""; }; 401A64B42A9DF88C00534ED1 /* String+Unique.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Unique.swift"; sourceTree = ""; }; + 401EDBAA2ACD5F1700520215 /* VisibilityThresholdModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibilityThresholdModifier.swift; sourceTree = ""; }; 402EE12F2AA8861B00312632 /* DemoChatViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoChatViewModel.swift; sourceTree = ""; }; 4030E59F2A9DF5BD003E8CBA /* AppEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppEnvironment.swift; sourceTree = ""; }; 4030E5A12A9DF6B6003E8CBA /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; @@ -896,6 +899,7 @@ 4046DEEA2A9E38DC00CA6D2F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4046DEF12A9F510C00CA6D2F /* DebugMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugMenu.swift; sourceTree = ""; }; 4059C3412AAF0CE40006928E /* DemoChatViewModel+Injection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DemoChatViewModel+Injection.swift"; sourceTree = ""; }; + 407D5D3C2ACEF0C500B5044E /* VisibilityThresholdModifier_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibilityThresholdModifier_Tests.swift; sourceTree = ""; }; 409386192AA09E4A00FF5AF4 /* MemoryLogDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryLogDestination.swift; sourceTree = ""; }; 4093861B2AA0A11500FF5AF4 /* LogQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogQueue.swift; sourceTree = ""; }; 4093861E2AA0A21800FF5AF4 /* MemoryLogViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryLogViewer.swift; sourceTree = ""; }; @@ -2109,7 +2113,9 @@ 82FF40B62A17C6CD00B4D95E /* ReconnectionView_Tests.swift */, 82FF40B82A17C6D600B4D95E /* RecordingView_Tests.swift */, 82FF40BA2A17C6DF00B4D95E /* ScreenSharingView_Tests.swift */, + 407D5D3C2ACEF0C500B5044E /* VisibilityThresholdModifier_Tests.swift */, 40D6ADDC2ACDB51C00EF5336 /* VideoRenderer_Tests.swift */, + 407D5D3C2ACEF0C500B5044E /* VisibilityThresholdModifier_Tests.swift */, ); path = CallView; sourceTree = ""; @@ -2332,6 +2338,7 @@ 846E4AFC29D1DDE8003733AB /* LayoutMenuView.swift */, 846BA2AC2A9F602C001AD0AF /* SampleBufferVideoCallView.swift */, 8430FD212AB1AB4C007AA3E6 /* ParticipantPopoverView.swift */, + 401EDBAA2ACD5F1700520215 /* VisibilityThresholdModifier.swift */, ); path = CallView; sourceTree = ""; @@ -4256,6 +4263,7 @@ 84366E7C29C9FB6600287D14 /* VideoRendererFactory.swift in Sources */, 848FE1EF2A9DEAD700B45AC2 /* PiPHandler.swift in Sources */, 843B707529C270C300AB0573 /* ReconnectionView.swift in Sources */, + 401EDBAC2ACD646000520215 /* VisibilityThresholdModifier.swift in Sources */, 8406269C2A37A653004B8748 /* CallEventsHandler.swift in Sources */, 8434C529289AA2FA0001490A /* Colors.swift in Sources */, 401480302A5317640029166A /* AudioValuePercentageNormaliser.swift in Sources */, @@ -4378,6 +4386,7 @@ 82E3BA562A0BAF64001AB93E /* WebSocketEngine_Mock.swift in Sources */, 829F7BFD29FAC116003EBACE /* ParticipantsFullScreenLayout_Tests.swift in Sources */, 82FF40C62A17C75400B4D95E /* JoiningCallView_Tests.swift in Sources */, + 407D5D3D2ACEF0C500B5044E /* VisibilityThresholdModifier_Tests.swift in Sources */, 82E3BA4C2A0BAE40001AB93E /* EquatableEvent.swift in Sources */, 82FF40C42A17C74D00B4D95E /* IncomingCallView_Tests.swift in Sources */, 829F7BFA29FABC0E003EBACE /* ViewFactory.swift in Sources */, diff --git a/StreamVideoSwiftUITests/CallView/ParticipantsFullScreenLayout_Tests.swift b/StreamVideoSwiftUITests/CallView/ParticipantsFullScreenLayout_Tests.swift index 9acc00355..7759493ba 100644 --- a/StreamVideoSwiftUITests/CallView/ParticipantsFullScreenLayout_Tests.swift +++ b/StreamVideoSwiftUITests/CallView/ParticipantsFullScreenLayout_Tests.swift @@ -16,7 +16,7 @@ final class ParticipantsFullScreenLayout_Tests: StreamVideoUITestCase { viewFactory: TestViewFactory(), participant: ParticipantFactory.get(1, withAudio: true).first!, call: call, - size: defaultScreenSize, + frame: .init(origin: .zero, size: defaultScreenSize), onChangeTrackVisibility: {_,_ in } ) AssertSnapshot(layout) @@ -27,7 +27,7 @@ final class ParticipantsFullScreenLayout_Tests: StreamVideoUITestCase { viewFactory: TestViewFactory(), participant: ParticipantFactory.get(1, withAudio: false).first!, call: call, - size: defaultScreenSize, + frame: .init(origin: .zero, size: defaultScreenSize), onChangeTrackVisibility: {_,_ in } ) AssertSnapshot(layout) @@ -39,7 +39,7 @@ final class ParticipantsFullScreenLayout_Tests: StreamVideoUITestCase { viewFactory: TestViewFactory(), participant: ParticipantFactory.get(1, connectionQuality: quality).first!, call: call, - size: defaultScreenSize, + frame: .init(origin: .zero, size: defaultScreenSize), onChangeTrackVisibility: {_,_ in } ) AssertSnapshot(layout, suffix: "\(quality)") @@ -51,7 +51,7 @@ final class ParticipantsFullScreenLayout_Tests: StreamVideoUITestCase { viewFactory: TestViewFactory(), participant: ParticipantFactory.get(1, withAudio: true, speaking: true).first!, call: call, - size: defaultScreenSize, + frame: .init(origin: .zero, size: defaultScreenSize), onChangeTrackVisibility: {_,_ in } ) AssertSnapshot(layout) diff --git a/StreamVideoSwiftUITests/CallView/ParticipantsGridLayout_Tests.swift b/StreamVideoSwiftUITests/CallView/ParticipantsGridLayout_Tests.swift index d74eb01a8..b97b6ba33 100644 --- a/StreamVideoSwiftUITests/CallView/ParticipantsGridLayout_Tests.swift +++ b/StreamVideoSwiftUITests/CallView/ParticipantsGridLayout_Tests.swift @@ -33,9 +33,9 @@ final class ParticipantsGridLayout_Tests: StreamVideoUITestCase { private lazy var call = streamVideoUI?.streamVideo.call(callType: callType, callId: callId) - private func gridSize(for participantsCount: Int) -> CGSize { + private func gridSize(for participantsCount: Int) -> CGRect { let heightDivider = CGFloat((participantsCount == 2 || participantsCount == 3) ? participantsCount : 1) - return CGSize(width: defaultScreenSize.width, height: defaultScreenSize.height / heightDivider) + return .init(origin: .zero, size: CGSize(width: defaultScreenSize.width, height: defaultScreenSize.height / heightDivider)) } func test_grid_participantWithAudio_snapshot() { @@ -44,7 +44,7 @@ final class ParticipantsGridLayout_Tests: StreamVideoUITestCase { viewFactory: TestViewFactory(participantLayout: .grid, participantsCount: count), call: call, participants: ParticipantFactory.get(count, withAudio: true), - availableSize: gridSize(for: count), + availableFrame: gridSize(for: count), orientation: .portrait, onChangeTrackVisibility: {_,_ in } ) @@ -58,7 +58,7 @@ final class ParticipantsGridLayout_Tests: StreamVideoUITestCase { viewFactory: TestViewFactory(participantLayout: .grid, participantsCount: count), call: call, participants: ParticipantFactory.get(count, withAudio: false), - availableSize: gridSize(for: count), + availableFrame: gridSize(for: count), orientation: .portrait, onChangeTrackVisibility: {_,_ in } ) @@ -73,7 +73,7 @@ final class ParticipantsGridLayout_Tests: StreamVideoUITestCase { viewFactory: TestViewFactory(participantLayout: .grid, participantsCount: count), call: call, participants: ParticipantFactory.get(count, connectionQuality: quality), - availableSize: gridSize(for: count), + availableFrame: gridSize(for: count), orientation: .portrait, onChangeTrackVisibility: {_,_ in } ) @@ -93,7 +93,7 @@ final class ParticipantsGridLayout_Tests: StreamVideoUITestCase { viewFactory: TestViewFactory(participantLayout: .grid, participantsCount: count), call: call, participants: participants, - availableSize: gridSize(for: count), + availableFrame: gridSize(for: count), orientation: .portrait, onChangeTrackVisibility: {_,_ in } ) diff --git a/StreamVideoSwiftUITests/CallView/ParticipantsSpotlightLayout_Tests.swift b/StreamVideoSwiftUITests/CallView/ParticipantsSpotlightLayout_Tests.swift index 687f86c92..ed7c6f94c 100644 --- a/StreamVideoSwiftUITests/CallView/ParticipantsSpotlightLayout_Tests.swift +++ b/StreamVideoSwiftUITests/CallView/ParticipantsSpotlightLayout_Tests.swift @@ -19,7 +19,7 @@ final class ParticipantsSpotlightLayout_Tests: StreamVideoUITestCase { participant: participants.first!, call: call, participants: participants, - size: defaultScreenSize, + frame: .init(origin: .zero, size: defaultScreenSize), onChangeTrackVisibility: {_,_ in } ) AssertSnapshot(layout, suffix: "with_\(count)_participants") @@ -34,7 +34,7 @@ final class ParticipantsSpotlightLayout_Tests: StreamVideoUITestCase { participant: participants.first!, call: call, participants: participants, - size: defaultScreenSize, + frame: .init(origin: .zero, size: defaultScreenSize), onChangeTrackVisibility: {_,_ in } ) AssertSnapshot(layout, suffix: "with_\(count)_participants") @@ -49,7 +49,7 @@ final class ParticipantsSpotlightLayout_Tests: StreamVideoUITestCase { participant: participants.first!, call: call, participants: participants, - size: defaultScreenSize, + frame: .init(origin: .zero, size: defaultScreenSize), onChangeTrackVisibility: {_,_ in } ) @@ -64,7 +64,7 @@ final class ParticipantsSpotlightLayout_Tests: StreamVideoUITestCase { participant: participants.first!, call: call, participants: participants, - size: defaultScreenSize, + frame: .init(origin: .zero, size: defaultScreenSize), onChangeTrackVisibility: {_,_ in } ) AssertSnapshot(layout) diff --git a/StreamVideoSwiftUITests/CallView/ScreenSharingView_Tests.swift b/StreamVideoSwiftUITests/CallView/ScreenSharingView_Tests.swift index 5c9f8a8f6..e9c5d5772 100644 --- a/StreamVideoSwiftUITests/CallView/ScreenSharingView_Tests.swift +++ b/StreamVideoSwiftUITests/CallView/ScreenSharingView_Tests.swift @@ -14,7 +14,7 @@ final class ScreenSharingView_Tests: StreamVideoUITestCase { let view = ScreenSharingView( viewModel: CallViewModel(), screenSharing: .init(track: .none, participant: ParticipantFactory.get(2).last!), - availableSize: defaultScreenSize + availableFrame: .init(origin: .zero, size: defaultScreenSize) ) AssertSnapshot(view) } diff --git a/StreamVideoSwiftUITests/CallView/VisibilityThresholdModifier_Tests.swift b/StreamVideoSwiftUITests/CallView/VisibilityThresholdModifier_Tests.swift new file mode 100644 index 000000000..1d7fac861 --- /dev/null +++ b/StreamVideoSwiftUITests/CallView/VisibilityThresholdModifier_Tests.swift @@ -0,0 +1,109 @@ +// +// Copyright © 2023 Stream.io Inc. All rights reserved. +// + +@testable import StreamVideoSwiftUI +@testable import StreamVideo +import SnapshotTesting +import XCTest +import SwiftUI + +final class VisibilityThresholdModifier_Tests: XCTestCase { + + private lazy var bounds: CGRect! = CGRect(x: 0, y: 0, width: 100, height: 100) + + override func tearDown() { + bounds = nil + super.tearDown() + } + + func test_visibilityFullyInsideBounds() { + assertVisibilityCalculations( + in: bounds, + threshold: 0.5, + viewRect: CGRect(x: 10, y: 10, width: 80, height: 80), + expected: (true, true) + ) + } + + func test_visibilityPartiallyOutsideBoundsTopLeft() { + assertVisibilityCalculations( + in: bounds, + threshold: 0.5, + viewRect: CGRect(x: -10, y: -10, width: 60, height: 60), + expected: (true, true) + ) + } + + func test_visibilityCompletelyOutsideBoundsTopLeft() { + assertVisibilityCalculations( + in: bounds, + threshold: 0.5, + viewRect: CGRect(x: -110, y: -110, width: 60, height: 60), + expected: (false, false) + ) + } + + func test_visibilityAtThreshold() { + assertVisibilityCalculations( + in: bounds, + threshold: 0.5, + viewRect: CGRect(x: 10, y: 10, width: 40, height: 40), + expected: (true, true) + ) + } + + func test_visibilityBelowThreshold() { + assertVisibilityCalculations( + in: bounds, + threshold: 0.8, + viewRect: CGRect(x: -35, y: -35, width: 40, height: 40), + expected: (false, false) + ) + } + + func test_visibilityPartiallyOutsideBoundsLeftFullyVisibleVertically() { + assertVisibilityCalculations( + in: bounds, + threshold: 0.5, + viewRect: CGRect(x: -10, y: 0, width: 60, height: 100), + expected: (false, true) + ) + } + + func test_visibilityCompletelyOutsideBoundsBottomFullyVisibleHorizontally() { + assertVisibilityCalculations( + in: bounds, + threshold: 0.5, + viewRect: CGRect(x: 0, y: 110, width: 100, height: 60), + expected: (false, false) + ) + } + + func test_visibilityCompletelyOutsideBoundsRightFullyVisibleVertically() { + assertVisibilityCalculations( + in: bounds, + threshold: 0.5, + viewRect: CGRect(x: 110, y: 0, width: 60, height: 100), + expected: (false, false) + ) + } + + // MARK: - Private Helpers + + private func assertVisibilityCalculations( + in bounds: CGRect, + threshold: CGFloat, + viewRect: CGRect, + expected: (Bool, Bool), + file: StaticString = #file, + line: UInt = #line + ) { + let modifier = VisibilityThresholdModifier(in: bounds, threshold: threshold) { _ in } + + let (vertical, horizontal) = modifier.calculateVisibilityInBothAxis(in: viewRect) + + XCTAssertEqual(expected.0, vertical, "Vertical visibility doesn't match!", file: file, line: line) + XCTAssertEqual(expected.1, horizontal, "Horizontal visibility doesn't", file: file, line: line) + } +} diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_6_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_6_participants.png index 5952a252c..fdf9a11ab 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_6_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_6_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_7_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_7_participants.png index ec367ad82..260b21a0c 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_7_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_7_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_8_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_8_participants.png index 768964f53..cb9a4db4f 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_8_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_8_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_9_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_9_participants.png index 768964f53..cb9a4db4f 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_9_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-dark-with_9_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_6_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_6_participants.png index 77c1b9523..abcc9be2a 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_6_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_6_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_7_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_7_participants.png index dc19657cd..b4d6329c1 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_7_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_7_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_8_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_8_participants.png index 8f99c0c40..92e73cee0 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_8_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_8_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_9_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_9_participants.png index 8f99c0c40..92e73cee0 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_9_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithAudio_snapshot.default-light-with_9_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_6_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_6_participants.png index f1401df97..07f42112e 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_6_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_6_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_7_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_7_participants.png index 751670e13..594d2bace 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_7_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_7_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_8_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_8_participants.png index 384da82a8..25a1f3203 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_8_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_8_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_9_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_9_participants.png index 384da82a8..25a1f3203 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_9_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-dark-with_9_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_6_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_6_participants.png index b12d66985..d80bd9ce1 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_6_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_6_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_7_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_7_participants.png index 862856ec1..86af40dc8 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_7_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_7_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_8_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_8_participants.png index 8a61d8719..8e67ee504 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_8_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_8_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_9_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_9_participants.png index 8a61d8719..8e67ee504 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_9_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantWithoutAudio_snapshot.default-light-with_9_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-excellent.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-excellent.png index 384da82a8..25a1f3203 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-excellent.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-excellent.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-good.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-good.png index 06822f9ee..0bc42f5e1 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-good.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-good.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-poor.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-poor.png index 8d367d28a..a99f0e909 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-poor.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-poor.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-unknown.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-unknown.png index 35b33ba05..911fa6e9c 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-unknown.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-dark-unknown.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-excellent.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-excellent.png index 8a61d8719..8e67ee504 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-excellent.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-excellent.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-good.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-good.png index 568e58712..d801c92cf 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-good.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-good.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-poor.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-poor.png index 1c0361812..96fe13ca0 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-poor.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-poor.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-unknown.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-unknown.png index 7ea141283..3e3ce1870 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-unknown.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsConnectionQuality_snapshot.default-light-unknown.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_6_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_6_participants.png index 238d14f4e..50713ff58 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_6_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_6_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_7_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_7_participants.png index 6f00b4cd4..4fe313aa3 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_7_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_7_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_8_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_8_participants.png index 41761a35d..0c91caede 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_8_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_8_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_9_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_9_participants.png index 41761a35d..0c91caede 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_9_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-dark-with_9_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_6_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_6_participants.png index 7a06760cb..e5f8706a3 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_6_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_6_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_7_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_7_participants.png index 3b7837376..c798ce912 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_7_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_7_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_8_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_8_participants.png index d44120bd7..896cfb5e3 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_8_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_8_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_9_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_9_participants.png index d44120bd7..896cfb5e3 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_9_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsGridLayout_Tests/test_grid_participantsSpeaking_snapshot.default-light-with_9_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_1_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_1_participants.png index 97194c6fc..3946c8be4 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_1_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_1_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_2_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_2_participants.png index e9e0e1da9..b4ca7a1a3 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_2_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_2_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_3_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_3_participants.png index 86918eeab..45ab1fe50 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_3_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_3_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_4_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_4_participants.png index 86918eeab..45ab1fe50 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_4_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-dark-with_4_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_1_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_1_participants.png index 0c382f143..43517be0b 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_1_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_1_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_2_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_2_participants.png index 9401a8816..de79afc60 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_2_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_2_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_3_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_3_participants.png index b9d28d01b..48ddcec72 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_3_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_3_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_4_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_4_participants.png index b9d28d01b..48ddcec72 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_4_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithAudio_snapshot.default-light-with_4_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_1_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_1_participants.png index 3cccb3b88..0e4cb8744 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_1_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_1_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_2_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_2_participants.png index b78282ad2..9adcbd942 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_2_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_2_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_3_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_3_participants.png index 1cac7c183..6fe7f4dcc 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_3_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_3_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_4_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_4_participants.png index 1cac7c183..6fe7f4dcc 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_4_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-dark-with_4_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_1_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_1_participants.png index 39a15d786..bcfeab958 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_1_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_1_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_2_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_2_participants.png index a728b358e..7eb3a7313 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_2_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_2_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_3_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_3_participants.png index e1a0b2c8f..3b8271620 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_3_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_3_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_4_participants.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_4_participants.png index e1a0b2c8f..3b8271620 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_4_participants.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantWithoutAudio_snapshot.default-light-with_4_participants.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-excellent.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-excellent.png index 1cac7c183..6fe7f4dcc 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-excellent.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-excellent.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-good.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-good.png index 9546ac6a3..f6a214294 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-good.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-good.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-poor.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-poor.png index 6b96f7dab..223366836 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-poor.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-poor.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-unknown.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-unknown.png index 24eea05ce..bbd3c1dc7 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-unknown.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-dark-unknown.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-excellent.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-excellent.png index e1a0b2c8f..3b8271620 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-excellent.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-excellent.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-good.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-good.png index 27a625aa3..d981147ac 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-good.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-good.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-poor.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-poor.png index 312e3d355..4480d7974 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-poor.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-poor.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-unknown.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-unknown.png index ad03987ec..8a64998bd 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-unknown.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsConnectionQuality_snapshot.default-light-unknown.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsSpeaking_snapshot.default-dark.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsSpeaking_snapshot.default-dark.png index 1cac7c183..6fe7f4dcc 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsSpeaking_snapshot.default-dark.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsSpeaking_snapshot.default-dark.png differ diff --git a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsSpeaking_snapshot.default-light.png b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsSpeaking_snapshot.default-light.png index e1a0b2c8f..3b8271620 100644 Binary files a/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsSpeaking_snapshot.default-light.png and b/StreamVideoSwiftUITests/CallView/__Snapshots__/ParticipantsSpotlightLayout_Tests/test_spotlight_participantsSpeaking_snapshot.default-light.png differ diff --git a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_0_participants.png b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_0_participants.png index 4513e0f4f..9c7ec7e96 100644 Binary files a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_0_participants.png and b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_0_participants.png differ diff --git a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_1_participants.png b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_1_participants.png index 4b2edd177..db395419f 100644 Binary files a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_1_participants.png and b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_1_participants.png differ diff --git a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_2_participants.png b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_2_participants.png index 6bc0d2583..082968ce0 100644 Binary files a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_2_participants.png and b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-dark-with_2_participants.png differ diff --git a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_0_participants.png b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_0_participants.png index cd1c043da..57b7c0aeb 100644 Binary files a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_0_participants.png and b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_0_participants.png differ diff --git a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_1_participants.png b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_1_participants.png index a101551da..feb86245f 100644 Binary files a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_1_participants.png and b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_1_participants.png differ diff --git a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_2_participants.png b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_2_participants.png index 9b5a6aa25..34bb5b833 100644 Binary files a/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_2_participants.png and b/StreamVideoSwiftUITests/CallingViews/__Snapshots__/LobbyView_Tests/test_lobbyView_snapshot.default-light-with_2_participants.png differ diff --git a/StreamVideoSwiftUITests/Livestreaming/__Snapshots__/LivestreamPlayer_Tests/test_livestreamPlayer_snapshot.1.png b/StreamVideoSwiftUITests/Livestreaming/__Snapshots__/LivestreamPlayer_Tests/test_livestreamPlayer_snapshot.1.png index 03bfc24d6..0998b9e0e 100644 Binary files a/StreamVideoSwiftUITests/Livestreaming/__Snapshots__/LivestreamPlayer_Tests/test_livestreamPlayer_snapshot.1.png and b/StreamVideoSwiftUITests/Livestreaming/__Snapshots__/LivestreamPlayer_Tests/test_livestreamPlayer_snapshot.1.png differ diff --git a/StreamVideoSwiftUITests/Livestreaming/__Snapshots__/LivestreamPlayer_Tests/test_livestreamPlayer_snapshotHideParticipantCount.1.png b/StreamVideoSwiftUITests/Livestreaming/__Snapshots__/LivestreamPlayer_Tests/test_livestreamPlayer_snapshotHideParticipantCount.1.png index 23505b068..eb7a377a8 100644 Binary files a/StreamVideoSwiftUITests/Livestreaming/__Snapshots__/LivestreamPlayer_Tests/test_livestreamPlayer_snapshotHideParticipantCount.1.png and b/StreamVideoSwiftUITests/Livestreaming/__Snapshots__/LivestreamPlayer_Tests/test_livestreamPlayer_snapshotHideParticipantCount.1.png differ diff --git a/TestTools/TestData/ViewFactory.swift b/TestTools/TestData/ViewFactory.swift index c571a153c..97adf6158 100644 --- a/TestTools/TestData/ViewFactory.swift +++ b/TestTools/TestData/ViewFactory.swift @@ -20,7 +20,7 @@ class TestViewFactory: ViewFactory { func makeVideoParticipantView( participant: CallParticipant, id: String, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, customData: [String: RawJSON], call: Call? @@ -48,7 +48,7 @@ class TestViewFactory: ViewFactory { } if isCustomGridFrame { - return zstack.frame(maxWidth: availableSize.width, maxHeight: availableSize.height) + return zstack.frame(maxWidth: availableFrame.width, maxHeight: availableFrame.height) } else { return zstack.frame(maxWidth: .infinity, maxHeight: .infinity) } diff --git a/docusaurus/docs/iOS/02-tutorials/01-video-calling.mdx b/docusaurus/docs/iOS/02-tutorials/01-video-calling.mdx index fb243d8af..f29060fce 100644 --- a/docusaurus/docs/iOS/02-tutorials/01-video-calling.mdx +++ b/docusaurus/docs/iOS/02-tutorials/01-video-calling.mdx @@ -214,11 +214,11 @@ struct ParticipantsView: View { ScrollView { LazyVStack { if participants.count == 1, let participant = participants.first { - makeCallParticipantView(participant, size: proxy.size) + makeCallParticipantView(participant, frame: proxy.frame(in: .global)) .frame(width: proxy.size.width, height: proxy.size.height) } else { ForEach(participants) { participant in - makeCallParticipantView(participant, size: proxy.size) + makeCallParticipantView(participant, frame: proxy.frame(in: .global)) .frame(width: proxy.size.width, height: proxy.size.height / 2) } } @@ -232,10 +232,10 @@ struct ParticipantsView: View { } @ViewBuilder - private func makeCallParticipantView(_ participant: CallParticipant, size: CGSize) -> some View { + private func makeCallParticipantView(_ participant: CallParticipant, frame: CGRect) -> some View { VideoCallParticipantView( participant: participant, - availableSize: size, + availableFrame: frame, contentMode: .scaleAspectFit, customData: [:], call: call @@ -284,7 +284,7 @@ We added the `changeTrackVisibility` in our app and we propagate its call to the ```swift VideoCallParticipantView( participant: participant, - availableSize: size, + availableFrame: frame, contentMode: .scaleAspectFit, customData: [:], call: call diff --git a/docusaurus/docs/iOS/03-guides/10-view-slots.mdx b/docusaurus/docs/iOS/03-guides/10-view-slots.mdx index 4b7b9555c..e50412e72 100644 --- a/docusaurus/docs/iOS/03-guides/10-view-slots.mdx +++ b/docusaurus/docs/iOS/03-guides/10-view-slots.mdx @@ -61,14 +61,12 @@ The video participants view slot presents the grid of users that are in the call ```swift public func makeVideoParticipantsView( participants: [CallParticipant], - availableSize: CGSize, - onViewRendering: @escaping (VideoRenderer, CallParticipant) -> Void, + availableFrame: CGRect, onChangeTrackVisibility: @escaping @MainActor(CallParticipant, Bool) -> Void ) -> some View { VideoParticipantsView( participants: participants, - availableSize: availableSize, - onViewRendering: onViewRendering, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } @@ -77,8 +75,7 @@ public func makeVideoParticipantsView( In the method, the following parameters are provided: - `participants` - the list of participants. -- `availableSize` - the available size for the participants view. -- `onViewRendering` - called when the view is rendered. This callback should be used to attach a track to the view. +- `availableFrame` - the available frame for the participants view. - `onChangeTrackVisibility` - callback when the track changes its visibility. #### Video Participant View @@ -89,7 +86,7 @@ If you want to customize one particular participant view, you can change it via func makeVideoParticipantView( participant: CallParticipant, id: String, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, customData: [String: RawJSON], call: Call? @@ -97,7 +94,7 @@ func makeVideoParticipantView( VideoCallParticipantView( participant: participant, id: id, - availableSize: availableSize, + availableFrame: availableFrame, contentMode: contentMode, call: call ) @@ -110,14 +107,14 @@ Additionally, you can change the modifier applied to the view, by implementing t public makeVideoCallParticipantModifier( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) -> some ViewModifier { VideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: showAllInfo ) diff --git a/docusaurus/docs/iOS/04-ui-components/02-video-renderer.mdx b/docusaurus/docs/iOS/04-ui-components/02-video-renderer.mdx index af11decc4..a2f7db7c5 100644 --- a/docusaurus/docs/iOS/04-ui-components/02-video-renderer.mdx +++ b/docusaurus/docs/iOS/04-ui-components/02-video-renderer.mdx @@ -72,27 +72,27 @@ public struct VideoCallParticipantModifier: ViewModifier { var participant: CallParticipant var call: Call? - var availableSize: CGSize + var availableFrame: CGRect var ratio: CGFloat var showAllInfo: Bool public init( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) { self.participant = participant self.call = call - self.availableSize = availableSize + self.availableFrame = availableFrame self.ratio = ratio self.showAllInfo = showAllInfo } public func body(content: Content) -> some View { content - .adjustVideoFrame(to: availableSize.width, ratio: ratio) + .adjustVideoFrame(to: availableFrame.size.width, ratio: ratio) .overlay( ZStack { BottomView(content: { @@ -206,7 +206,7 @@ ForEach(participants) { participant in viewFactory.makeVideoParticipantView( participant: participant, id: participant.id, - availableSize: availableSize, + availableFrame: availableFrame, contentMode: .scaleAspectFill, customData: [:], call: call @@ -215,7 +215,7 @@ ForEach(participants) { participant in viewFactory.makeVideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: true ) diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/04-active-call.mdx b/docusaurus/docs/iOS/04-ui-components/07-call/04-active-call.mdx index a3f2f733a..090e70c49 100644 --- a/docusaurus/docs/iOS/04-ui-components/07-call/04-active-call.mdx +++ b/docusaurus/docs/iOS/04-ui-components/07-call/04-active-call.mdx @@ -43,14 +43,12 @@ The video participants view slot presents the grid of users that are in the call ```swift public func makeVideoParticipantsView( participants: [CallParticipant], - availableSize: CGSize, - onViewRendering: @escaping (VideoRenderer, CallParticipant) -> Void, + availableFrame: CGRect, onChangeTrackVisibility: @escaping @MainActor(CallParticipant, Bool) -> Void ) -> some View { VideoParticipantsView( participants: participants, - availableSize: availableSize, - onViewRendering: onViewRendering, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } @@ -59,8 +57,7 @@ public func makeVideoParticipantsView( In the method, the following parameters are provided: - `participants` - the list of participants. -- `availableSize` - the available size for the participants view. -- `onViewRendering` - called when the view is rendered. This callback should be used to attach a track to the view. +- `availableFrame` - the available frame for the participants view. - `onChangeTrackVisibility` - callback when the track changes its visibility. #### Video Participant View @@ -71,7 +68,7 @@ If you want to customize one particular participant view, you can change it via public func makeVideoParticipantView( participant: CallParticipant, id: String, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, customData: [String: RawJSON], call: Call? @@ -79,7 +76,7 @@ public func makeVideoParticipantView( VideoCallParticipantView( participant: participant, id: id, - availableSize: availableSize, + availableFrame: availableFrame, contentMode: contentMode, call: call ) @@ -92,14 +89,14 @@ Additionally, you can change the modifier applied to the view, by implementing t public func makeVideoCallParticipantModifier( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) -> some ViewModifier { VideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: showAllInfo ) diff --git a/docusaurus/docs/iOS/04-ui-components/07-call/07-screen-share-content.mdx b/docusaurus/docs/iOS/04-ui-components/07-call/07-screen-share-content.mdx index cafc8da2f..9dd9bc1f1 100644 --- a/docusaurus/docs/iOS/04-ui-components/07-call/07-screen-share-content.mdx +++ b/docusaurus/docs/iOS/04-ui-components/07-call/07-screen-share-content.mdx @@ -16,7 +16,7 @@ Here's an example how to create a `ScreenSharingView`: ScreenSharingView( viewModel: viewModel, screenSharing: screensharingSession, - availableSize: availableSize + availableFrame: CGRect ) ``` @@ -24,7 +24,7 @@ In this method, the following parameters are provided: - `viewModel` - the `CallViewModel` used in the call. - `screensharingSession` - The current screen sharing session, that contains information about the track, as well as the participant that is sharing. -- `availableSize` - the available size to layout the rendering view. +- `availableFrame` - the available frame to layout the rendering view. ## Customization @@ -34,12 +34,12 @@ If you want to implement your own UI when there's screen sharing in progress, yo public func makeScreenSharingView( viewModel: CallViewModel, screensharingSession: ScreenSharingSession, - availableSize: CGSize + availableFrame: CGRect ) -> some View { CustomScreenSharingView( viewModel: viewModel, screenSharing: screensharingSession, - availableSize: availableSize + availableFrame: availableFrame ) } ``` @@ -48,4 +48,4 @@ Similarly to above, the following parameters are provided: - `viewModel` - the `CallViewModel` used in the call. - `screensharingSession` - The current screen sharing session, that contains information about the track, as well as the participant that is sharing. -- `availableSize` - the available size to layout the rendering view. \ No newline at end of file +- `availableFrame` - the available frame to layout the rendering view. \ No newline at end of file diff --git a/docusaurus/docs/iOS/04-ui-components/08-participants/01-call-participant.mdx b/docusaurus/docs/iOS/04-ui-components/08-participants/01-call-participant.mdx index 966da6f74..01d284e0a 100644 --- a/docusaurus/docs/iOS/04-ui-components/08-participants/01-call-participant.mdx +++ b/docusaurus/docs/iOS/04-ui-components/08-participants/01-call-participant.mdx @@ -14,7 +14,7 @@ To use the `VideoCallParticipantView` component, embed it anywhere in your custo VideoCallParticipantView( participant: participant, id: id, - availableSize: availableSize, + availableFrame: availableFrame, contentMode: contentMode, customData: customData, call: call @@ -23,7 +23,7 @@ VideoCallParticipantView( VideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: true ) @@ -36,7 +36,7 @@ If you are using our `ViewFactory`, these parameters are provided in the factory public func makeVideoParticipantView( participant: CallParticipant, id: String, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, customData: [String: RawJSON], call: Call? @@ -44,7 +44,7 @@ public func makeVideoParticipantView( VideoCallParticipantView( participant: participant, id: id, - availableSize: availableSize, + availableFrame: availableFrame, contentMode: contentMode, customData: customData, call: call @@ -54,14 +54,14 @@ public func makeVideoParticipantView( public func makeVideoCallParticipantModifier( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) -> some ViewModifier { VideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: showAllInfo ) @@ -71,7 +71,7 @@ public func makeVideoCallParticipantModifier( For the `VideoCallParticipantView`, the required parameters are: - `participant` - the `CallParticipant` object representing a user in a call - `id` - the SwiftUI id for the view (you can pass the id of the `participant` here) -- `availableSize` - the available size for the view +- `availableFrame` - the available frame for the view - `contentMode` - the content mode of the view - `customData` - any custom data that you can pass to the view - `call` - the current call @@ -80,7 +80,7 @@ For the `VideoCallParticipantModifier` you should provide the following paramete - `participant` - the `CallParticipant` object representing a user in a call - `participantCount` - the number of participants in the call - `pinnedParticipant` - optional binding of the pinned participant (if any) -- `availableSize` - the available size for the view +- `availableFrame` - the available frame≈ for the view - `ratio` - the ratio for the view slot - `showAllInfo` - if all information should be shown in the card diff --git a/docusaurus/docs/iOS/04-ui-components/08-participants/02-call-participants.mdx b/docusaurus/docs/iOS/04-ui-components/08-participants/02-call-participants.mdx index 9cc46ee5c..6d640fc84 100644 --- a/docusaurus/docs/iOS/04-ui-components/08-participants/02-call-participants.mdx +++ b/docusaurus/docs/iOS/04-ui-components/08-participants/02-call-participants.mdx @@ -23,8 +23,7 @@ The `VideoParticipantsView` is a stateful component that requires a `CallViewMod VideoParticipantsView( viewFactory: DefaultViewFactory.shared, viewModel: viewModel, - availableSize: availableSize, - onViewRendering: onViewRendering, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) ``` @@ -32,8 +31,7 @@ VideoParticipantsView( The parameters needed for this component are as follows: - `viewFactory` - the view factory used for creation of the views - `viewModel` - the `CallViewModel` -- `availableSize` - the available size for the view -- `onViewRendering` - called when the view is rendered or updated +- `availableFrame` - the available frame for the view - `onChangeTrackVisibility` - called when the track changes its visibility If you are using our `ViewFactory`, you can swap this component with your implementation by implementing the following method: @@ -41,15 +39,13 @@ If you are using our `ViewFactory`, you can swap this component with your implem ```swift public func makeVideoParticipantsView( viewModel: CallViewModel, - availableSize: CGSize, - onViewRendering: @escaping (VideoRenderer, CallParticipant) -> Void, + availableFrame: CGRect, onChangeTrackVisibility: @escaping @MainActor(CallParticipant, Bool) -> Void ) -> some View { CustomVideoParticipantsView( viewFactory: self, viewModel: viewModel, - availableSize: availableSize, - onViewRendering: onViewRendering, + availableFrame: availableFrame, onChangeTrackVisibility: onChangeTrackVisibility ) } @@ -66,9 +62,8 @@ ParticipantsGridLayout( viewFactory: viewFactory, participants: viewModel.participants, pinnedParticipant: $viewModel.pinnedParticipant, - availableSize: availableSize, + availableFrame: availableFrame, orientation: orientation, - onViewRendering: onViewRendering, onChangeTrackVisibility: onChangeTrackVisibility ) ``` @@ -82,9 +77,8 @@ ParticipantsSpotlightLayout( viewFactory: viewFactory, participant: first, participants: Array(viewModel.participants.dropFirst()), - size: availableSize, + size: availableFrame.size, pinnedParticipant: $viewModel.pinnedParticipant, - onViewRendering: onViewRendering, onChangeTrackVisibility: onChangeTrackVisibility ) ``` @@ -97,9 +91,8 @@ You can use the full screen layout with the code below: ParticipantsFullScreenLayout( viewFactory: viewFactory, participant: first, - size: availableSize, + frame: availableFrame, pinnedParticipant: $viewModel.pinnedParticipant, - onViewRendering: onViewRendering, onChangeTrackVisibility: onChangeTrackVisibility ) ``` \ No newline at end of file diff --git a/docusaurus/docs/iOS/04-ui-components/08-participants/03-call-participants-info-menu.mdx b/docusaurus/docs/iOS/04-ui-components/08-participants/03-call-participants-info-menu.mdx index 7f5a5ffde..e283d6b7b 100644 --- a/docusaurus/docs/iOS/04-ui-components/08-participants/03-call-participants-info-menu.mdx +++ b/docusaurus/docs/iOS/04-ui-components/08-participants/03-call-participants-info-menu.mdx @@ -11,23 +11,23 @@ Let's see how to use the component. If you want to use the componant as a standalone, you can create it like this: ```swift -let view = CallParticipantsInfoView(callViewModel: viewModel, availableSize: availableSize) +let view = CallParticipantsInfoView(callViewModel: viewModel, availableFrame: availableFrame) ``` The required parameters for this method are: - `callViewModel` - the call view model used for the call. -- `availableSize` - the available size for the view. +- `availableFrame` - the available frame for the view. Additionally, if you are using our `ViewFactory` and the default view, you can customize or swap this view with your own implementation. In order to do that, you should implement the method `makeParticipantsListView`: ```swift func makeParticipantsListView( viewModel: CallViewModel, - availableSize: CGSize + availableFrame: CGRect ) -> some View { CustomCallParticipantsInfoView( callViewModel: viewModel, - availableSize: availableSize + availableFrame: availableFrame ) ``` diff --git a/docusaurus/docs/iOS/05-ui-cookbook/03-custom-label.mdx b/docusaurus/docs/iOS/05-ui-cookbook/03-custom-label.mdx index 3b563f9ad..4bbb0b5b1 100644 --- a/docusaurus/docs/iOS/05-ui-cookbook/03-custom-label.mdx +++ b/docusaurus/docs/iOS/05-ui-cookbook/03-custom-label.mdx @@ -14,7 +14,7 @@ func makeVideoCallParticipantModifier( participant: CallParticipant, participantCount: Int, pinnedParticipant: Binding, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) -> some ViewModifier { @@ -22,7 +22,7 @@ func makeVideoCallParticipantModifier( participant: participant, pinnedParticipant: pinnedParticipant, participantCount: participantCount, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: showAllInfo ) @@ -37,26 +37,26 @@ struct CustomParticipantModifier: ViewModifier { var participant: CallParticipant @Binding var pinnedParticipant: CallParticipant? var participantCount: Int - var availableSize: CGSize + var availableFrame: CGRect var ratio: CGFloat public init( participant: CallParticipant, pinnedParticipant: Binding, participantCount: Int, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat ) { self.participant = participant _pinnedParticipant = pinnedParticipant self.participantCount = participantCount - self.availableSize = availableSize + self.availableFrame = availableFrame self.ratio = ratio } public func body(content: Content) -> some View { content - .adjustVideoFrame(to: availableSize.width, ratio: ratio) + .adjustVideoFrame(to: availableFrame.size.width, ratio: ratio) .overlay( ZStack { VStack { diff --git a/docusaurus/docs/iOS/05-ui-cookbook/04-video-layout.mdx b/docusaurus/docs/iOS/05-ui-cookbook/04-video-layout.mdx index a2e0c74f4..ef2671e62 100644 --- a/docusaurus/docs/iOS/05-ui-cookbook/04-video-layout.mdx +++ b/docusaurus/docs/iOS/05-ui-cookbook/04-video-layout.mdx @@ -115,7 +115,7 @@ var body: some View { if let dominantSpeaker = participants.first { VideoCallParticipantView( participant: dominantSpeaker, - availableSize: reader.size, + availableFrame: reader.frame(in: .global), contentMode: .scaleAspectFit, call: call ) diff --git a/docusaurus/docs/iOS/05-ui-cookbook/07-video-fallback.mdx b/docusaurus/docs/iOS/05-ui-cookbook/07-video-fallback.mdx index ce73358bd..fb6dee72d 100644 --- a/docusaurus/docs/iOS/05-ui-cookbook/07-video-fallback.mdx +++ b/docusaurus/docs/iOS/05-ui-cookbook/07-video-fallback.mdx @@ -17,7 +17,7 @@ In order to do this, we need to implement the `makeVideoParticipantView` in our func makeVideoParticipantView( participant: CallParticipant, id: String, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, customData: [String: RawJSON], call: Call? @@ -25,7 +25,7 @@ func makeVideoParticipantView( CustomVideoCallParticipantView( participant: participant, id: id, - availableSize: availableSize, + availableFrame: availableFrame, contentMode: contentMode, call: call ) @@ -42,7 +42,7 @@ public struct CustomVideoCallParticipantView: View { let participant: CallParticipant var id: String - var availableSize: CGSize + var availableFrame: CGRect var contentMode: UIView.ContentMode var edgesIgnoringSafeArea: Edge.Set var call: Call? @@ -50,14 +50,14 @@ public struct CustomVideoCallParticipantView: View { public init( participant: CallParticipant, id: String? = nil, - availableSize: CGSize, + availableFrame: CGRect, contentMode: UIView.ContentMode, edgesIgnoringSafeArea: Edge.Set = .all, call: Call? ) { self.participant = participant self.id = id ?? participant.id - self.availableSize = availableSize + self.availableFrame = availableFrame self.contentMode = contentMode self.edgesIgnoringSafeArea = edgesIgnoringSafeArea self.call = call @@ -66,7 +66,7 @@ public struct CustomVideoCallParticipantView: View { public var body: some View { VideoRendererView( id: id, - size: availableSize, + size: availableFrame.size, contentMode: contentMode, handleRendering: { view in view.handleViewRendering(for: participant) { size, participant in @@ -86,7 +86,7 @@ public struct CustomVideoCallParticipantView: View { name: participant.name, imageURL: participant.profileImageURL ) - .frame(width: availableSize.width) + .frame(width: availableFrame.size.width) .opacity(showVideo ? 0 : 1) ) } diff --git a/docusaurus/docs/iOS/05-ui-cookbook/13-pinning-users.mdx b/docusaurus/docs/iOS/05-ui-cookbook/13-pinning-users.mdx index 908e14ee4..85e0b6de6 100644 --- a/docusaurus/docs/iOS/05-ui-cookbook/13-pinning-users.mdx +++ b/docusaurus/docs/iOS/05-ui-cookbook/13-pinning-users.mdx @@ -47,14 +47,14 @@ If you want to change this behaviour, you should implement your own version of i func makeVideoCallParticipantModifier( participant: CallParticipant, call: Call?, - availableSize: CGSize, + availableFrame: CGRect, ratio: CGFloat, showAllInfo: Bool ) -> some ViewModifier { CustomVideoCallParticipantModifier( participant: participant, call: call, - availableSize: availableSize, + availableFrame: availableFrame, ratio: ratio, showAllInfo: showAllInfo ) diff --git a/docusaurus/docs/iOS/06-advanced/04-screensharing.mdx b/docusaurus/docs/iOS/06-advanced/04-screensharing.mdx index 054dca749..733608f1b 100644 --- a/docusaurus/docs/iOS/06-advanced/04-screensharing.mdx +++ b/docusaurus/docs/iOS/06-advanced/04-screensharing.mdx @@ -58,12 +58,12 @@ If you use our default UI components, this logic is already handled for you. In public func makeScreenSharingView( viewModel: CallViewModel, screensharingSession: ScreenSharingSession, - availableSize: CGSize + availableFrame: CGRect ) -> some View { CustomScreenSharingView( viewModel: viewModel, screenSharing: screensharingSession, - availableSize: availableSize + availableFrame: availableFrame ) } ```