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 { if !immediately {
mediumBlob.layer.animateScale(from: 0.75, to: 1, duration: 0.35, removeOnCompletion: false) 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) bigBlob.layer.animateScale(from: 0.75, to: 1, duration: 0.35, removeOnCompletion: false)
} else {
mediumBlob.layer.removeAllAnimations()
bigBlob.layer.removeAllAnimations()
} }
updateBlobsState() updateBlobsState()

View File

@ -1625,6 +1625,9 @@ public final class VoiceChatController: ViewController {
if ignore { if ignore {
return nil return nil
} }
if !strongSelf.readyVideoNodes.contains(endpointId) {
return nil
}
for (listEndpointId, videoNode) in strongSelf.videoNodes { for (listEndpointId, videoNode) in strongSelf.videoNodes {
if listEndpointId == endpointId { if listEndpointId == endpointId {
return videoNode return videoNode
@ -4417,6 +4420,22 @@ public final class VoiceChatController: ViewController {
strongSelf.wideVideoNodes.insert(channel.endpointId) strongSelf.wideVideoNodes.insert(channel.endpointId)
} }
strongSelf.updateMembers() 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) }), forKey: channel.endpointId)

View File

@ -188,9 +188,6 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
let videoContainerNode: ASDisplayNode let videoContainerNode: ASDisplayNode
private let videoFadeNode: ASDisplayNode private let videoFadeNode: ASDisplayNode
var videoNode: GroupVideoNode? var videoNode: GroupVideoNode?
private let videoReadyDisposable = MetaDisposable()
private var videoReadyDelayed = false
private var videoReady = false
private var profileNode: VoiceChatPeerProfileNode? private var profileNode: VoiceChatPeerProfileNode?
@ -289,7 +286,6 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
} }
deinit { deinit {
self.videoReadyDisposable.dispose()
self.audioLevelDisposable.dispose() self.audioLevelDisposable.dispose()
self.raiseHandTimer?.invalidate() self.raiseHandTimer?.invalidate()
self.silenceTimer?.invalidate() self.silenceTimer?.invalidate()
@ -544,10 +540,30 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
strongSelf.layoutParams = (item, params, first, last) strongSelf.layoutParams = (item, params, first, last)
strongSelf.wavesColor = wavesColor strongSelf.wavesColor = wavesColor
let videoContainerScale = tileSize.width / videoSize.width
let videoNode = item.getVideo() let videoNode = item.getVideo()
if let current = strongSelf.videoNode, current !== videoNode { if let currentVideoNode = strongSelf.videoNode, currentVideoNode !== videoNode {
current.removeFromSupernode() if videoNode == nil {
strongSelf.videoReadyDisposable.set(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 let videoNodeUpdated = strongSelf.videoNode !== videoNode
@ -821,8 +837,6 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
node.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2) node.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
} }
let videoContainerScale = tileSize.width / videoSize.width
if !strongSelf.isExtracted && !strongSelf.animatingExtraction { if !strongSelf.isExtracted && !strongSelf.animatingExtraction {
strongSelf.videoFadeNode.frame = CGRect(x: 0.0, y: videoSize.height - fadeHeight, width: videoSize.width, height: fadeHeight) strongSelf.videoFadeNode.frame = CGRect(x: 0.0, y: videoSize.height - fadeHeight, width: videoSize.width, height: fadeHeight)
strongSelf.videoContainerNode.bounds = CGRect(origin: CGPoint(), size: videoSize) strongSelf.videoContainerNode.bounds = CGRect(origin: CGPoint(), size: videoSize)
@ -881,7 +895,7 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
if canUpdateAvatarVisibility { if canUpdateAvatarVisibility {
strongSelf.avatarNode.alpha = 1.0 strongSelf.avatarNode.alpha = 1.0
} }
} else if strongSelf.videoReady { } else {
videoNode.alpha = 1.0 videoNode.alpha = 1.0
strongSelf.avatarNode.alpha = 0.0 strongSelf.avatarNode.alpha = 0.0
} }
@ -899,22 +913,8 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
videoNode.bounds = CGRect(origin: CGPoint(), size: videoSize) videoNode.bounds = CGRect(origin: CGPoint(), size: videoSize)
} }
if videoNodeUpdated { if let _ = currentItem, videoNodeUpdated {
strongSelf.videoReadyDelayed = false if item.active {
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 { if canUpdateAvatarVisibility {
strongSelf.avatarNode.alpha = 1.0 strongSelf.avatarNode.alpha = 1.0
} }
@ -925,7 +925,6 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
videoNode.layer.animateScale(from: 0.01, to: 1.0, duration: 0.2) videoNode.layer.animateScale(from: 0.01, to: 1.0, duration: 0.2)
videoNode.alpha = 1.0 videoNode.alpha = 1.0
} }
}
} else { } else {
if item.active { if item.active {
if canUpdateAvatarVisibility { if canUpdateAvatarVisibility {
@ -937,10 +936,6 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
videoNode.alpha = 1.0 videoNode.alpha = 1.0
} }
} }
}
}
}))
}
} else if canUpdateAvatarVisibility { } else if canUpdateAvatarVisibility {
strongSelf.avatarNode.alpha = 1.0 strongSelf.avatarNode.alpha = 1.0
} }

View File

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