mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-04 10:30:42 +00:00
Merge commit '4efe0468c5b051df8706d83cc1f219add75a1a7d'
This commit is contained in:
commit
3ae13c31df
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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<UIImage?, NoError> {
|
||||
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<UIImage?, NoError> {
|
||||
let iconSignal: Signal<UIImage?, NoError>
|
||||
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<UIImage?, NoError> 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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -723,6 +723,7 @@ public final class VoiceChatController: ViewController {
|
||||
private var animatingAppearance = false
|
||||
private var animatingButtonsSwap = false
|
||||
private var panGestureArguments: (topInset: CGFloat, offset: CGFloat)?
|
||||
private var isPanning = false
|
||||
|
||||
private var peer: Peer?
|
||||
private var currentTitle: String = ""
|
||||
@ -826,11 +827,7 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var effectiveDisplayMode: DisplayMode {
|
||||
return self.displayMode
|
||||
}
|
||||
|
||||
|
||||
private var isExpanded: Bool {
|
||||
switch self.displayMode {
|
||||
case .modal(true, _), .fullscreen:
|
||||
@ -1060,7 +1057,7 @@ public final class VoiceChatController: ViewController {
|
||||
if peerId != strongSelf.currentDominantSpeaker?.0 {
|
||||
strongSelf.currentDominantSpeaker = (peerId, CACurrentMediaTime())
|
||||
}
|
||||
strongSelf.updateMainVideo(waitForFullSize: false, updateMembers: true, force: true)
|
||||
strongSelf.updateMainVideo(waitForFullSize: true, updateMembers: true, force: true)
|
||||
}
|
||||
}
|
||||
}, openInvite: { [weak self] in
|
||||
@ -1628,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
|
||||
@ -2005,18 +2005,6 @@ public final class VoiceChatController: ViewController {
|
||||
self.mainStageNode.switchTo = { [weak self] peerId in
|
||||
if let strongSelf = self, let interaction = strongSelf.itemInteraction {
|
||||
interaction.switchToPeer(peerId, nil, false)
|
||||
|
||||
// let position: ListViewScrollPosition
|
||||
// var index: Int = 0
|
||||
// if index > strongSelf.currentFullscreenEntries.count - 3 {
|
||||
// index = strongSelf.currentFullscreenEntries.count - 1
|
||||
// position = .bottom(0.0)
|
||||
// } else {
|
||||
// position = .center(.bottom)
|
||||
// }
|
||||
// strongSelf.fullscreenListNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: index, position: position, animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in
|
||||
// completion()
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
||||
@ -3111,7 +3099,7 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
|
||||
private var isFullscreen: Bool {
|
||||
switch self.effectiveDisplayMode {
|
||||
switch self.displayMode {
|
||||
case .fullscreen(_), .modal(_, true):
|
||||
return true
|
||||
default:
|
||||
@ -3137,7 +3125,7 @@ public final class VoiceChatController: ViewController {
|
||||
|
||||
let layoutTopInset: CGFloat = max(layout.statusBarHeight ?? 0.0, layout.safeInsets.top)
|
||||
let listTopInset = isLandscape ? topPanelHeight : layoutTopInset + topPanelHeight
|
||||
let bottomPanelHeight = isLandscape ? layout.intrinsicInsets.bottom : self.effectiveBottomAreaHeight + layout.intrinsicInsets.bottom
|
||||
let bottomPanelHeight = isLandscape ? layout.intrinsicInsets.bottom : bottomAreaHeight + layout.intrinsicInsets.bottom
|
||||
|
||||
var size = layout.size
|
||||
if case .regular = layout.metrics.widthClass {
|
||||
@ -3218,12 +3206,10 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
|
||||
var bottomInset: CGFloat = 0.0
|
||||
var bottomEdgeInset: CGFloat = 0.0
|
||||
if case let .fullscreen(controlsHidden) = self.effectiveDisplayMode {
|
||||
if case let .fullscreen(controlsHidden) = self.displayMode {
|
||||
if !controlsHidden {
|
||||
bottomInset = 80.0
|
||||
}
|
||||
bottomEdgeInset = 154.0
|
||||
}
|
||||
transition.updateAlpha(node: self.bottomGradientNode, alpha: self.isLandscape ? 0.0 : 1.0)
|
||||
|
||||
@ -3277,14 +3263,13 @@ public final class VoiceChatController: ViewController {
|
||||
self.topPanelBackgroundNode.frame = CGRect(x: 0.0, y: topPanelHeight - 24.0, width: size.width, height: min(topPanelFrame.height, 24.0))
|
||||
|
||||
let listMaxY = listTopInset + listSize.height
|
||||
let bottomOffset: CGFloat = min(0.0, bottomEdge - listMaxY) + layout.size.height - bottomPanelHeight
|
||||
let bottomDelta = bottomGradientHeight - bottomEdgeInset
|
||||
|
||||
let bottomCornersFrame = CGRect(origin: CGPoint(x: sideInset + floorToScreenPixels((size.width - contentWidth) / 2.0), y: -50.0 + bottomOffset + bottomDelta), size: CGSize(width: contentWidth - sideInset * 2.0, height: 50.0))
|
||||
let bottomOffset = min(0.0, bottomEdge - listMaxY) + layout.size.height - bottomPanelHeight
|
||||
|
||||
let bottomCornersFrame = CGRect(origin: CGPoint(x: sideInset + floorToScreenPixels((size.width - contentWidth) / 2.0), y: -50.0 + bottomOffset + bottomGradientHeight), size: CGSize(width: contentWidth - sideInset * 2.0, height: 50.0))
|
||||
let previousBottomCornersFrame = self.bottomCornersNode.frame
|
||||
if !bottomCornersFrame.equalTo(previousBottomCornersFrame) {
|
||||
self.bottomCornersNode.frame = bottomCornersFrame
|
||||
self.bottomPanelBackgroundNode.frame = CGRect(x: 0.0, y: bottomOffset + bottomDelta, width: size.width, height: 2000.0)
|
||||
self.bottomPanelBackgroundNode.frame = CGRect(x: 0.0, y: bottomOffset + bottomGradientHeight, width: size.width, height: 2000.0)
|
||||
|
||||
let positionDelta = CGPoint(x: 0.0, y: previousBottomCornersFrame.minY - bottomCornersFrame.minY)
|
||||
transition.animatePositionAdditive(node: self.bottomCornersNode, offset: positionDelta)
|
||||
@ -3299,8 +3284,7 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
|
||||
let isFullscreen = self.isFullscreen
|
||||
let isLandscape = self.isLandscape
|
||||
let effectiveDisplayMode = self.effectiveDisplayMode
|
||||
let effectiveDisplayMode = self.displayMode
|
||||
|
||||
self.controller?.statusBar.updateStatusBarStyle(isFullscreen ? .White : .Ignore, animated: true)
|
||||
|
||||
@ -3324,11 +3308,7 @@ public final class VoiceChatController: ViewController {
|
||||
|
||||
let backgroundColor: UIColor
|
||||
if case .fullscreen = effectiveDisplayMode {
|
||||
if isLandscape {
|
||||
backgroundColor = isFullscreen ? panelBackgroundColor : secondaryPanelBackgroundColor
|
||||
} else {
|
||||
backgroundColor = fullscreenBackgroundColor
|
||||
}
|
||||
backgroundColor = isFullscreen ? panelBackgroundColor : secondaryPanelBackgroundColor
|
||||
} else if self.isScheduling || self.callState?.scheduleTimestamp != nil {
|
||||
backgroundColor = panelBackgroundColor
|
||||
} else {
|
||||
@ -3578,7 +3558,7 @@ public final class VoiceChatController: ViewController {
|
||||
|
||||
|
||||
if previousIsLandscape != isLandscape {
|
||||
if case .modal = self.effectiveDisplayMode {
|
||||
if case .modal = self.displayMode {
|
||||
self.displayMode = .modal(isExpanded: true, isFilled: true)
|
||||
}
|
||||
self.updateDecorationsColors()
|
||||
@ -3586,7 +3566,7 @@ public final class VoiceChatController: ViewController {
|
||||
self.updateMembers()
|
||||
}
|
||||
|
||||
let effectiveDisplayMode = self.effectiveDisplayMode
|
||||
let effectiveDisplayMode = self.displayMode
|
||||
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - contentWidth) / 2.0), y: 10.0), size: CGSize(width: contentWidth, height: 44.0)))
|
||||
self.updateTitle(transition: transition)
|
||||
@ -4440,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)
|
||||
@ -4595,7 +4591,9 @@ public final class VoiceChatController: ViewController {
|
||||
|
||||
self.controller?.dismissAllTooltips()
|
||||
|
||||
if case .fullscreen = self.effectiveDisplayMode {
|
||||
if case .fullscreen = self.displayMode {
|
||||
self.isPanning = true
|
||||
|
||||
self.mainStageBackgroundNode.alpha = 0.0
|
||||
self.mainStageBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.4)
|
||||
self.mainStageNode.setControlsHidden(true, animated: true)
|
||||
@ -4613,7 +4611,7 @@ public final class VoiceChatController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
switch self.effectiveDisplayMode {
|
||||
switch self.displayMode {
|
||||
case let .modal(isExpanded, previousIsFilled):
|
||||
var topInset: CGFloat = 0.0
|
||||
if let (currentTopInset, currentPanOffset) = self.panGestureArguments {
|
||||
@ -4699,13 +4697,14 @@ public final class VoiceChatController: ViewController {
|
||||
topInset = self.listNode.frame.height
|
||||
}
|
||||
|
||||
if case .fullscreen = self.effectiveDisplayMode {
|
||||
if case .fullscreen = self.displayMode {
|
||||
self.panGestureArguments = nil
|
||||
if abs(translation.y) > 100.0 || abs(velocity.y) > 300.0 {
|
||||
self.currentForcedSpeaker = nil
|
||||
self.updateDisplayMode(.modal(isExpanded: true, isFilled: true), fromPan: true)
|
||||
self.effectiveSpeaker = nil
|
||||
} else {
|
||||
self.isPanning = false
|
||||
self.mainStageBackgroundNode.alpha = 1.0
|
||||
self.mainStageBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, completion: { [weak self] _ in
|
||||
self?.attachFullscreenVideos()
|
||||
@ -4725,7 +4724,7 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if case .modal(true, _) = self.effectiveDisplayMode {
|
||||
} else if case .modal(true, _) = self.displayMode {
|
||||
self.panGestureArguments = nil
|
||||
if velocity.y > 300.0 || offset > topInset / 2.0 {
|
||||
self.displayMode = .modal(isExpanded: false, isFilled: false)
|
||||
@ -4758,7 +4757,7 @@ public final class VoiceChatController: ViewController {
|
||||
if self.isScheduling {
|
||||
self.dismissScheduled()
|
||||
} else {
|
||||
if case .fullscreen = self.effectiveDisplayMode {
|
||||
if case .fullscreen = self.displayMode {
|
||||
} else {
|
||||
self.controller?.dismiss(closing: false, manual: true)
|
||||
dismissing = true
|
||||
@ -4771,7 +4770,7 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
if case .modal = self.effectiveDisplayMode {
|
||||
if case .modal = self.displayMode {
|
||||
self.displayMode = .modal(isExpanded: true, isFilled: true)
|
||||
}
|
||||
self.updateDecorationsColors()
|
||||
@ -4818,6 +4817,28 @@ public final class VoiceChatController: ViewController {
|
||||
self.updateDecorationsLayout(transition: .animated(duration: 0.3, curve: .easeInOut), completion: {
|
||||
self.animatingExpansion = false
|
||||
})
|
||||
|
||||
if case .fullscreen = self.displayMode {
|
||||
self.isPanning = false
|
||||
self.mainStageBackgroundNode.alpha = 1.0
|
||||
self.mainStageBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, completion: { [weak self] _ in
|
||||
self?.attachFullscreenVideos()
|
||||
})
|
||||
self.mainStageNode.setControlsHidden(false, animated: true)
|
||||
|
||||
self.fullscreenListNode.alpha = 1.0
|
||||
self.fullscreenListNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, delay: 0.15)
|
||||
|
||||
var bounds = self.mainStageContainerNode.bounds
|
||||
let previousBounds = bounds
|
||||
bounds.origin.y = 0.0
|
||||
self.mainStageContainerNode.bounds = bounds
|
||||
self.mainStageContainerNode.layer.animateBounds(from: previousBounds, to: self.mainStageContainerNode.bounds, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring, completion: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.contentContainer.insertSubnode(strongSelf.mainStageContainerNode, belowSubnode: strongSelf.transitionContainerNode)
|
||||
}
|
||||
})
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -5277,13 +5298,17 @@ public final class VoiceChatController: ViewController {
|
||||
}
|
||||
|
||||
self.fullscreenListNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? VoiceChatFullscreenParticipantItemNode, let item = itemNode.item, let otherItemNode = verticalItemNodes[item.peer.id] {
|
||||
itemNode.animateTransitionIn(from: otherItemNode, containerNode: self.transitionContainerNode, transition: transition, animate: item.peer.id != effectiveSpeakerPeerId)
|
||||
if let itemNode = itemNode as? VoiceChatFullscreenParticipantItemNode, let item = itemNode.item {
|
||||
itemNode.animateTransitionIn(from: verticalItemNodes[item.peer.id], containerNode: self.transitionContainerNode, transition: transition, animate: item.peer.id != effectiveSpeakerPeerId)
|
||||
}
|
||||
}
|
||||
|
||||
if self.isLandscape {
|
||||
self.transitionMaskTopFillLayer.opacity = 1.0
|
||||
}
|
||||
self.transitionMaskBottomFillLayer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, removeOnCompletion: false, completion: { [weak self] _ in
|
||||
Queue.mainQueue().after(0.2) {
|
||||
self?.transitionMaskTopFillLayer.opacity = 0.0
|
||||
self?.transitionMaskBottomFillLayer.removeAllAnimations()
|
||||
}
|
||||
})
|
||||
@ -5378,6 +5403,8 @@ public final class VoiceChatController: ViewController {
|
||||
strongSelf.mainStageContainerNode.bounds = bounds
|
||||
|
||||
strongSelf.contentContainer.insertSubnode(strongSelf.mainStageContainerNode, belowSubnode: strongSelf.transitionContainerNode)
|
||||
|
||||
strongSelf.isPanning = false
|
||||
})
|
||||
|
||||
self.transitionMaskTopFillLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15)
|
||||
|
@ -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()
|
||||
@ -300,7 +296,7 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
||||
self.layoutParams?.0.action?(self.contextSourceNode)
|
||||
}
|
||||
|
||||
func animateTransitionIn(from sourceNode: ASDisplayNode, containerNode: ASDisplayNode, transition: ContainedViewLayoutTransition, animate: Bool = true) {
|
||||
func animateTransitionIn(from sourceNode: ASDisplayNode?, containerNode: ASDisplayNode, transition: ContainedViewLayoutTransition, animate: Bool = true) {
|
||||
guard let item = self.item else {
|
||||
return
|
||||
}
|
||||
@ -372,7 +368,7 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
||||
self.contentWrapperNode.layer.animateScale(from: 0.001, to: 1.0, duration: duration, timingFunction: timingFunction)
|
||||
self.contentWrapperNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, timingFunction: timingFunction)
|
||||
} else if !initialAnimate {
|
||||
if case .animated = transition {
|
||||
if transition.isAnimated {
|
||||
self.contextSourceNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, timingFunction: timingFunction)
|
||||
self.contextSourceNode.layer.animateScale(from: 0.0, to: 1.0, duration: duration, timingFunction: timingFunction)
|
||||
}
|
||||
@ -380,7 +376,7 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
||||
} else if let sourceNode = sourceNode as? VoiceChatParticipantItemNode, let _ = sourceNode.item {
|
||||
var startContainerPosition = sourceNode.avatarNode.view.convert(sourceNode.avatarNode.bounds, to: containerNode.view).center
|
||||
var animate = true
|
||||
if startContainerPosition.y > containerNode.frame.height {
|
||||
if startContainerPosition.y < -tileHeight || startContainerPosition.y > containerNode.frame.height + tileHeight {
|
||||
animate = false
|
||||
}
|
||||
startContainerPosition = startContainerPosition.offsetBy(dx: 0.0, dy: 9.0)
|
||||
@ -416,6 +412,11 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
||||
self.contentWrapperNode.layer.animateScale(from: 0.001, to: 1.0, duration: duration, timingFunction: timingFunction)
|
||||
self.contentWrapperNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, timingFunction: timingFunction)
|
||||
}
|
||||
} else {
|
||||
if transition.isAnimated {
|
||||
self.contextSourceNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, timingFunction: timingFunction)
|
||||
self.contextSourceNode.layer.animateScale(from: 0.0, to: 1.0, duration: duration, timingFunction: timingFunction)
|
||||
}
|
||||
}
|
||||
}
|
||||
private func updateIsExtracted(_ isExtracted: Bool, transition: ContainedViewLayoutTransition) {
|
||||
@ -539,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
|
||||
@ -667,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
|
||||
}
|
||||
}
|
||||
@ -816,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)
|
||||
@ -842,8 +861,11 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
||||
if currentItem != nil {
|
||||
if item.active {
|
||||
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)
|
||||
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)
|
||||
}
|
||||
@ -873,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
|
||||
}
|
||||
@ -890,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
|
||||
|
@ -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)
|
||||
@ -491,6 +504,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 +542,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 +565,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
|
||||
}))
|
||||
}
|
||||
|
||||
@ -579,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 {
|
||||
@ -592,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 {
|
||||
@ -607,28 +628,32 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
||||
let previousVideoNode = strongSelf.currentVideoNode
|
||||
strongSelf.currentVideoNode = videoNode
|
||||
strongSelf.insertSubnode(videoNode, aboveSubnode: strongSelf.backgroundNode)
|
||||
if let previousVideoNode = previousVideoNode {
|
||||
Queue.mainQueue().after(0.03) {
|
||||
previousVideoNode.removeFromSupernode()
|
||||
}
|
||||
// currentVideoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak currentVideoNode] _ in
|
||||
// currentVideoNode?.removeFromSupernode()
|
||||
// })
|
||||
}
|
||||
if let (size, sideInset, bottomInset, isLandscape) = strongSelf.validLayout {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, isLandscape: isLandscape, transition: .immediate)
|
||||
}
|
||||
|
||||
if waitForFullSize {
|
||||
strongSelf.videoReadyDisposable.set((videoNode.ready
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { _ in
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
Queue.mainQueue().after(0.07) {
|
||||
completion?()
|
||||
|
||||
if let strongSelf = self {
|
||||
if let (size, sideInset, bottomInset, isLandscape) = strongSelf.validLayout {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, isLandscape: isLandscape, transition: .immediate)
|
||||
}
|
||||
}
|
||||
if let previousVideoNode = previousVideoNode {
|
||||
previousVideoNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
if let (size, sideInset, bottomInset, isLandscape) = strongSelf.validLayout {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, isLandscape: isLandscape, transition: .immediate)
|
||||
}
|
||||
if let previousVideoNode = previousVideoNode {
|
||||
previousVideoNode.removeFromSupernode()
|
||||
}
|
||||
strongSelf.videoReadyDisposable.set(nil)
|
||||
completion?()
|
||||
}
|
||||
@ -637,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 {
|
||||
@ -699,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)
|
||||
|
@ -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)))
|
||||
}
|
||||
|
||||
@ -405,12 +407,6 @@ final class VoiceChatTileItemNode: ASDisplayNode {
|
||||
videoNode.alpha = 1.0
|
||||
self.videoNode = videoNode
|
||||
self.videoContainerNode.addSubnode(videoNode)
|
||||
|
||||
if animate {
|
||||
// self.videoContainerNode.layer.animateScale(from: sourceNode.bounds.width / videoSize.width, to: tileSize.width / videoSize.width, duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
||||
// self.videoContainerNode.layer.animate(from: (tileSize.width / 2.0) as NSNumber, to: videoCornerRadius as NSNumber, keyPath: "cornerRadius", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.2, removeOnCompletion: false, completion: { _ in
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
||||
if animate {
|
||||
@ -445,7 +441,9 @@ final class VoiceChatTileItemNode: ASDisplayNode {
|
||||
sourceNode.layer.animateScale(from: 1.0, to: 0.0, duration: duration, timingFunction: timingFunction)
|
||||
}
|
||||
|
||||
self.fadeNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
if transition.isAnimated {
|
||||
self.fadeNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user