mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-04 10:30:42 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
0e086c2a10
@ -40,7 +40,9 @@ final class GroupVideoNode: ASDisplayNode {
|
|||||||
return self.readyPromise.get()
|
return self.readyPromise.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
init(videoView: PresentationCallVideoView, backdropVideoView: PresentationCallVideoView?, disabledText: String? = nil) {
|
public var isMainstageExclusive = false
|
||||||
|
|
||||||
|
init(videoView: PresentationCallVideoView, backdropVideoView: PresentationCallVideoView?) {
|
||||||
self.sourceContainerNode = PinchSourceContainerNode()
|
self.sourceContainerNode = PinchSourceContainerNode()
|
||||||
self.containerNode = ASDisplayNode()
|
self.containerNode = ASDisplayNode()
|
||||||
self.videoViewContainer = UIView()
|
self.videoViewContainer = UIView()
|
||||||
@ -193,7 +195,6 @@ final class GroupVideoNode: ASDisplayNode {
|
|||||||
return rotatedAspect
|
return rotatedAspect
|
||||||
}
|
}
|
||||||
|
|
||||||
var keepBackdropSize = false
|
|
||||||
func updateLayout(size: CGSize, layoutMode: LayoutMode, transition: ContainedViewLayoutTransition) {
|
func updateLayout(size: CGSize, layoutMode: LayoutMode, transition: ContainedViewLayoutTransition) {
|
||||||
self.validLayout = (size, layoutMode)
|
self.validLayout = (size, layoutMode)
|
||||||
let bounds = CGRect(origin: CGPoint(), size: size)
|
let bounds = CGRect(origin: CGPoint(), size: size)
|
||||||
|
@ -2556,6 +2556,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
|
|
||||||
public func disableVideo() {
|
public func disableVideo() {
|
||||||
self.hasVideo = false
|
self.hasVideo = false
|
||||||
|
self.useFrontCamera = true;
|
||||||
if let _ = self.videoCapturer {
|
if let _ = self.videoCapturer {
|
||||||
self.videoCapturer = nil
|
self.videoCapturer = nil
|
||||||
self.isVideoMutedDisposable.set(nil)
|
self.isVideoMutedDisposable.set(nil)
|
||||||
|
@ -901,8 +901,10 @@ public final class VoiceChatController: ViewController {
|
|||||||
private var wideVideoNodes = Set<String>()
|
private var wideVideoNodes = Set<String>()
|
||||||
private var videoOrder: [String] = []
|
private var videoOrder: [String] = []
|
||||||
private var readyVideoEndpointIds = Set<String>()
|
private var readyVideoEndpointIds = Set<String>()
|
||||||
|
private var readyVideoEndpointIdsPromise = ValuePromise<Set<String>>(Set())
|
||||||
private var timeoutedEndpointIds = Set<String>()
|
private var timeoutedEndpointIds = Set<String>()
|
||||||
private var readyVideoDisposables = DisposableDict<String>()
|
private var readyVideoDisposables = DisposableDict<String>()
|
||||||
|
private var myPeerVideoReadyDisposable = MetaDisposable()
|
||||||
|
|
||||||
private var peerIdToEndpointId: [PeerId: String] = [:]
|
private var peerIdToEndpointId: [PeerId: String] = [:]
|
||||||
|
|
||||||
@ -1761,7 +1763,9 @@ public final class VoiceChatController: ViewController {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var ignore = false
|
var ignore = false
|
||||||
if case .fullscreen = strongSelf.displayMode, !strongSelf.isPanning {
|
if case .mainstage = position {
|
||||||
|
ignore = false
|
||||||
|
} else if case .fullscreen = strongSelf.displayMode, !strongSelf.isPanning {
|
||||||
ignore = ![.mainstage, .list].contains(position)
|
ignore = ![.mainstage, .list].contains(position)
|
||||||
} else {
|
} else {
|
||||||
ignore = position != .tile
|
ignore = position != .tile
|
||||||
@ -1774,6 +1778,9 @@ public final class VoiceChatController: ViewController {
|
|||||||
}
|
}
|
||||||
for (listEndpointId, videoNode) in strongSelf.videoNodes {
|
for (listEndpointId, videoNode) in strongSelf.videoNodes {
|
||||||
if listEndpointId == endpointId {
|
if listEndpointId == endpointId {
|
||||||
|
if position != .mainstage && videoNode.isMainstageExclusive {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return videoNode
|
return videoNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2276,6 +2283,33 @@ public final class VoiceChatController: ViewController {
|
|||||||
return self?.itemInteraction?.getAudioLevel(peerId) ?? .single(0.0)
|
return self?.itemInteraction?.getAudioLevel(peerId) ?? .single(0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.mainStageNode.getVideo = { [weak self] endpointId, isMyPeer, completion in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if isMyPeer {
|
||||||
|
if strongSelf.readyVideoEndpointIds.contains(endpointId) {
|
||||||
|
completion(strongSelf.itemInteraction?.getPeerVideo(endpointId, .mainstage))
|
||||||
|
} else {
|
||||||
|
strongSelf.myPeerVideoReadyDisposable.set((strongSelf.readyVideoEndpointIdsPromise.get()
|
||||||
|
|> filter { $0.contains(endpointId) }
|
||||||
|
|> take(1)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||||
|
if let strongSelf = self {
|
||||||
|
completion(strongSelf.itemInteraction?.getPeerVideo(endpointId, .mainstage))
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strongSelf.call.makeIncomingVideoView(endpointId: endpointId, requestClone: true, completion: { videoView, backdropVideoView in
|
||||||
|
if let videoView = videoView {
|
||||||
|
completion(GroupVideoNode(videoView: videoView, backdropVideoView: backdropVideoView))
|
||||||
|
} else {
|
||||||
|
completion(nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.applicationStateDisposable = (self.context.sharedContext.applicationBindings.applicationIsActive
|
self.applicationStateDisposable = (self.context.sharedContext.applicationBindings.applicationIsActive
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] active in
|
|> deliverOnMainQueue).start(next: { [weak self] active in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
@ -2305,6 +2339,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
self.ignoreConnectingTimer?.invalidate()
|
self.ignoreConnectingTimer?.invalidate()
|
||||||
self.readyVideoDisposables.dispose()
|
self.readyVideoDisposables.dispose()
|
||||||
self.applicationStateDisposable?.dispose()
|
self.applicationStateDisposable?.dispose()
|
||||||
|
self.myPeerVideoReadyDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func openSettingsMenu(sourceNode: ASDisplayNode, gesture: ContextGesture?) {
|
private func openSettingsMenu(sourceNode: ASDisplayNode, gesture: ContextGesture?) {
|
||||||
@ -3621,7 +3656,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
if !self.mainStageNode.animating {
|
if !self.mainStageNode.animating {
|
||||||
transition.updateFrame(node: self.mainStageNode, frame: videoFrame)
|
transition.updateFrame(node: self.mainStageNode, frame: videoFrame)
|
||||||
}
|
}
|
||||||
self.mainStageNode.update(size: videoFrame.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, isLandscape: self.isLandscape, isTablet: isTablet, transition: transition)
|
self.mainStageNode.update(size: videoFrame.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, isLandscape: videoFrame.width > videoFrame.height, isTablet: isTablet, transition: transition)
|
||||||
|
|
||||||
let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: size.width, height: layout.size.height))
|
let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: size.width, height: layout.size.height))
|
||||||
|
|
||||||
@ -3633,8 +3668,13 @@ public final class VoiceChatController: ViewController {
|
|||||||
leftBorderFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY - additionalInset), size: CGSize(width: (size.width - contentWidth) / 2.0 + sideInset, height: layout.size.height))
|
leftBorderFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY - additionalInset), size: CGSize(width: (size.width - contentWidth) / 2.0 + sideInset, height: layout.size.height))
|
||||||
rightBorderFrame = CGRect(origin: CGPoint(x: size.width - (size.width - contentWidth) / 2.0 - sideInset, y: topPanelFrame.maxY - additionalInset), size: CGSize(width: layout.safeInsets.right + (size.width - contentWidth) / 2.0 + sideInset, height: layout.size.height))
|
rightBorderFrame = CGRect(origin: CGPoint(x: size.width - (size.width - contentWidth) / 2.0 - sideInset, y: topPanelFrame.maxY - additionalInset), size: CGSize(width: layout.safeInsets.right + (size.width - contentWidth) / 2.0 + sideInset, height: layout.size.height))
|
||||||
} else {
|
} else {
|
||||||
leftBorderFrame = CGRect(origin: CGPoint(x: -additionalInset, y: topPanelFrame.maxY - additionalInset * 0.6), size: CGSize(width: sideInset + additionalInset + (contentLeftInset.isZero ? additionalSideInset : contentLeftInset), height: layout.size.height))
|
var isFullscreen = false
|
||||||
rightBorderFrame = CGRect(origin: CGPoint(x: size.width - sideInset - (contentLeftInset.isZero ? additionalSideInset : 0.0), y: topPanelFrame.maxY - additionalInset * 0.6), size: CGSize(width: sideInset + additionalInset + additionalSideInset, height: layout.size.height))
|
if case .fullscreen = self.displayMode {
|
||||||
|
isFullscreen = true
|
||||||
|
forceUpdate = true
|
||||||
|
}
|
||||||
|
leftBorderFrame = CGRect(origin: CGPoint(x: -additionalInset, y: topPanelFrame.maxY - additionalInset * (isFullscreen ? 0.95 : 0.8)), size: CGSize(width: sideInset + additionalInset + (contentLeftInset.isZero ? additionalSideInset : contentLeftInset), height: layout.size.height))
|
||||||
|
rightBorderFrame = CGRect(origin: CGPoint(x: size.width - sideInset - (contentLeftInset.isZero ? additionalSideInset : 0.0), y: topPanelFrame.maxY - additionalInset * (isFullscreen ? 0.95 : 0.8)), size: CGSize(width: sideInset + additionalInset + additionalSideInset, height: layout.size.height))
|
||||||
}
|
}
|
||||||
|
|
||||||
let topCornersFrame = CGRect(x: sideInset + (contentLeftInset.isZero ? floorToScreenPixels((size.width - contentWidth) / 2.0) : contentLeftInset), y: topPanelFrame.maxY - 60.0, width: contentWidth - sideInset * 2.0, height: 50.0 + 60.0)
|
let topCornersFrame = CGRect(x: sideInset + (contentLeftInset.isZero ? floorToScreenPixels((size.width - contentWidth) / 2.0) : contentLeftInset), y: topPanelFrame.maxY - 60.0, width: contentWidth - sideInset * 2.0, height: 50.0 + 60.0)
|
||||||
@ -5079,11 +5119,10 @@ public final class VoiceChatController: ViewController {
|
|||||||
self.requestedVideoSources.insert(channel.endpointId)
|
self.requestedVideoSources.insert(channel.endpointId)
|
||||||
self.call.makeIncomingVideoView(endpointId: channel.endpointId, requestClone: true, completion: { [weak self] videoView, backdropVideoView in
|
self.call.makeIncomingVideoView(endpointId: channel.endpointId, requestClone: true, completion: { [weak self] videoView, backdropVideoView in
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
print("create video \(channel.endpointId)")
|
|
||||||
guard let strongSelf = self, let videoView = videoView else {
|
guard let strongSelf = self, let videoView = videoView else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let videoNode = GroupVideoNode(videoView: videoView, backdropVideoView: backdropVideoView, disabledText: strongSelf.presentationData.strings.VoiceChat_VideoPaused)
|
let videoNode = GroupVideoNode(videoView: videoView, backdropVideoView: backdropVideoView)
|
||||||
|
|
||||||
strongSelf.readyVideoDisposables.set((combineLatest(videoNode.ready, .single(false) |> then(.single(true) |> delay(10.0, queue: Queue.mainQueue())))
|
strongSelf.readyVideoDisposables.set((combineLatest(videoNode.ready, .single(false) |> then(.single(true) |> delay(10.0, queue: Queue.mainQueue())))
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
@ -5093,11 +5132,13 @@ public final class VoiceChatController: ViewController {
|
|||||||
if timeouted && !ready {
|
if timeouted && !ready {
|
||||||
strongSelf.timeoutedEndpointIds.insert(channel.endpointId)
|
strongSelf.timeoutedEndpointIds.insert(channel.endpointId)
|
||||||
strongSelf.readyVideoEndpointIds.remove(channel.endpointId)
|
strongSelf.readyVideoEndpointIds.remove(channel.endpointId)
|
||||||
|
strongSelf.readyVideoEndpointIdsPromise.set(strongSelf.readyVideoEndpointIds)
|
||||||
strongSelf.wideVideoNodes.remove(channel.endpointId)
|
strongSelf.wideVideoNodes.remove(channel.endpointId)
|
||||||
|
|
||||||
strongSelf.updateMembers()
|
strongSelf.updateMembers()
|
||||||
} else if ready {
|
} else if ready {
|
||||||
strongSelf.readyVideoEndpointIds.insert(channel.endpointId)
|
strongSelf.readyVideoEndpointIds.insert(channel.endpointId)
|
||||||
|
strongSelf.readyVideoEndpointIdsPromise.set(strongSelf.readyVideoEndpointIds)
|
||||||
strongSelf.timeoutedEndpointIds.remove(channel.endpointId)
|
strongSelf.timeoutedEndpointIds.remove(channel.endpointId)
|
||||||
if videoNode.aspectRatio <= 0.77 {
|
if videoNode.aspectRatio <= 0.77 {
|
||||||
strongSelf.wideVideoNodes.insert(channel.endpointId)
|
strongSelf.wideVideoNodes.insert(channel.endpointId)
|
||||||
@ -5152,6 +5193,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
self.videoNodes[videoEndpointId] = nil
|
self.videoNodes[videoEndpointId] = nil
|
||||||
self.videoOrder.removeAll(where: { $0 == videoEndpointId })
|
self.videoOrder.removeAll(where: { $0 == videoEndpointId })
|
||||||
self.readyVideoEndpointIds.remove(videoEndpointId)
|
self.readyVideoEndpointIds.remove(videoEndpointId)
|
||||||
|
self.readyVideoEndpointIdsPromise.set(self.readyVideoEndpointIds)
|
||||||
self.readyVideoDisposables.set(nil, forKey: videoEndpointId)
|
self.readyVideoDisposables.set(nil, forKey: videoEndpointId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,6 +315,10 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
videoNode = item.getVideo()
|
videoNode = item.getVideo()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if videoNode?.isMainstageExclusive == true && active {
|
||||||
|
videoNode = nil
|
||||||
|
}
|
||||||
|
|
||||||
if let videoNode = videoNode {
|
if let videoNode = videoNode {
|
||||||
if active {
|
if active {
|
||||||
self.avatarNode.alpha = 1.0
|
self.avatarNode.alpha = 1.0
|
||||||
@ -488,7 +492,9 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
strongSelf.videoContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -9.0), duration: appearanceDuration, additive: true)
|
strongSelf.videoContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -9.0), duration: appearanceDuration, additive: true)
|
||||||
strongSelf.audioLevelView?.layer.animateScale(from: 0.0, to: 1.0, duration: appearanceDuration)
|
strongSelf.audioLevelView?.layer.animateScale(from: 0.0, to: 1.0, duration: appearanceDuration)
|
||||||
}
|
}
|
||||||
apperanceTransition.updateAlpha(node: currentVideoNode, alpha: 0.0)
|
if currentVideoNode.supernode === strongSelf.videoContainerNode {
|
||||||
|
apperanceTransition.updateAlpha(node: currentVideoNode, alpha: 0.0)
|
||||||
|
}
|
||||||
apperanceTransition.updateAlpha(node: strongSelf.videoFadeNode, alpha: 0.0)
|
apperanceTransition.updateAlpha(node: strongSelf.videoFadeNode, alpha: 0.0)
|
||||||
apperanceTransition.updateAlpha(node: strongSelf.avatarNode, alpha: 1.0)
|
apperanceTransition.updateAlpha(node: strongSelf.avatarNode, alpha: 1.0)
|
||||||
if let audioLevelView = strongSelf.audioLevelView {
|
if let audioLevelView = strongSelf.audioLevelView {
|
||||||
|
@ -78,6 +78,7 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
var controlsHidden: ((Bool) -> Void)?
|
var controlsHidden: ((Bool) -> Void)?
|
||||||
|
|
||||||
var getAudioLevel: ((PeerId) -> Signal<Float, NoError>)?
|
var getAudioLevel: ((PeerId) -> Signal<Float, NoError>)?
|
||||||
|
var getVideo: ((String, Bool, @escaping (GroupVideoNode?) -> Void) -> Void)?
|
||||||
private let videoReadyDisposable = MetaDisposable()
|
private let videoReadyDisposable = MetaDisposable()
|
||||||
private var silenceTimer: SwiftSignalKit.Timer?
|
private var silenceTimer: SwiftSignalKit.Timer?
|
||||||
|
|
||||||
@ -116,8 +117,6 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
||||||
}) {
|
}) {
|
||||||
self.bottomFadeNode.backgroundColor = UIColor(patternImage: image)
|
self.bottomFadeNode.backgroundColor = UIColor(patternImage: image)
|
||||||
self.bottomFadeNode.view.layer.rasterizationScale = UIScreen.main.scale
|
|
||||||
self.bottomFadeNode.view.layer.shouldRasterize = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.bottomFillNode = ASDisplayNode()
|
self.bottomFillNode = ASDisplayNode()
|
||||||
@ -288,6 +287,11 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
self.layer.cornerCurve = .continuous
|
self.layer.cornerCurve = .continuous
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.topFadeNode.view.layer.rasterizationScale = UIScreen.main.scale
|
||||||
|
self.topFadeNode.view.layer.shouldRasterize = true
|
||||||
|
self.bottomFadeNode.view.layer.rasterizationScale = UIScreen.main.scale
|
||||||
|
self.bottomFadeNode.view.layer.shouldRasterize = true
|
||||||
|
|
||||||
let speakingEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
|
let speakingEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
|
||||||
speakingEffectView.layer.cornerRadius = 19.0
|
speakingEffectView.layer.cornerRadius = 19.0
|
||||||
speakingEffectView.clipsToBounds = true
|
speakingEffectView.clipsToBounds = true
|
||||||
@ -479,7 +483,7 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
self.animatingOut = true
|
self.animatingOut = true
|
||||||
let targetFrame = targetNode.view.convert(targetNode.bounds, to: self.supernode?.view)
|
let targetFrame = targetNode.view.convert(targetNode.bounds, to: self.supernode?.view)
|
||||||
|
|
||||||
self.currentVideoNode?.keepBackdropSize = true
|
let currentVideoNode = self.currentVideoNode
|
||||||
|
|
||||||
var infoView: UIView?
|
var infoView: UIView?
|
||||||
if let snapshotView = targetNode.infoNode.view.snapshotView(afterScreenUpdates: false) {
|
if let snapshotView = targetNode.infoNode.view.snapshotView(afterScreenUpdates: false) {
|
||||||
@ -525,6 +529,8 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
|
|
||||||
infoView?.removeFromSuperview()
|
infoView?.removeFromSuperview()
|
||||||
textView?.removeFromSuperview()
|
textView?.removeFromSuperview()
|
||||||
|
currentVideoNode?.isMainstageExclusive = false
|
||||||
|
targetNode.transitionIn(from: nil)
|
||||||
targetNode.alpha = 1.0
|
targetNode.alpha = 1.0
|
||||||
targetNode.highlightNode.layer.animateAlpha(from: 0.0, to: targetNode.highlightNode.alpha, duration: 0.2)
|
targetNode.highlightNode.layer.animateAlpha(from: 0.0, to: targetNode.highlightNode.alpha, duration: 0.2)
|
||||||
strongSelf.animatingOut = false
|
strongSelf.animatingOut = false
|
||||||
@ -812,13 +818,19 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
if !delayTransition {
|
if !delayTransition {
|
||||||
self.setAvatarHidden(true)
|
self.setAvatarHidden(true)
|
||||||
}
|
}
|
||||||
self.call.makeIncomingVideoView(endpointId: endpointId, requestClone: true, completion: { [weak self] videoView, backdropVideoView in
|
|
||||||
|
var waitForFullSize = waitForFullSize
|
||||||
|
if isMyPeer && !isPresentation && isReady && !self.appeared {
|
||||||
|
waitForFullSize = false
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getVideo?(endpointId, isMyPeer && !isPresentation, { [weak self] videoNode in
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
guard let strongSelf = self, let videoView = videoView else {
|
guard let strongSelf = self, let videoNode = videoNode else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let videoNode = GroupVideoNode(videoView: videoView, backdropVideoView: backdropVideoView, disabledText: presentationData.strings.VoiceChat_VideoPaused)
|
videoNode.isMainstageExclusive = isMyPeer
|
||||||
videoNode.tapped = { [weak self] in
|
videoNode.tapped = { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -846,20 +858,31 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
videoNode.updateIsBlurred(isBlurred: isPaused, light: true, animated: false)
|
videoNode.updateIsBlurred(isBlurred: isPaused, light: true, animated: false)
|
||||||
videoNode.isUserInteractionEnabled = true
|
videoNode.isUserInteractionEnabled = true
|
||||||
let previousVideoNode = strongSelf.currentVideoNode
|
let previousVideoNode = strongSelf.currentVideoNode
|
||||||
|
var previousVideoNodeSnapshot: UIView?
|
||||||
|
if let previousVideoNode = previousVideoNode, previousVideoNode.isMainstageExclusive, let snapshotView = previousVideoNode.view.snapshotView(afterScreenUpdates: false) {
|
||||||
|
previousVideoNodeSnapshot = snapshotView
|
||||||
|
snapshotView.frame = previousVideoNode.frame
|
||||||
|
previousVideoNode.view.superview?.insertSubview(snapshotView, aboveSubview: previousVideoNode.view)
|
||||||
|
}
|
||||||
strongSelf.currentVideoNode = videoNode
|
strongSelf.currentVideoNode = videoNode
|
||||||
strongSelf.insertSubnode(videoNode, aboveSubnode: strongSelf.backdropAvatarNode)
|
strongSelf.insertSubnode(videoNode, aboveSubnode: strongSelf.backdropAvatarNode)
|
||||||
|
|
||||||
if !isReady {
|
if delayTransition {
|
||||||
|
videoNode.alpha = 0.0
|
||||||
|
} else if !isReady {
|
||||||
videoNode.alpha = 0.0
|
videoNode.alpha = 0.0
|
||||||
strongSelf.topFadeNode.isHidden = true
|
strongSelf.topFadeNode.isHidden = true
|
||||||
strongSelf.bottomFadeNode.isHidden = true
|
strongSelf.bottomFadeNode.isHidden = true
|
||||||
strongSelf.bottomFillNode.isHidden = true
|
strongSelf.bottomFillNode.isHidden = true
|
||||||
} else if delayTransition {
|
} else if isMyPeer {
|
||||||
videoNode.alpha = 0.0
|
videoNode.layer.removeAnimation(forKey: "opacity")
|
||||||
|
videoNode.alpha = 1.0
|
||||||
}
|
}
|
||||||
if waitForFullSize {
|
if waitForFullSize {
|
||||||
|
previousVideoNode?.isMainstageExclusive = false
|
||||||
Queue.mainQueue().after(2.0) {
|
Queue.mainQueue().after(2.0) {
|
||||||
if let previousVideoNode = previousVideoNode {
|
previousVideoNodeSnapshot?.removeFromSuperview()
|
||||||
|
if let previousVideoNode = previousVideoNode, previousVideoNode.supernode === strongSelf && !previousVideoNode.isMainstageExclusive {
|
||||||
previousVideoNode.removeFromSupernode()
|
previousVideoNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -881,23 +904,36 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if videoNode.alpha.isZero {
|
if videoNode.alpha.isZero {
|
||||||
strongSelf.topFadeNode.isHidden = true
|
if delayTransition {
|
||||||
strongSelf.bottomFadeNode.isHidden = true
|
strongSelf.topFadeNode.isHidden = false
|
||||||
strongSelf.bottomFillNode.isHidden = true
|
strongSelf.bottomFadeNode.isHidden = false
|
||||||
|
strongSelf.bottomFillNode.isHidden = false
|
||||||
|
strongSelf.topFadeNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||||
|
strongSelf.bottomFadeNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||||
|
strongSelf.bottomFillNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||||
|
|
||||||
|
strongSelf.avatarNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||||
|
strongSelf.audioLevelNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||||
|
}
|
||||||
if let videoNode = strongSelf.currentVideoNode {
|
if let videoNode = strongSelf.currentVideoNode {
|
||||||
videoNode.alpha = 1.0
|
videoNode.alpha = 1.0
|
||||||
videoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, completion: { [weak self] _ in
|
videoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, completion: { [weak self] _ in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.setAvatarHidden(true)
|
strongSelf.setAvatarHidden(true)
|
||||||
if let previousVideoNode = previousVideoNode {
|
strongSelf.avatarNode.layer.removeAllAnimations()
|
||||||
|
strongSelf.audioLevelNode.layer.removeAllAnimations()
|
||||||
|
previousVideoNodeSnapshot?.removeFromSuperview()
|
||||||
|
if let previousVideoNode = previousVideoNode, previousVideoNode.supernode === strongSelf {
|
||||||
previousVideoNode.removeFromSupernode()
|
previousVideoNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
previousVideoNodeSnapshot?.removeFromSuperview()
|
||||||
|
previousVideoNode?.isMainstageExclusive = false
|
||||||
Queue.mainQueue().after(0.07) {
|
Queue.mainQueue().after(0.07) {
|
||||||
if let previousVideoNode = previousVideoNode {
|
if let previousVideoNode = previousVideoNode, previousVideoNode.supernode === strongSelf {
|
||||||
previousVideoNode.removeFromSupernode()
|
previousVideoNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -909,7 +945,11 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, isLandscape: isLandscape, isTablet: isTablet, transition: .immediate)
|
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, isLandscape: isLandscape, isTablet: isTablet, transition: .immediate)
|
||||||
}
|
}
|
||||||
if let previousVideoNode = previousVideoNode {
|
if let previousVideoNode = previousVideoNode {
|
||||||
previousVideoNode.removeFromSupernode()
|
previousVideoNodeSnapshot?.removeFromSuperview()
|
||||||
|
previousVideoNode.isMainstageExclusive = false
|
||||||
|
if previousVideoNode.supernode === strongSelf {
|
||||||
|
previousVideoNode.removeFromSupernode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
strongSelf.videoReadyDisposable.set(nil)
|
strongSelf.videoReadyDisposable.set(nil)
|
||||||
completion?()
|
completion?()
|
||||||
@ -918,7 +958,10 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if let currentVideoNode = self.currentVideoNode {
|
if let currentVideoNode = self.currentVideoNode {
|
||||||
currentVideoNode.removeFromSupernode()
|
currentVideoNode.isMainstageExclusive = false
|
||||||
|
if currentVideoNode.supernode === self {
|
||||||
|
currentVideoNode.removeFromSupernode()
|
||||||
|
}
|
||||||
self.currentVideoNode = nil
|
self.currentVideoNode = nil
|
||||||
}
|
}
|
||||||
self.setAvatarHidden(false)
|
self.setAvatarHidden(false)
|
||||||
@ -970,7 +1013,10 @@ final class VoiceChatMainStageNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
self.videoReadyDisposable.set(nil)
|
self.videoReadyDisposable.set(nil)
|
||||||
if let currentVideoNode = self.currentVideoNode {
|
if let currentVideoNode = self.currentVideoNode {
|
||||||
currentVideoNode.removeFromSupernode()
|
currentVideoNode.isMainstageExclusive = false
|
||||||
|
if currentVideoNode.supernode === self {
|
||||||
|
currentVideoNode.removeFromSupernode()
|
||||||
|
}
|
||||||
self.currentVideoNode = nil
|
self.currentVideoNode = nil
|
||||||
}
|
}
|
||||||
completion?()
|
completion?()
|
||||||
|
@ -500,7 +500,7 @@ public final class PrincipalThemeAdditionalGraphics {
|
|||||||
public let chatEmptyItemBackgroundImage: UIImage
|
public let chatEmptyItemBackgroundImage: UIImage
|
||||||
public let chatLoadingIndicatorBackgroundImage: UIImage
|
public let chatLoadingIndicatorBackgroundImage: UIImage
|
||||||
|
|
||||||
public let chatBubbleShareButtonImage: UIImage
|
|
||||||
public let chatBubbleNavigateButtonImage: UIImage
|
public let chatBubbleNavigateButtonImage: UIImage
|
||||||
public let chatBubbleActionButtonIncomingMiddleImage: UIImage
|
public let chatBubbleActionButtonIncomingMiddleImage: UIImage
|
||||||
public let chatBubbleActionButtonIncomingBottomLeftImage: UIImage
|
public let chatBubbleActionButtonIncomingBottomLeftImage: UIImage
|
||||||
@ -547,7 +547,6 @@ public final class PrincipalThemeAdditionalGraphics {
|
|||||||
self.chatEmptyItemBackgroundImage = generateStretchableFilledCircleImage(radius: 14.0, color: serviceColor.fill)!
|
self.chatEmptyItemBackgroundImage = generateStretchableFilledCircleImage(radius: 14.0, color: serviceColor.fill)!
|
||||||
self.chatLoadingIndicatorBackgroundImage = generateStretchableFilledCircleImage(diameter: 30.0, color: serviceColor.fill)!
|
self.chatLoadingIndicatorBackgroundImage = generateStretchableFilledCircleImage(diameter: 30.0, color: serviceColor.fill)!
|
||||||
|
|
||||||
self.chatBubbleShareButtonImage = chatBubbleActionButtonImage(fillColor: bubbleVariableColor(variableColor: theme.message.shareButtonFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.shareButtonStrokeColor, wallpaper: wallpaper), foregroundColor: bubbleVariableColor(variableColor: theme.message.shareButtonForegroundColor, wallpaper: wallpaper), image: UIImage(bundleImageName: "Chat/Message/ShareIcon"))!
|
|
||||||
self.chatBubbleNavigateButtonImage = chatBubbleActionButtonImage(fillColor: bubbleVariableColor(variableColor: theme.message.shareButtonFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.shareButtonStrokeColor, wallpaper: wallpaper), foregroundColor: bubbleVariableColor(variableColor: theme.message.shareButtonForegroundColor, wallpaper: wallpaper), image: UIImage(bundleImageName: "Chat/Message/NavigateToMessageIcon"), iconOffset: CGPoint(x: 0.0, y: 1.0))!
|
self.chatBubbleNavigateButtonImage = chatBubbleActionButtonImage(fillColor: bubbleVariableColor(variableColor: theme.message.shareButtonFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.shareButtonStrokeColor, wallpaper: wallpaper), foregroundColor: bubbleVariableColor(variableColor: theme.message.shareButtonForegroundColor, wallpaper: wallpaper), image: UIImage(bundleImageName: "Chat/Message/NavigateToMessageIcon"), iconOffset: CGPoint(x: 0.0, y: 1.0))!
|
||||||
self.chatBubbleActionButtonIncomingMiddleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .middle, bubbleCorners: bubbleCorners)
|
self.chatBubbleActionButtonIncomingMiddleImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .middle, bubbleCorners: bubbleCorners)
|
||||||
self.chatBubbleActionButtonIncomingBottomLeftImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomLeft, bubbleCorners: bubbleCorners)
|
self.chatBubbleActionButtonIncomingBottomLeftImage = messageBubbleActionButtonImage(color: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsFillColor, wallpaper: wallpaper), strokeColor: bubbleVariableColor(variableColor: theme.message.incoming.actionButtonsStrokeColor, wallpaper: wallpaper), position: .bottomLeft, bubbleCorners: bubbleCorners)
|
||||||
|
@ -95,20 +95,16 @@ class ChatMessageShareButton: HighlightableButtonNode {
|
|||||||
self.isReplies = isReplies
|
self.isReplies = isReplies
|
||||||
|
|
||||||
let graphics = PresentationResourcesChat.additionalGraphics(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners)
|
let graphics = PresentationResourcesChat.additionalGraphics(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners)
|
||||||
//var updatedShareButtonBackground: UIImage?
|
|
||||||
var updatedIconImage: UIImage?
|
var updatedIconImage: UIImage?
|
||||||
if case .pinnedMessages = subject {
|
if case .pinnedMessages = subject {
|
||||||
updatedIconImage = PresentationResourcesChat.chatFreeNavigateButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
updatedIconImage = PresentationResourcesChat.chatFreeNavigateButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
||||||
//updatedShareButtonBackground = graphics.chatBubbleNavigateButtonImage
|
|
||||||
} else if isReplies {
|
} else if isReplies {
|
||||||
//updatedShareButtonBackground = PresentationResourcesChat.chatFreeCommentButtonBackground(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
|
||||||
updatedIconImage = PresentationResourcesChat.chatFreeCommentButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
updatedIconImage = PresentationResourcesChat.chatFreeCommentButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
||||||
} else if message.id.peerId.isRepliesOrSavedMessages(accountPeerId: account.peerId) {
|
} else if message.id.peerId.isRepliesOrSavedMessages(accountPeerId: account.peerId) {
|
||||||
updatedIconImage = PresentationResourcesChat.chatFreeNavigateButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
updatedIconImage = PresentationResourcesChat.chatFreeNavigateButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
||||||
//updatedShareButtonBackground = graphics.chatBubbleNavigateButtonImage
|
|
||||||
} else {
|
} else {
|
||||||
updatedIconImage = PresentationResourcesChat.chatFreeShareButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
updatedIconImage = PresentationResourcesChat.chatFreeShareButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
||||||
//updatedShareButtonBackground = graphics.chatBubbleShareButtonImage
|
|
||||||
}
|
}
|
||||||
self.backgroundNode.color = presentationData.theme.theme.chat.serviceMessage.components.withDefaultWallpaper.dateFillStatic
|
self.backgroundNode.color = presentationData.theme.theme.chat.serviceMessage.components.withDefaultWallpaper.dateFillStatic
|
||||||
self.iconNode.image = updatedIconImage
|
self.iconNode.image = updatedIconImage
|
||||||
|
@ -414,7 +414,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
private var mosaicStatusNode: ChatMessageDateAndStatusNode?
|
private var mosaicStatusNode: ChatMessageDateAndStatusNode?
|
||||||
private var actionButtonsNode: ChatMessageActionButtonsNode?
|
private var actionButtonsNode: ChatMessageActionButtonsNode?
|
||||||
|
|
||||||
private var shareButtonNode: HighlightableButtonNode?
|
private var shareButtonNode: ChatMessageShareButton?
|
||||||
|
|
||||||
private let messageAccessibilityArea: AccessibilityAreaNode
|
private let messageAccessibilityArea: AccessibilityAreaNode
|
||||||
|
|
||||||
@ -1068,8 +1068,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
|
|
||||||
let mosaicStatusLayout = ChatMessageDateAndStatusNode.asyncLayout(self.mosaicStatusNode)
|
let mosaicStatusLayout = ChatMessageDateAndStatusNode.asyncLayout(self.mosaicStatusNode)
|
||||||
|
|
||||||
let currentShareButtonNode = self.shareButtonNode
|
|
||||||
|
|
||||||
let layoutConstants = self.layoutConstants
|
let layoutConstants = self.layoutConstants
|
||||||
|
|
||||||
let currentItem = self.appliedItem
|
let currentItem = self.appliedItem
|
||||||
@ -1089,7 +1087,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
replyInfoLayout: replyInfoLayout,
|
replyInfoLayout: replyInfoLayout,
|
||||||
actionButtonsLayout: actionButtonsLayout,
|
actionButtonsLayout: actionButtonsLayout,
|
||||||
mosaicStatusLayout: mosaicStatusLayout,
|
mosaicStatusLayout: mosaicStatusLayout,
|
||||||
currentShareButtonNode: currentShareButtonNode,
|
|
||||||
layoutConstants: layoutConstants,
|
layoutConstants: layoutConstants,
|
||||||
currentItem: currentItem,
|
currentItem: currentItem,
|
||||||
currentForwardInfo: currentForwardInfo,
|
currentForwardInfo: currentForwardInfo,
|
||||||
@ -1106,7 +1103,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
replyInfoLayout: (ChatPresentationData, PresentationStrings, AccountContext, ChatMessageReplyInfoType, Message, CGSize) -> (CGSize, () -> ChatMessageReplyInfoNode),
|
replyInfoLayout: (ChatPresentationData, PresentationStrings, AccountContext, ChatMessageReplyInfoType, Message, CGSize) -> (CGSize, () -> ChatMessageReplyInfoNode),
|
||||||
actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationChatBubbleCorners, PresentationStrings, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (Bool) -> ChatMessageActionButtonsNode)),
|
actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationChatBubbleCorners, PresentationStrings, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (Bool) -> ChatMessageActionButtonsNode)),
|
||||||
mosaicStatusLayout: (AccountContext, ChatPresentationData, Bool, Int?, String, ChatMessageDateAndStatusType, CGSize, [MessageReaction], Int, Bool, Bool) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode),
|
mosaicStatusLayout: (AccountContext, ChatPresentationData, Bool, Int?, String, ChatMessageDateAndStatusType, CGSize, [MessageReaction], Int, Bool, Bool) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode),
|
||||||
currentShareButtonNode: HighlightableButtonNode?,
|
|
||||||
layoutConstants: ChatMessageItemLayoutConstants,
|
layoutConstants: ChatMessageItemLayoutConstants,
|
||||||
currentItem: ChatMessageItem?,
|
currentItem: ChatMessageItem?,
|
||||||
currentForwardInfo: (Peer?, String?)?,
|
currentForwardInfo: (Peer?, String?)?,
|
||||||
@ -2155,38 +2151,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
layoutInsets.top += layoutConstants.timestampHeaderHeight
|
layoutInsets.top += layoutConstants.timestampHeaderHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
var updatedShareButtonBackground: UIImage?
|
|
||||||
|
|
||||||
var updatedShareButtonNode: HighlightableButtonNode?
|
|
||||||
if needShareButton {
|
|
||||||
if currentShareButtonNode != nil {
|
|
||||||
updatedShareButtonNode = currentShareButtonNode
|
|
||||||
if item.presentationData.theme !== currentItem?.presentationData.theme {
|
|
||||||
let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners)
|
|
||||||
if case .pinnedMessages = item.associatedData.subject {
|
|
||||||
updatedShareButtonBackground = graphics.chatBubbleNavigateButtonImage
|
|
||||||
} else if item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) {
|
|
||||||
updatedShareButtonBackground = graphics.chatBubbleNavigateButtonImage
|
|
||||||
} else {
|
|
||||||
updatedShareButtonBackground = graphics.chatBubbleShareButtonImage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let buttonNode = HighlightableButtonNode()
|
|
||||||
let buttonIcon: UIImage?
|
|
||||||
let graphics = PresentationResourcesChat.additionalGraphics(item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners)
|
|
||||||
if case .pinnedMessages = item.associatedData.subject {
|
|
||||||
buttonIcon = graphics.chatBubbleNavigateButtonImage
|
|
||||||
} else if item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) {
|
|
||||||
buttonIcon = graphics.chatBubbleNavigateButtonImage
|
|
||||||
} else {
|
|
||||||
buttonIcon = graphics.chatBubbleShareButtonImage
|
|
||||||
}
|
|
||||||
buttonNode.setBackgroundImage(buttonIcon, for: [.normal])
|
|
||||||
updatedShareButtonNode = buttonNode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let layout = ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets)
|
let layout = ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets)
|
||||||
|
|
||||||
let graphics = PresentationResourcesChat.principalGraphics(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners)
|
let graphics = PresentationResourcesChat.principalGraphics(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper, bubbleCorners: item.presentationData.chatBubbleCorners)
|
||||||
@ -2241,8 +2205,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
contentContainerNodeFrames: contentContainerNodeFrames,
|
contentContainerNodeFrames: contentContainerNodeFrames,
|
||||||
mosaicStatusOrigin: mosaicStatusOrigin,
|
mosaicStatusOrigin: mosaicStatusOrigin,
|
||||||
mosaicStatusSizeAndApply: mosaicStatusSizeAndApply,
|
mosaicStatusSizeAndApply: mosaicStatusSizeAndApply,
|
||||||
updatedShareButtonNode: updatedShareButtonNode,
|
needsShareButton: needShareButton
|
||||||
updatedShareButtonBackground: updatedShareButtonBackground
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -2282,8 +2245,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
contentContainerNodeFrames: [(UInt32, CGRect, Bool?, CGFloat)],
|
contentContainerNodeFrames: [(UInt32, CGRect, Bool?, CGFloat)],
|
||||||
mosaicStatusOrigin: CGPoint?,
|
mosaicStatusOrigin: CGPoint?,
|
||||||
mosaicStatusSizeAndApply: (CGSize, (Bool) -> ChatMessageDateAndStatusNode)?,
|
mosaicStatusSizeAndApply: (CGSize, (Bool) -> ChatMessageDateAndStatusNode)?,
|
||||||
updatedShareButtonNode: HighlightableButtonNode?,
|
needsShareButton: Bool
|
||||||
updatedShareButtonBackground: UIImage?
|
|
||||||
) -> Void {
|
) -> Void {
|
||||||
guard let strongSelf = selfReference.value else {
|
guard let strongSelf = selfReference.value else {
|
||||||
return
|
return
|
||||||
@ -2737,22 +2699,18 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
strongSelf.mosaicStatusNode = nil
|
strongSelf.mosaicStatusNode = nil
|
||||||
mosaicStatusNode.removeFromSupernode()
|
mosaicStatusNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
|
|
||||||
if let updatedShareButtonNode = updatedShareButtonNode {
|
if needsShareButton {
|
||||||
if updatedShareButtonNode !== strongSelf.shareButtonNode {
|
if strongSelf.shareButtonNode == nil {
|
||||||
if let shareButtonNode = strongSelf.shareButtonNode {
|
let shareButtonNode = ChatMessageShareButton()
|
||||||
shareButtonNode.removeFromSupernode()
|
strongSelf.shareButtonNode = shareButtonNode
|
||||||
}
|
strongSelf.insertSubnode(shareButtonNode, belowSubnode: strongSelf.messageAccessibilityArea)
|
||||||
strongSelf.shareButtonNode = updatedShareButtonNode
|
shareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
||||||
strongSelf.insertSubnode(updatedShareButtonNode, belowSubnode: strongSelf.messageAccessibilityArea)
|
|
||||||
updatedShareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
|
||||||
}
|
|
||||||
if let updatedShareButtonBackground = updatedShareButtonBackground {
|
|
||||||
strongSelf.shareButtonNode?.setBackgroundImage(updatedShareButtonBackground, for: [.normal])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
||||||
shareButtonNode.removeFromSupernode()
|
|
||||||
strongSelf.shareButtonNode = nil
|
strongSelf.shareButtonNode = nil
|
||||||
|
shareButtonNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
|
|
||||||
if case .System = animation, !strongSelf.mainContextSourceNode.isExtractedToContextPreview {
|
if case .System = animation, !strongSelf.mainContextSourceNode.isExtractedToContextPreview {
|
||||||
@ -2761,7 +2719,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
if let shareButtonNode = strongSelf.shareButtonNode {
|
if let shareButtonNode = strongSelf.shareButtonNode {
|
||||||
let currentBackgroundFrame = strongSelf.backgroundNode.frame
|
let currentBackgroundFrame = strongSelf.backgroundNode.frame
|
||||||
shareButtonNode.frame = CGRect(origin: CGPoint(x: currentBackgroundFrame.maxX + 8.0, y: currentBackgroundFrame.maxY - 30.0), size: CGSize(width: 29.0, height: 29.0))
|
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
||||||
|
shareButtonNode.frame = CGRect(origin: CGPoint(x: currentBackgroundFrame.maxX + 8.0, y: currentBackgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let _ = strongSelf.backgroundFrameTransition {
|
if let _ = strongSelf.backgroundFrameTransition {
|
||||||
@ -2770,7 +2729,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
strongSelf.messageAccessibilityArea.frame = backgroundFrame
|
strongSelf.messageAccessibilityArea.frame = backgroundFrame
|
||||||
if let shareButtonNode = strongSelf.shareButtonNode {
|
if let shareButtonNode = strongSelf.shareButtonNode {
|
||||||
shareButtonNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - 30.0), size: CGSize(width: 29.0, height: 29.0))
|
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
||||||
|
shareButtonNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
if case .System = animation, strongSelf.mainContextSourceNode.isExtractedToContextPreview {
|
if case .System = animation, strongSelf.mainContextSourceNode.isExtractedToContextPreview {
|
||||||
@ -2963,8 +2923,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
self.messageAccessibilityArea.frame = backgroundFrame
|
self.messageAccessibilityArea.frame = backgroundFrame
|
||||||
|
|
||||||
if let shareButtonNode = self.shareButtonNode {
|
if let item = self.item, let shareButtonNode = self.shareButtonNode {
|
||||||
shareButtonNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - 30.0), size: CGSize(width: 29.0, height: 29.0))
|
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
||||||
|
shareButtonNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
if CGFloat(1.0).isLessThanOrEqualTo(progress) {
|
if CGFloat(1.0).isLessThanOrEqualTo(progress) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user