mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-02 00:17:02 +00:00
Video Chat Improvements
This commit is contained in:
parent
b64860e116
commit
6fc89c71a5
@ -747,6 +747,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
private var currentNormalButtonColor: UIColor?
|
private var currentNormalButtonColor: UIColor?
|
||||||
private var currentActiveButtonColor: UIColor?
|
private var currentActiveButtonColor: UIColor?
|
||||||
|
|
||||||
|
private var mainEntry: VoiceChatPeerEntry?
|
||||||
private var currentEntries: [ListEntry] = []
|
private var currentEntries: [ListEntry] = []
|
||||||
private var currentFullscreenEntries: [ListEntry] = []
|
private var currentFullscreenEntries: [ListEntry] = []
|
||||||
|
|
||||||
@ -1840,7 +1841,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
} else if strongSelf.peerIdToEndpoint.count > 0 {
|
} else if strongSelf.peerIdToEndpoint.count > 0 {
|
||||||
for entry in strongSelf.currentFullscreenEntries {
|
for entry in strongSelf.currentFullscreenEntries {
|
||||||
if case let .peer(peerEntry, _) = entry {
|
if case let .peer(peerEntry, _) = entry {
|
||||||
if let videoEndpointId = peerEntry.effectiveVideoEndpointId {
|
if let _ = peerEntry.effectiveVideoEndpointId {
|
||||||
maxLevelWithVideo = (peerEntry.peer.id, 0.0)
|
maxLevelWithVideo = (peerEntry.peer.id, 0.0)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -4162,11 +4163,11 @@ public final class VoiceChatController: ViewController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateMembers() {
|
private func updateMembers(maybeUpdateVideo: Bool = true) {
|
||||||
self.updateMembers(muteState: self.effectiveMuteState, callMembers: self.currentCallMembers ?? ([], nil), invitedPeers: self.currentInvitedPeers ?? [], speakingPeers: self.currentSpeakingPeers ?? Set())
|
self.updateMembers(muteState: self.effectiveMuteState, callMembers: self.currentCallMembers ?? ([], nil), invitedPeers: self.currentInvitedPeers ?? [], speakingPeers: self.currentSpeakingPeers ?? Set(), maybeUpdateVideo: maybeUpdateVideo)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateMembers(muteState: GroupCallParticipantsContext.Participant.MuteState?, callMembers: ([GroupCallParticipantsContext.Participant], String?), invitedPeers: [Peer], speakingPeers: Set<PeerId>, updatePinnedPeer: Bool = true) {
|
private func updateMembers(muteState: GroupCallParticipantsContext.Participant.MuteState?, callMembers: ([GroupCallParticipantsContext.Participant], String?), invitedPeers: [Peer], speakingPeers: Set<PeerId>, maybeUpdateVideo: Bool = true) {
|
||||||
var disableAnimation = false
|
var disableAnimation = false
|
||||||
if self.currentCallMembers?.1 != callMembers.1 {
|
if self.currentCallMembers?.1 != callMembers.1 {
|
||||||
disableAnimation = true
|
disableAnimation = true
|
||||||
@ -4193,6 +4194,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
var entryByPeerId: [PeerId: VoiceChatPeerEntry] = [:]
|
var entryByPeerId: [PeerId: VoiceChatPeerEntry] = [:]
|
||||||
var latestWideVideo: String? = nil
|
var latestWideVideo: String? = nil
|
||||||
|
|
||||||
|
var mainEntry: VoiceChatPeerEntry?
|
||||||
for member in callMembers.0 {
|
for member in callMembers.0 {
|
||||||
if processedPeerIds.contains(member.peer.id) {
|
if processedPeerIds.contains(member.peer.id) {
|
||||||
continue
|
continue
|
||||||
@ -4270,7 +4272,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
isLandscape: self.isLandscape
|
isLandscape: self.isLandscape
|
||||||
)
|
)
|
||||||
if peerEntry.active {
|
if peerEntry.active {
|
||||||
self.mainStageNode.update(peerEntry: peerEntry, pinned: self.currentForcedSpeaker != nil)
|
mainEntry = peerEntry
|
||||||
}
|
}
|
||||||
entryByPeerId[peerEntry.peer.id] = peerEntry
|
entryByPeerId[peerEntry.peer.id] = peerEntry
|
||||||
|
|
||||||
@ -4392,6 +4394,19 @@ public final class VoiceChatController: ViewController {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let previousMainEntry = self.mainEntry
|
||||||
|
self.mainEntry = mainEntry
|
||||||
|
if let mainEntry = mainEntry {
|
||||||
|
self.mainStageNode.update(peerEntry: mainEntry, pinned: self.currentForcedSpeaker != nil)
|
||||||
|
|
||||||
|
if let previousMainEntry = previousMainEntry, maybeUpdateVideo {
|
||||||
|
if previousMainEntry.effectiveVideoEndpointId != mainEntry.effectiveVideoEndpointId {
|
||||||
|
self.updateMainVideo(waitForFullSize: true, entries: fullscreenEntries, force: true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.updateRequestedVideoChannels()
|
self.updateRequestedVideoChannels()
|
||||||
|
|
||||||
self.endpointToPeerId = endpointIdToPeerId
|
self.endpointToPeerId = endpointIdToPeerId
|
||||||
@ -4557,13 +4572,13 @@ public final class VoiceChatController: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateMainVideo(waitForFullSize: Bool, updateMembers: Bool = true, force: Bool = false, completion: (() -> Void)? = nil) {
|
private func updateMainVideo(waitForFullSize: Bool, entries: [ListEntry]? = nil, updateMembers: Bool = true, force: Bool = false, completion: (() -> Void)? = nil) {
|
||||||
let effectiveMainSpeaker = self.currentForcedSpeaker ?? self.currentDominantSpeaker.flatMap { ($0.0, $0.1) }
|
let effectiveMainSpeaker = self.currentForcedSpeaker ?? self.currentDominantSpeaker.flatMap { ($0.0, $0.1) }
|
||||||
guard effectiveMainSpeaker?.0 != self.effectiveSpeaker?.0 || effectiveMainSpeaker?.1 != self.effectiveSpeaker?.1 || force else {
|
guard effectiveMainSpeaker?.0 != self.effectiveSpeaker?.0 || effectiveMainSpeaker?.1 != self.effectiveSpeaker?.1 || force else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentEntries = self.currentFullscreenEntries
|
let currentEntries = entries ?? self.currentFullscreenEntries
|
||||||
var effectiveSpeaker: (PeerId, String?)? = nil
|
var effectiveSpeaker: (PeerId, String?)? = nil
|
||||||
var anySpeakerWithVideo: (PeerId, String?)? = nil
|
var anySpeakerWithVideo: (PeerId, String?)? = nil
|
||||||
var anySpeaker: PeerId? = nil
|
var anySpeaker: PeerId? = nil
|
||||||
@ -4600,7 +4615,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
|
|
||||||
self.effectiveSpeaker = effectiveSpeaker
|
self.effectiveSpeaker = effectiveSpeaker
|
||||||
if updateMembers {
|
if updateMembers {
|
||||||
self.updateMembers()
|
self.updateMembers(maybeUpdateVideo: false)
|
||||||
}
|
}
|
||||||
self.mainStageNode.update(peer: effectiveSpeaker, waitForFullSize: waitForFullSize, completion: {
|
self.mainStageNode.update(peer: effectiveSpeaker, waitForFullSize: waitForFullSize, completion: {
|
||||||
completion?()
|
completion?()
|
||||||
|
@ -284,10 +284,13 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
private var animatingIn = false
|
private var animatingIn = false
|
||||||
private var animatingOut = false
|
private var animatingOut = false
|
||||||
|
private var appeared = false
|
||||||
|
|
||||||
func animateTransitionIn(from sourceNode: ASDisplayNode, transition: ContainedViewLayoutTransition) {
|
func animateTransitionIn(from sourceNode: ASDisplayNode, transition: ContainedViewLayoutTransition) {
|
||||||
guard let sourceNode = sourceNode as? VoiceChatTileItemNode, let _ = sourceNode.item, let (_, sideInset, bottomInset, isLandscape) = self.validLayout else {
|
guard let sourceNode = sourceNode as? VoiceChatTileItemNode, let _ = sourceNode.item, let (_, sideInset, bottomInset, isLandscape) = self.validLayout else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.appeared = true
|
||||||
|
|
||||||
let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
|
let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
|
||||||
alphaTransition.updateAlpha(node: self.backgroundNode, alpha: 1.0)
|
alphaTransition.updateAlpha(node: self.backgroundNode, alpha: 1.0)
|
||||||
@ -327,6 +330,8 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.appeared = false
|
||||||
|
|
||||||
let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
|
let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
|
||||||
alphaTransition.updateAlpha(node: self.backgroundNode, alpha: 0.0)
|
alphaTransition.updateAlpha(node: self.backgroundNode, alpha: 0.0)
|
||||||
alphaTransition.updateAlpha(node: self.topFadeNode, alpha: 0.0)
|
alphaTransition.updateAlpha(node: self.topFadeNode, alpha: 0.0)
|
||||||
@ -543,14 +548,13 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
self.audioLevelNode.startAnimating(immediately: true)
|
self.audioLevelNode.startAnimating(immediately: true)
|
||||||
|
|
||||||
if let getAudioLevel = self.getAudioLevel, previousPeerEntry?.peer.id != peerEntry.peer.id {
|
if let getAudioLevel = self.getAudioLevel, previousPeerEntry?.peer.id != peerEntry.peer.id {
|
||||||
|
self.audioLevelNode.isHidden = self.currentPeer?.1 != nil
|
||||||
self.audioLevelDisposable.set((getAudioLevel(peerEntry.peer.id)
|
self.audioLevelDisposable.set((getAudioLevel(peerEntry.peer.id)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.audioLevelNode.isHidden = strongSelf.currentPeer?.1 != nil
|
|
||||||
|
|
||||||
let level = min(1.5, max(0.0, CGFloat(value)))
|
let level = min(1.5, max(0.0, CGFloat(value)))
|
||||||
|
|
||||||
strongSelf.audioLevelNode.updateLevel(CGFloat(value))
|
strongSelf.audioLevelNode.updateLevel(CGFloat(value))
|
||||||
@ -590,7 +594,14 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
if let (_, endpointId) = peer {
|
if let (_, endpointId) = peer {
|
||||||
if endpointId != previousPeer?.1 {
|
if endpointId != previousPeer?.1 {
|
||||||
if let endpointId = endpointId {
|
if let endpointId = endpointId {
|
||||||
self.setAvatarHidden(true)
|
var delayTransition = false
|
||||||
|
if previousPeer?.0 == peer?.0 && self.appeared {
|
||||||
|
delayTransition = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !delayTransition {
|
||||||
|
self.setAvatarHidden(true)
|
||||||
|
}
|
||||||
|
|
||||||
self.call.makeIncomingVideoView(endpointId: endpointId, completion: { [weak self] videoView in
|
self.call.makeIncomingVideoView(endpointId: endpointId, completion: { [weak self] videoView in
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
@ -630,6 +641,9 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
strongSelf.currentVideoNode = videoNode
|
strongSelf.currentVideoNode = videoNode
|
||||||
strongSelf.insertSubnode(videoNode, aboveSubnode: strongSelf.backgroundNode)
|
strongSelf.insertSubnode(videoNode, aboveSubnode: strongSelf.backgroundNode)
|
||||||
|
|
||||||
|
if delayTransition {
|
||||||
|
videoNode.alpha = 0.0
|
||||||
|
}
|
||||||
if waitForFullSize {
|
if waitForFullSize {
|
||||||
strongSelf.videoReadyDisposable.set((videoNode.ready
|
strongSelf.videoReadyDisposable.set((videoNode.ready
|
||||||
|> filter { $0 }
|
|> filter { $0 }
|
||||||
@ -643,8 +657,23 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, isLandscape: isLandscape, transition: .immediate)
|
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, isLandscape: isLandscape, transition: .immediate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let previousVideoNode = previousVideoNode {
|
|
||||||
previousVideoNode.removeFromSupernode()
|
if delayTransition {
|
||||||
|
if let videoNode = strongSelf.currentVideoNode {
|
||||||
|
videoNode.alpha = 1.0
|
||||||
|
videoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, completion: { [weak self] _ in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.setAvatarHidden(true)
|
||||||
|
if let previousVideoNode = previousVideoNode {
|
||||||
|
previousVideoNode.removeFromSupernode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let previousVideoNode = previousVideoNode {
|
||||||
|
previousVideoNode.removeFromSupernode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@ -664,9 +693,17 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
self.setAvatarHidden(false)
|
self.setAvatarHidden(false)
|
||||||
if let currentVideoNode = self.currentVideoNode {
|
if self.appeared {
|
||||||
currentVideoNode.removeFromSupernode()
|
if let currentVideoNode = self.currentVideoNode {
|
||||||
self.currentVideoNode = nil
|
currentVideoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak currentVideoNode] _ in
|
||||||
|
currentVideoNode?.removeFromSupernode()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let currentVideoNode = self.currentVideoNode {
|
||||||
|
currentVideoNode.removeFromSupernode()
|
||||||
|
self.currentVideoNode = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user