mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Video Chat Improvements
This commit is contained in:
parent
ed031f0d4c
commit
d20661d5a9
@ -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()
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
@ -898,48 +912,29 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
videoNode.position = CGPoint(x: videoSize.width / 2.0, y: videoSize.height / 2.0)
|
videoNode.position = CGPoint(x: videoSize.width / 2.0, y: videoSize.height / 2.0)
|
||||||
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
|
if canUpdateAvatarVisibility {
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] ready in
|
strongSelf.avatarNode.alpha = 1.0
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}))
|
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 {
|
} else if canUpdateAvatarVisibility {
|
||||||
strongSelf.avatarNode.alpha = 1.0
|
strongSelf.avatarNode.alpha = 1.0
|
||||||
|
@ -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
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user