diff --git a/submodules/AudioBlob/Sources/BlobView.swift b/submodules/AudioBlob/Sources/BlobView.swift index 27d6080366..dfe97bfe62 100644 --- a/submodules/AudioBlob/Sources/BlobView.swift +++ b/submodules/AudioBlob/Sources/BlobView.swift @@ -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() diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index d1ad73f1e9..2797799d0c 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -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) diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift b/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift index 975ba3a116..48bb82d95d 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift @@ -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 diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatMainStageNode.swift b/submodules/TelegramCallsUI/Sources/VoiceChatMainStageNode.swift index 83ffeaaa34..936a0b4a0d 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatMainStageNode.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatMainStageNode.swift @@ -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 })) }