[WIP] Conference

This commit is contained in:
Isaac
2025-01-21 11:04:37 +04:00
parent 550fd89558
commit a4717b7906
47 changed files with 4439 additions and 816 deletions

View File

@@ -191,6 +191,7 @@ final class VideoChatParticipantVideoComponent: Component {
private let pinchContainerNode: PinchSourceContainerNode
private let extractedContainerView: ContextExtractedContentContainingView
private var videoSource: AdaptedCallVideoSource?
private var videoPlaceholder: VideoSource.Output?
private var videoDisposable: Disposable?
private var videoBackgroundLayer: SimpleLayer?
private var videoLayer: PrivateCallVideoLayer?
@@ -263,6 +264,11 @@ final class VideoChatParticipantVideoComponent: Component {
}
}
func updatePlaceholder(placeholder: VideoSource.Output) {
self.videoPlaceholder = placeholder
self.componentState?.updated(transition: .immediate, isLocal: true)
}
func update(component: VideoChatParticipantVideoComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
self.isUpdating = true
defer {
@@ -456,6 +462,46 @@ final class VideoChatParticipantVideoComponent: Component {
videoBackgroundLayer.isHidden = true
}
let videoUpdated: () -> Void = { [weak self] in
guard let self, let videoSource = self.videoSource, let videoLayer = self.videoLayer else {
return
}
var videoOutput = videoSource.currentOutput
var isPlaceholder = false
if videoOutput == nil {
isPlaceholder = true
videoOutput = self.videoPlaceholder
} else {
self.videoPlaceholder = nil
}
videoLayer.video = videoOutput
if let videoOutput {
let videoSpec = VideoSpec(resolution: videoOutput.resolution, rotationAngle: videoOutput.rotationAngle, followsDeviceOrientation: videoOutput.followsDeviceOrientation)
if self.videoSpec != videoSpec || self.awaitingFirstVideoFrameForUnpause {
self.awaitingFirstVideoFrameForUnpause = false
self.videoSpec = videoSpec
if !self.isUpdating {
var transition: ComponentTransition = .immediate
if !isPlaceholder {
transition = transition.withUserData(AnimationHint(kind: .videoAvailabilityChanged))
}
self.componentState?.updated(transition: transition, isLocal: true)
}
}
} else {
if self.videoSpec != nil {
self.videoSpec = nil
if !self.isUpdating {
self.componentState?.updated(transition: .immediate, isLocal: true)
}
}
}
}
let videoLayer: PrivateCallVideoLayer
if let current = self.videoLayer {
videoLayer = current
@@ -473,36 +519,16 @@ final class VideoChatParticipantVideoComponent: Component {
self.videoSource = videoSource
self.videoDisposable?.dispose()
self.videoDisposable = videoSource.addOnUpdated { [weak self] in
guard let self, let videoSource = self.videoSource, let videoLayer = self.videoLayer else {
return
}
let videoOutput = videoSource.currentOutput
videoLayer.video = videoOutput
if let videoOutput {
let videoSpec = VideoSpec(resolution: videoOutput.resolution, rotationAngle: videoOutput.rotationAngle, followsDeviceOrientation: videoOutput.followsDeviceOrientation)
if self.videoSpec != videoSpec || self.awaitingFirstVideoFrameForUnpause {
self.awaitingFirstVideoFrameForUnpause = false
self.videoSpec = videoSpec
if !self.isUpdating {
self.componentState?.updated(transition: ComponentTransition.immediate.withUserData(AnimationHint(kind: .videoAvailabilityChanged)), isLocal: true)
}
}
} else {
if self.videoSpec != nil {
self.videoSpec = nil
if !self.isUpdating {
self.componentState?.updated(transition: .immediate, isLocal: true)
}
}
}
self.videoDisposable = videoSource.addOnUpdated {
videoUpdated()
}
}
}
if let _ = self.videoPlaceholder, videoLayer.video == nil {
videoUpdated()
}
transition.setFrame(layer: videoBackgroundLayer, frame: CGRect(origin: CGPoint(), size: availableSize))
if let videoSpec = self.videoSpec {