Video Chat Improvements

This commit is contained in:
Ilya Laktyushin 2021-05-22 12:12:27 +04:00
parent ed031f0d4c
commit d20661d5a9
4 changed files with 71 additions and 52 deletions

View File

@ -114,6 +114,9 @@ public final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDeco
if !immediately {
mediumBlob.layer.animateScale(from: 0.75, to: 1, duration: 0.35, removeOnCompletion: false)
bigBlob.layer.animateScale(from: 0.75, to: 1, duration: 0.35, removeOnCompletion: false)
} else {
mediumBlob.layer.removeAllAnimations()
bigBlob.layer.removeAllAnimations()
}
updateBlobsState()

View File

@ -1625,6 +1625,9 @@ public final class VoiceChatController: ViewController {
if ignore {
return nil
}
if !strongSelf.readyVideoNodes.contains(endpointId) {
return nil
}
for (listEndpointId, videoNode) in strongSelf.videoNodes {
if listEndpointId == endpointId {
return videoNode
@ -4417,6 +4420,22 @@ public final class VoiceChatController: ViewController {
strongSelf.wideVideoNodes.insert(channel.endpointId)
}
strongSelf.updateMembers()
if let interaction = strongSelf.itemInteraction {
loop: for i in 0 ..< strongSelf.currentFullscreenEntries.count {
let entry = strongSelf.currentFullscreenEntries[i]
switch entry {
case let .peer(peerEntry, _):
if peerEntry.effectiveVideoEndpointId == channel.endpointId {
let presentationData = strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme)
strongSelf.fullscreenListNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [ListViewUpdateItem(index: i, previousIndex: i, item: entry.fullscreenItem(context: strongSelf.context, presentationData: presentationData, interaction: interaction), directionHint: nil)], options: [.Synchronous], updateOpaqueState: nil)
break loop
}
default:
break
}
}
}
}
}
}), forKey: channel.endpointId)

View File

@ -188,9 +188,6 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
let videoContainerNode: ASDisplayNode
private let videoFadeNode: ASDisplayNode
var videoNode: GroupVideoNode?
private let videoReadyDisposable = MetaDisposable()
private var videoReadyDelayed = false
private var videoReady = false
private var profileNode: VoiceChatPeerProfileNode?
@ -289,7 +286,6 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
}
deinit {
self.videoReadyDisposable.dispose()
self.audioLevelDisposable.dispose()
self.raiseHandTimer?.invalidate()
self.silenceTimer?.invalidate()
@ -544,10 +540,30 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
strongSelf.layoutParams = (item, params, first, last)
strongSelf.wavesColor = wavesColor
let videoContainerScale = tileSize.width / videoSize.width
let videoNode = item.getVideo()
if let current = strongSelf.videoNode, current !== videoNode {
current.removeFromSupernode()
strongSelf.videoReadyDisposable.set(nil)
if let currentVideoNode = strongSelf.videoNode, currentVideoNode !== videoNode {
if videoNode == nil {
let transition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
if strongSelf.avatarNode.alpha.isZero {
strongSelf.animatingSelection = true
strongSelf.videoContainerNode.layer.animateScale(from: videoContainerScale, to: 0.001, duration: 0.2)
strongSelf.avatarNode.layer.animateScale(from: 0.0, to: 1.0, duration: 0.2, completion: { [weak self] _ in
self?.animatingSelection = false
})
strongSelf.videoContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -9.0), duration: 0.2, additive: true)
strongSelf.audioLevelView?.layer.animateScale(from: 0.0, to: 1.0, duration: 0.2)
}
transition.updateAlpha(node: currentVideoNode, alpha: 0.0)
transition.updateAlpha(node: strongSelf.videoFadeNode, alpha: 0.0)
transition.updateAlpha(node: strongSelf.avatarNode, alpha: 1.0)
if let audioLevelView = strongSelf.audioLevelView {
transition.updateAlpha(layer: audioLevelView.layer, alpha: 1.0)
}
} else {
currentVideoNode.removeFromSupernode()
}
}
let videoNodeUpdated = strongSelf.videoNode !== videoNode
@ -821,8 +837,6 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
node.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
}
let videoContainerScale = tileSize.width / videoSize.width
if !strongSelf.isExtracted && !strongSelf.animatingExtraction {
strongSelf.videoFadeNode.frame = CGRect(x: 0.0, y: videoSize.height - fadeHeight, width: videoSize.width, height: fadeHeight)
strongSelf.videoContainerNode.bounds = CGRect(origin: CGPoint(), size: videoSize)
@ -881,7 +895,7 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
if canUpdateAvatarVisibility {
strongSelf.avatarNode.alpha = 1.0
}
} else if strongSelf.videoReady {
} else {
videoNode.alpha = 1.0
strongSelf.avatarNode.alpha = 0.0
}
@ -898,48 +912,29 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
videoNode.position = CGPoint(x: videoSize.width / 2.0, y: videoSize.height / 2.0)
videoNode.bounds = CGRect(origin: CGPoint(), size: videoSize)
}
if videoNodeUpdated {
strongSelf.videoReadyDelayed = false
strongSelf.videoReadyDisposable.set((videoNode.ready
|> deliverOnMainQueue).start(next: { [weak self] ready in
if let strongSelf = self {
if !ready {
strongSelf.videoReadyDelayed = true
}
strongSelf.videoReady = ready
if let videoNode = strongSelf.videoNode, ready {
if strongSelf.videoReadyDelayed {
Queue.mainQueue().after(0.15) {
guard let currentItem = strongSelf.item else {
return
}
if currentItem.active {
if canUpdateAvatarVisibility {
strongSelf.avatarNode.alpha = 1.0
}
videoNode.alpha = 0.0
} else {
strongSelf.avatarNode.alpha = 0.0
strongSelf.avatarNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
videoNode.layer.animateScale(from: 0.01, to: 1.0, duration: 0.2)
videoNode.alpha = 1.0
}
}
} else {
if item.active {
if canUpdateAvatarVisibility {
strongSelf.avatarNode.alpha = 1.0
}
videoNode.alpha = 0.0
} else {
strongSelf.avatarNode.alpha = 0.0
videoNode.alpha = 1.0
}
}
}
if let _ = currentItem, videoNodeUpdated {
if item.active {
if canUpdateAvatarVisibility {
strongSelf.avatarNode.alpha = 1.0
}
}))
videoNode.alpha = 0.0
} else {
strongSelf.avatarNode.alpha = 0.0
strongSelf.avatarNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
videoNode.layer.animateScale(from: 0.01, to: 1.0, duration: 0.2)
videoNode.alpha = 1.0
}
} else {
if item.active {
if canUpdateAvatarVisibility {
strongSelf.avatarNode.alpha = 1.0
}
videoNode.alpha = 0.0
} else {
strongSelf.avatarNode.alpha = 0.0
videoNode.alpha = 1.0
}
}
} else if canUpdateAvatarVisibility {
strongSelf.avatarNode.alpha = 1.0

View File

@ -491,6 +491,7 @@ final class VoiceChatMainStageNode: ASDisplayNode {
self.pinButtonTitleNode.isHidden = !pinned
self.pinButtonIconNode.image = !pinned ? generateTintedImage(image: UIImage(bundleImageName: "Call/Pin"), color: .white) : generateTintedImage(image: UIImage(bundleImageName: "Call/Unpin"), color: .white)
var firstTime = true
var wavesColor = UIColor(rgb: 0x34c759)
if let getAudioLevel = self.getAudioLevel, previousPeerEntry?.peer.id != peerEntry.peer.id {
if let audioLevelView = self.audioLevelView {
@ -528,7 +529,7 @@ final class VoiceChatMainStageNode: ASDisplayNode {
let avatarScale: CGFloat
if value > 0.02 {
audioLevelView.startAnimating(immediately: true)
audioLevelView.startAnimating(immediately: firstTime)
avatarScale = 1.03 + level * 0.13
audioLevelView.setColor(wavesColor, animated: true)
@ -551,6 +552,7 @@ final class VoiceChatMainStageNode: ASDisplayNode {
let transition: ContainedViewLayoutTransition = .animated(duration: 0.15, curve: .easeInOut)
transition.updateTransformScale(node: strongSelf.avatarNode, scale: avatarScale, beginWithCurrentState: true)
}
firstTime = false
}))
}