diff --git a/submodules/AvatarNode/Sources/AvatarNode.swift b/submodules/AvatarNode/Sources/AvatarNode.swift index 670d1ad420..22b15b4753 100644 --- a/submodules/AvatarNode/Sources/AvatarNode.swift +++ b/submodules/AvatarNode/Sources/AvatarNode.swift @@ -623,11 +623,13 @@ public final class AvatarNode: ASDisplayNode { } } -public func drawPeerAvatarLetters(context: CGContext, size: CGSize, font: UIFont, letters: [String], peerId: PeerId) { - context.beginPath() - context.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: - size.height)) - context.clip() +public func drawPeerAvatarLetters(context: CGContext, size: CGSize, round: Bool = true, font: UIFont, letters: [String], peerId: PeerId) { + if round { + context.beginPath() + context.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: + size.height)) + context.clip() + } let colorIndex: Int if peerId.namespace == .max { diff --git a/submodules/AvatarNode/Sources/PeerAvatar.swift b/submodules/AvatarNode/Sources/PeerAvatar.swift index 4012e26d00..c37effc85b 100644 --- a/submodules/AvatarNode/Sources/PeerAvatar.swift +++ b/submodules/AvatarNode/Sources/PeerAvatar.swift @@ -87,9 +87,9 @@ public func peerAvatarImageData(account: Account, peerReference: PeerReference?, } } -public func peerAvatarCompleteImage(account: Account, peer: Peer, size: CGSize, font: UIFont = avatarPlaceholderFont(size: 13.0), fullSize: Bool = false) -> Signal { +public func peerAvatarCompleteImage(account: Account, peer: Peer, size: CGSize, round: Bool = true, font: UIFont = avatarPlaceholderFont(size: 13.0), drawLetters: Bool = true, fullSize: Bool = false) -> Signal { let iconSignal: Signal - if let signal = peerAvatarImage(account: account, peerReference: PeerReference(peer), authorOfMessage: nil, representation: peer.profileImageRepresentations.first, displayDimensions: size, inset: 0.0, emptyColor: nil, synchronousLoad: fullSize) { + if let signal = peerAvatarImage(account: account, peerReference: PeerReference(peer), authorOfMessage: nil, representation: peer.profileImageRepresentations.first, displayDimensions: size, round: round, inset: 0.0, emptyColor: nil, synchronousLoad: fullSize) { if fullSize, let fullSizeSignal = peerAvatarImage(account: account, peerReference: PeerReference(peer), authorOfMessage: nil, representation: peer.profileImageRepresentations.last, displayDimensions: size, emptyColor: nil, synchronousLoad: true) { iconSignal = combineLatest(.single(nil) |> then(signal), .single(nil) |> then(fullSizeSignal)) |> mapToSignal { thumbnailImage, fullSizeImage -> Signal in @@ -113,10 +113,13 @@ public func peerAvatarCompleteImage(account: Account, peer: Peer, size: CGSize, if displayLetters.count == 2 && displayLetters[0].isSingleEmoji && displayLetters[1].isSingleEmoji { displayLetters = [displayLetters[0]] } + if !drawLetters { + displayLetters = [] + } iconSignal = Signal { subscriber in let image = generateImage(size, rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - drawPeerAvatarLetters(context: context, size: CGSize(width: size.width, height: size.height), font: font, letters: displayLetters, peerId: peerId) + drawPeerAvatarLetters(context: context, size: CGSize(width: size.width, height: size.height), round: round, font: font, letters: displayLetters, peerId: peerId) })?.withRenderingMode(.alwaysOriginal) subscriber.putNext(image) diff --git a/submodules/TelegramCallsUI/Sources/CallControllerNode.swift b/submodules/TelegramCallsUI/Sources/CallControllerNode.swift index 6c5651cc17..ddf2440048 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerNode.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerNode.swift @@ -132,6 +132,14 @@ private final class CallVideoNode: ASDisplayNode { self.isReadyTimer?.invalidate() } + override func didLoad() { + super.didLoad() + + if #available(iOS 13.0, *) { + self.layer.cornerCurve = .continuous + } + } + func animateRadialMask(from fromRect: CGRect, to toRect: CGRect) { let maskLayer = CAShapeLayer() maskLayer.frame = fromRect diff --git a/submodules/TelegramCallsUI/Sources/CallControllerToastNode.swift b/submodules/TelegramCallsUI/Sources/CallControllerToastNode.swift index b8a472ddcd..ddcb9aa279 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerToastNode.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerToastNode.swift @@ -222,9 +222,6 @@ private class CallControllerToastItemNode: ASDisplayNode { self.clipNode = ASDisplayNode() self.clipNode.clipsToBounds = true self.clipNode.layer.cornerRadius = 14.0 - if #available(iOS 13.0, *) { - self.clipNode.layer.cornerCurve = .continuous - } self.effectView = UIVisualEffectView() self.effectView.effect = UIBlurEffect(style: .light) @@ -248,6 +245,14 @@ private class CallControllerToastItemNode: ASDisplayNode { self.clipNode.addSubnode(self.textNode) } + override func didLoad() { + super.didLoad() + + if #available(iOS 13.0, *) { + self.clipNode.layer.cornerCurve = .continuous + } + } + func update(width: CGFloat, content: Content, transition: ContainedViewLayoutTransition) -> CGFloat { let inset: CGFloat = 30.0 let isNarrowScreen = width <= 320.0 diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift b/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift index 48bb82d95d..39fc53d115 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift @@ -688,7 +688,7 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode { strongSelf.audioLevelView = audioLevelView strongSelf.offsetContainerNode.view.insertSubview(audioLevelView, at: 0) - if let item = strongSelf.item, strongSelf.videoNode != nil || item.active { + if let item = strongSelf.item, strongSelf.videoNode != nil && !item.active { audioLevelView.alpha = 0.0 } } diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatMainStageNode.swift b/submodules/TelegramCallsUI/Sources/VoiceChatMainStageNode.swift index 936a0b4a0d..39f45c8eb9 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatMainStageNode.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatMainStageNode.swift @@ -48,12 +48,12 @@ final class VoiceChatMainStageNode: ASDisplayNode { private let audioLevelDisposable = MetaDisposable() private let speakingPeerDisposable = MetaDisposable() private let speakingAudioLevelDisposable = MetaDisposable() - private var avatarNode: ASImageNode + private var backdropAvatarNode: ImageNode + private var backdropEffectView: UIVisualEffectView? + private var avatarNode: ImageNode private let titleNode: ImmediateTextNode private let microphoneNode: VoiceChatMicrophoneNode - - private let avatarDisposable = MetaDisposable() - + private let speakingContainerNode: ASDisplayNode private var speakingEffectView: UIVisualEffectView? private let speakingAvatarNode: AvatarNode @@ -129,7 +129,12 @@ final class VoiceChatMainStageNode: ASDisplayNode { self.pinButtonTitleNode.attributedText = NSAttributedString(string: "Unpin", font: Font.regular(17.0), textColor: .white) self.pinButtonNode = HighlightableButtonNode() - self.avatarNode = ASImageNode() + self.backdropAvatarNode = ImageNode() + self.backdropAvatarNode.contentMode = .scaleAspectFill + self.backdropAvatarNode.displaysAsynchronously = false + self.backdropAvatarNode.isHidden = true + + self.avatarNode = ImageNode() self.avatarNode.displaysAsynchronously = false self.avatarNode.isHidden = true @@ -152,14 +157,12 @@ final class VoiceChatMainStageNode: ASDisplayNode { self.clipsToBounds = true self.cornerRadius = backgroundCornerRadius - if #available(iOS 13.0, *) { - self.layer.cornerCurve = .continuous - } self.addSubnode(self.backgroundNode) self.addSubnode(self.topFadeNode) self.addSubnode(self.bottomFadeNode) self.addSubnode(self.bottomFillNode) + self.addSubnode(self.backdropAvatarNode) self.addSubnode(self.avatarNode) self.addSubnode(self.titleNode) self.addSubnode(self.microphoneNode) @@ -215,7 +218,6 @@ final class VoiceChatMainStageNode: ASDisplayNode { } deinit { - self.avatarDisposable.dispose() self.videoReadyDisposable.dispose() self.audioLevelDisposable.dispose() self.speakingPeerDisposable.dispose() @@ -226,10 +228,25 @@ final class VoiceChatMainStageNode: ASDisplayNode { override func didLoad() { super.didLoad() + if #available(iOS 13.0, *) { + self.layer.cornerCurve = .continuous + } + let speakingEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark)) self.speakingContainerNode.view.insertSubview(speakingEffectView, at: 0) self.speakingEffectView = speakingEffectView + let effect: UIVisualEffect + if #available(iOS 13.0, *) { + effect = UIBlurEffect(style: .systemMaterialDark) + } else { + effect = UIBlurEffect(style: .dark) + } + let backdropEffectView = UIVisualEffectView(effect: effect) + backdropEffectView.isHidden = true + self.view.insertSubview(backdropEffectView, aboveSubview: self.backdropAvatarNode.view) + self.backdropEffectView = backdropEffectView + self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tap))) self.speakingContainerNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.speakingTap))) @@ -476,12 +493,8 @@ final class VoiceChatMainStageNode: ASDisplayNode { if !arePeersEqual(previousPeerEntry?.peer, peerEntry.peer) { let peer = peerEntry.peer let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } - self.avatarDisposable.set((peerAvatarCompleteImage(account: self.context.account, peer: peer, size: CGSize(width: 180.0, height: 180.0), font: avatarPlaceholderFont(size: 78.0), fullSize: true) - |> deliverOnMainQueue).start(next: { [weak self] image in - if let strongSelf = self { - strongSelf.avatarNode.image = image - } - })) + self.backdropAvatarNode.setSignal(peerAvatarCompleteImage(account: self.context.account, peer: peer, size: CGSize(width: 180.0, height: 180.0), round: false, font: avatarPlaceholderFont(size: 78.0), drawLetters: false)) + self.avatarNode.setSignal(peerAvatarCompleteImage(account: self.context.account, peer: peer, size: CGSize(width: 180.0, height: 180.0), font: avatarPlaceholderFont(size: 78.0), fullSize: true)) self.titleNode.attributedText = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.semibold(15.0), textColor: .white) if let (size, sideInset, bottomInset, isLandscape) = self.validLayout { self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, isLandscape: isLandscape, transition: .immediate) @@ -581,6 +594,13 @@ final class VoiceChatMainStageNode: ASDisplayNode { self.microphoneNode.update(state: VoiceChatMicrophoneNode.State(muted: muted, filled: true, color: .white), animated: true) } + private func setAvatarHidden(_ hidden: Bool) { + self.backdropAvatarNode.isHidden = hidden + self.backdropEffectView?.isHidden = hidden + self.avatarNode.isHidden = hidden + self.audioLevelView?.isHidden = hidden + } + func update(peer: (peer: PeerId, endpointId: String?)?, waitForFullSize: Bool, completion: (() -> Void)? = nil) { let previousPeer = self.currentPeer if previousPeer?.0 == peer?.0 && previousPeer?.1 == peer?.1 { @@ -594,8 +614,7 @@ final class VoiceChatMainStageNode: ASDisplayNode { if let (_, endpointId) = peer { if endpointId != previousPeer?.1 { if let endpointId = endpointId { - self.avatarNode.isHidden = true - self.audioLevelView?.isHidden = true + self.setAvatarHidden(true) self.call.makeIncomingVideoView(endpointId: endpointId, completion: { [weak self] videoView in Queue.mainQueue().async { @@ -643,15 +662,14 @@ final class VoiceChatMainStageNode: ASDisplayNode { } }) } else { - self.avatarNode.isHidden = false - self.audioLevelView?.isHidden = false + self.setAvatarHidden(false) if let currentVideoNode = self.currentVideoNode { currentVideoNode.removeFromSupernode() self.currentVideoNode = nil } } } else { - self.audioLevelView?.isHidden = self.currentPeer?.1 != nil + self.setAvatarHidden(endpointId != nil) completion?() } } else { @@ -705,6 +723,10 @@ final class VoiceChatMainStageNode: ASDisplayNode { } transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) + transition.updateFrame(node: self.backdropAvatarNode, frame: CGRect(origin: CGPoint(), size: size)) + if let backdropEffectView = self.backdropEffectView { + transition.updateFrame(view: backdropEffectView, frame: CGRect(origin: CGPoint(), size: size)) + } let avatarSize = CGSize(width: 180.0, height: 180.0) let avatarFrame = CGRect(origin: CGPoint(x: (size.width - avatarSize.width) / 2.0, y: (size.height - avatarSize.height) / 2.0), size: avatarSize) diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatTileItemNode.swift b/submodules/TelegramCallsUI/Sources/VoiceChatTileItemNode.swift index 7928b9e5f8..207868260b 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatTileItemNode.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatTileItemNode.swift @@ -129,9 +129,7 @@ final class VoiceChatTileItemNode: ASDisplayNode { self.contentNode = ASDisplayNode() self.contentNode.clipsToBounds = true self.contentNode.cornerRadius = backgroundCornerRadius - if #available(iOS 13.0, *) { - self.contentNode.layer.cornerCurve = .continuous - } + self.backgroundNode = ASDisplayNode() self.backgroundNode.backgroundColor = panelBackgroundColor @@ -203,6 +201,10 @@ final class VoiceChatTileItemNode: ASDisplayNode { override func didLoad() { super.didLoad() + if #available(iOS 13.0, *) { + self.contentNode.layer.cornerCurve = .continuous + } + self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tap))) }