Merge commit 'c22ca26aae8630b165c1648952f360dae03f5cac'

This commit is contained in:
Ali 2021-09-12 22:42:23 +04:00
commit fde7516cf4
7 changed files with 131 additions and 54 deletions

View File

@ -6721,6 +6721,8 @@ Sorry for the inconvenience.";
"Conversation.Theme.DontSetTheme" = "Do Not Set Theme"; "Conversation.Theme.DontSetTheme" = "Do Not Set Theme";
"Conversation.Theme.SwitchToDark" = "Switch to dark appearance"; "Conversation.Theme.SwitchToDark" = "Switch to dark appearance";
"Conversation.Theme.SwitchToLight" = "Switch to light appearance"; "Conversation.Theme.SwitchToLight" = "Switch to light appearance";
"Conversation.Theme.DismissAlert" = "Do you want to apply the selected theme to the chat?";
"Conversation.Theme.DismissAlertApply" = "Apply";
"Notification.ChangedTheme" = "%1$@ changed chat theme to %2$@"; "Notification.ChangedTheme" = "%1$@ changed chat theme to %2$@";
"Notification.DisabledTheme" = "%@ disabled chat theme"; "Notification.DisabledTheme" = "%@ disabled chat theme";

View File

@ -24,8 +24,11 @@ public final class AnimationNode : ASDisplayNode {
return self.animationView()?.isAnimationPlaying ?? false return self.animationView()?.isAnimationPlaying ?? false
} }
private var currentParams: (String?, [String: UIColor]?)?
public init(animation: String? = nil, colors: [String: UIColor]? = nil, scale: CGFloat = 1.0) { public init(animation: String? = nil, colors: [String: UIColor]? = nil, scale: CGFloat = 1.0) {
self.scale = scale self.scale = scale
self.currentParams = (animation, colors)
super.init() super.init()
@ -80,11 +83,23 @@ public final class AnimationNode : ASDisplayNode {
}) })
} }
public func makeCopy(colors: [String: UIColor]? = nil, progress: CGFloat? = nil) -> AnimationNode? {
guard let (animation, currentColors) = self.currentParams else {
return nil
}
let animationNode = AnimationNode(animation: animation, colors: colors ?? currentColors, scale: 1.0)
animationNode.animationView()?.play(fromProgress: progress ?? (self.animationView()?.animationProgress ?? 0.0), toProgress: 1.0, withCompletion: { [weak animationNode] _ in
animationNode?.completion?()
})
return animationNode
}
public func seekToEnd() { public func seekToEnd() {
self.animationView()?.animationProgress = 1.0 self.animationView()?.animationProgress = 1.0
} }
public func setAnimation(name: String, colors: [String: UIColor]? = nil) { public func setAnimation(name: String, colors: [String: UIColor]? = nil) {
self.currentParams = (name, colors)
if let url = getAppBundle().url(forResource: name, withExtension: "json"), let composition = LOTComposition(filePath: url.path) { if let url = getAppBundle().url(forResource: name, withExtension: "json"), let composition = LOTComposition(filePath: url.path) {
self.didPlay = false self.didPlay = false
self.animationView()?.sceneModel = composition self.animationView()?.sceneModel = composition

View File

@ -310,6 +310,13 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
private final var actionsForVSync: [() -> ()] = [] private final var actionsForVSync: [() -> ()] = []
private final var inVSync = false private final var inVSync = false
private var tapGestureRecognizer: UITapGestureRecognizer?
public final var tapped: (() -> Void)? {
didSet {
self.tapGestureRecognizer?.isEnabled = self.tapped != nil
}
}
private let frictionSlider = UISlider() private let frictionSlider = UISlider()
private let springSlider = UISlider() private let springSlider = UISlider()
private let freeResistanceSlider = UISlider() private let freeResistanceSlider = UISlider()
@ -420,6 +427,12 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
self?.updateReordering(offset: offset) self?.updateReordering(offset: offset)
})) }))
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))
tapGestureRecognizer.isEnabled = false
tapGestureRecognizer.delegate = self
self.view.addGestureRecognizer(tapGestureRecognizer)
self.tapGestureRecognizer = tapGestureRecognizer
self.displayLink = CADisplayLink(target: DisplayLinkProxy(target: self), selector: #selector(DisplayLinkProxy.displayLinkEvent)) self.displayLink = CADisplayLink(target: DisplayLinkProxy(target: self), selector: #selector(DisplayLinkProxy.displayLinkEvent))
self.displayLink.add(to: RunLoop.main, forMode: RunLoop.Mode.common) self.displayLink.add(to: RunLoop.main, forMode: RunLoop.Mode.common)
@ -449,6 +462,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
self.reorderFeedbackDisposable?.dispose() self.reorderFeedbackDisposable?.dispose()
} }
@objc private func tapGesture(_ gestureRecognizer: UITapGestureRecognizer) {
self.tapped?()
}
private func displayLinkEvent() { private func displayLinkEvent() {
self.updateAnimations() self.updateAnimations()
} }

View File

@ -1126,6 +1126,7 @@ public class Account {
self.managedOperationsDisposable.add(managedSynchronizeAppLogEventsOperations(postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedSynchronizeAppLogEventsOperations(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedNotificationSettingsBehaviors(postbox: self.postbox).start()) self.managedOperationsDisposable.add(managedNotificationSettingsBehaviors(postbox: self.postbox).start())
self.managedOperationsDisposable.add(managedThemesUpdates(accountManager: accountManager, postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedThemesUpdates(accountManager: accountManager, postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedChatThemesUpdates(accountManager: accountManager, network: self.network).start())
if !self.supplementary { if !self.supplementary {
self.managedOperationsDisposable.add(managedAnimatedEmojiUpdates(postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedAnimatedEmojiUpdates(postbox: self.postbox, network: self.network).start())

View File

@ -101,7 +101,7 @@ func _internal_getChatThemes(accountManager: AccountManager<TelegramAccountManag
} }
} }
|> mapToSignal { current, hash -> Signal<[ChatTheme], NoError> in |> mapToSignal { current, hash -> Signal<[ChatTheme], NoError> in
if onlyCached { if onlyCached && !current.isEmpty {
return .single(current) return .single(current)
} else { } else {
return .single(current) return .single(current)
@ -151,3 +151,11 @@ extension ChatTheme {
} }
} }
} }
func managedChatThemesUpdates(accountManager: AccountManager<TelegramAccountManagerTypes>, network: Network) -> Signal<Void, NoError> {
let poll = _internal_getChatThemes(accountManager: accountManager, network: network)
|> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
}
return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
}

View File

@ -3924,7 +3924,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let accountManager = context.sharedContext.accountManager let accountManager = context.sharedContext.accountManager
let currentThemeEmoticon = Atomic<(String?, Bool)?>(value: nil) let currentThemeEmoticon = Atomic<(String?, Bool)?>(value: nil)
self.presentationDataDisposable = combineLatest(queue: Queue.mainQueue(), context.sharedContext.presentationData, themeSettings, context.engine.themes.getChatThemes(accountManager: accountManager, onlyCached: false), themeEmoticon, self.themeEmoticonAndDarkAppearancePreviewPromise.get()).start(next: { [weak self] presentationData, themeSettings, chatThemes, themeEmoticon, themeEmoticonAndDarkAppearance in self.presentationDataDisposable = combineLatest(queue: Queue.mainQueue(), context.sharedContext.presentationData, themeSettings, context.engine.themes.getChatThemes(accountManager: accountManager, onlyCached: true), themeEmoticon, self.themeEmoticonAndDarkAppearancePreviewPromise.get()).start(next: { [weak self] presentationData, themeSettings, chatThemes, themeEmoticon, themeEmoticonAndDarkAppearance in
if let strongSelf = self { if let strongSelf = self {
let (themeEmoticonPreview, darkAppearancePreview) = themeEmoticonAndDarkAppearance let (themeEmoticonPreview, darkAppearancePreview) = themeEmoticonAndDarkAppearance
@ -13460,6 +13460,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return nil return nil
} }
} }
controller.dismissed = { [weak self] in
if let strongSelf = self {
strongSelf.chatDisplayNode.historyNode.tapped = nil
}
}
strongSelf.chatDisplayNode.historyNode.tapped = { [weak controller] in
controller?.dimTapped()
}
strongSelf.present(controller, in: .window(.root)) strongSelf.present(controller, in: .window(.root))
strongSelf.themeSceen = controller strongSelf.themeSceen = controller
}) })

View File

@ -529,6 +529,8 @@ final class ChatThemeScreen: ViewController {
private var presentationData: PresentationData private var presentationData: PresentationData
private var presentationDataDisposable: Disposable? private var presentationDataDisposable: Disposable?
var dismissed: (() -> Void)?
var passthroughHitTestImpl: ((CGPoint) -> UIView?)? { var passthroughHitTestImpl: ((CGPoint) -> UIView?)? {
didSet { didSet {
if self.isNodeLoaded { if self.isNodeLoaded {
@ -572,7 +574,7 @@ final class ChatThemeScreen: ViewController {
} }
override public func loadDisplayNode() { override public func loadDisplayNode() {
self.displayNode = ChatThemeScreenNode(context: self.context, presentationData: self.presentationData, animatedEmojiStickers: self.animatedEmojiStickers, initiallySelectedEmoticon: self.initiallySelectedEmoticon, dismissByTapOutside: self.dismissByTapOutside) self.displayNode = ChatThemeScreenNode(context: self.context, presentationData: self.presentationData, controller: self, animatedEmojiStickers: self.animatedEmojiStickers, initiallySelectedEmoticon: self.initiallySelectedEmoticon, dismissByTapOutside: self.dismissByTapOutside)
self.controllerNode.passthroughHitTestImpl = self.passthroughHitTestImpl self.controllerNode.passthroughHitTestImpl = self.passthroughHitTestImpl
self.controllerNode.previewTheme = { [weak self] emoticon, dark in self.controllerNode.previewTheme = { [weak self] emoticon, dark in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -629,6 +631,8 @@ final class ChatThemeScreen: ViewController {
}) })
self.controllerNode.animateOut(completion: completion) self.controllerNode.animateOut(completion: completion)
self.dismissed?()
} }
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
@ -636,6 +640,10 @@ final class ChatThemeScreen: ViewController {
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition) self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
} }
func dimTapped() {
self.controllerNode.dimTapped()
}
} }
private func iconColors(theme: PresentationTheme) -> [String: UIColor] { private func iconColors(theme: PresentationTheme) -> [String: UIColor] {
@ -658,6 +666,7 @@ private func iconColors(theme: PresentationTheme) -> [String: UIColor] {
private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelegate {
private let context: AccountContext private let context: AccountContext
private var presentationData: PresentationData private var presentationData: PresentationData
private weak var controller: ChatThemeScreen?
private let dismissByTapOutside: Bool private let dismissByTapOutside: Bool
private let dimNode: ASDisplayNode private let dimNode: ASDisplayNode
@ -671,7 +680,8 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
private let textNode: ImmediateTextNode private let textNode: ImmediateTextNode
private let cancelButton: HighlightableButtonNode private let cancelButton: HighlightableButtonNode
private let switchThemeButton: HighlightTrackingButtonNode private let switchThemeButton: HighlightTrackingButtonNode
private let animationNode: AnimationNode private let animationContainerNode: ASDisplayNode
private var animationNode: AnimationNode
private let doneButton: SolidRoundedButtonNode private let doneButton: SolidRoundedButtonNode
private let listNode: ListView private let listNode: ListView
@ -704,8 +714,9 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
var dismiss: (() -> Void)? var dismiss: (() -> Void)?
var cancel: (() -> Void)? var cancel: (() -> Void)?
init(context: AccountContext, presentationData: PresentationData, animatedEmojiStickers: [String: [StickerPackItem]], initiallySelectedEmoticon: String?, dismissByTapOutside: Bool) { init(context: AccountContext, presentationData: PresentationData, controller: ChatThemeScreen, animatedEmojiStickers: [String: [StickerPackItem]], initiallySelectedEmoticon: String?, dismissByTapOutside: Bool) {
self.context = context self.context = context
self.controller = controller
self.initiallySelectedEmoticon = initiallySelectedEmoticon self.initiallySelectedEmoticon = initiallySelectedEmoticon
self.selectedEmoticon = initiallySelectedEmoticon self.selectedEmoticon = initiallySelectedEmoticon
self.selectedEmoticonPromise = ValuePromise(initiallySelectedEmoticon) self.selectedEmoticonPromise = ValuePromise(initiallySelectedEmoticon)
@ -754,6 +765,9 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
self.cancelButton.setImage(closeButtonImage(theme: self.presentationData.theme), for: .normal) self.cancelButton.setImage(closeButtonImage(theme: self.presentationData.theme), for: .normal)
self.switchThemeButton = HighlightTrackingButtonNode() self.switchThemeButton = HighlightTrackingButtonNode()
self.animationContainerNode = ASDisplayNode()
self.animationContainerNode.isUserInteractionEnabled = false
self.animationNode = AnimationNode(animation: self.isDarkAppearance ? "anim_sun_reverse" : "anim_sun", colors: iconColors(theme: self.presentationData.theme), scale: 1.0) self.animationNode = AnimationNode(animation: self.isDarkAppearance ? "anim_sun_reverse" : "anim_sun", colors: iconColors(theme: self.presentationData.theme), scale: 1.0)
self.animationNode.isUserInteractionEnabled = false self.animationNode.isUserInteractionEnabled = false
@ -768,7 +782,6 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
self.backgroundColor = nil self.backgroundColor = nil
self.isOpaque = false self.isOpaque = false
self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:))))
self.addSubnode(self.dimNode) self.addSubnode(self.dimNode)
self.wrappingScrollNode.view.delegate = self self.wrappingScrollNode.view.delegate = self
@ -784,7 +797,8 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
self.contentContainerNode.addSubnode(self.textNode) self.contentContainerNode.addSubnode(self.textNode)
self.contentContainerNode.addSubnode(self.doneButton) self.contentContainerNode.addSubnode(self.doneButton)
self.topContentContainerNode.addSubnode(self.animationNode) self.topContentContainerNode.addSubnode(self.animationContainerNode)
self.animationContainerNode.addSubnode(self.animationNode)
self.topContentContainerNode.addSubnode(self.switchThemeButton) self.topContentContainerNode.addSubnode(self.switchThemeButton)
self.topContentContainerNode.addSubnode(self.listNode) self.topContentContainerNode.addSubnode(self.listNode)
self.topContentContainerNode.addSubnode(self.cancelButton) self.topContentContainerNode.addSubnode(self.cancelButton)
@ -820,7 +834,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
let action: (String?) -> Void = { [weak self] emoticon in let action: (String?) -> Void = { [weak self] emoticon in
if let strongSelf = self, strongSelf.selectedEmoticon != emoticon { if let strongSelf = self, strongSelf.selectedEmoticon != emoticon {
strongSelf.animateCrossfade(animateBackground: strongSelf.presentationData.theme.overallDarkAppearance, updateSunIcon: true) strongSelf.animateCrossfade(animateIcon: false)
strongSelf.previewTheme?(emoticon, strongSelf.isDarkAppearance) strongSelf.previewTheme?(emoticon, strongSelf.isDarkAppearance)
strongSelf.selectedEmoticon = emoticon strongSelf.selectedEmoticon = emoticon
@ -928,11 +942,6 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
let previousTheme = self.presentationData.theme let previousTheme = self.presentationData.theme
self.presentationData = presentationData self.presentationData = presentationData
if let effectView = self.effectNode.view as? UIVisualEffectView {
effectView.effect = UIBlurEffect(style: presentationData.theme.actionSheet.backgroundType == .light ? .light : .dark)
}
self.contentBackgroundNode.backgroundColor = self.presentationData.theme.actionSheet.itemBackgroundColor
self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor) self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
if previousTheme !== presentationData.theme, let (layout, navigationBarHeight) = self.containerLayout { if previousTheme !== presentationData.theme, let (layout, navigationBarHeight) = self.containerLayout {
@ -943,7 +952,19 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
self.doneButton.updateTheme(SolidRoundedButtonTheme(theme: self.presentationData.theme)) self.doneButton.updateTheme(SolidRoundedButtonTheme(theme: self.presentationData.theme))
if self.animationNode.isPlaying { if self.animationNode.isPlaying {
if let animationNode = self.animationNode.makeCopy(colors: iconColors(theme: self.presentationData.theme), progress: 0.25) {
let previousAnimationNode = self.animationNode
self.animationNode = animationNode
animationNode.completion = { [weak previousAnimationNode] in
previousAnimationNode?.removeFromSupernode()
}
animationNode.isUserInteractionEnabled = false
animationNode.frame = previousAnimationNode.frame
previousAnimationNode.supernode?.insertSubnode(animationNode, belowSubnode: previousAnimationNode)
previousAnimationNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
animationNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
} else { } else {
self.animationNode.setAnimation(name: self.isDarkAppearance ? "anim_sun_reverse" : "anim_sun", colors: iconColors(theme: self.presentationData.theme)) self.animationNode.setAnimation(name: self.isDarkAppearance ? "anim_sun_reverse" : "anim_sun", colors: iconColors(theme: self.presentationData.theme))
} }
@ -963,8 +984,21 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
self.cancel?() self.cancel?()
} }
func dimTapped() {
if self.selectedEmoticon == self.initiallySelectedEmoticon {
self.cancelButtonPressed()
} else {
let alertController = textAlertController(context: self.context, updatedPresentationData: (self.presentationData, .single(self.presentationData)), title: nil, text: self.presentationData.strings.Conversation_Theme_DismissAlert, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Conversation_Theme_DismissAlertApply, action: { [weak self] in
if let strongSelf = self {
strongSelf.completion?(strongSelf.selectedEmoticon)
}
})], actionLayout: .horizontal, dismissOnOutsideTap: true)
self.present?(alertController)
}
}
@objc func switchThemePressed() { @objc func switchThemePressed() {
self.animateCrossfade(animateBackground: true) self.animateCrossfade(animateIcon: false)
self.animationNode.setAnimation(name: self.isDarkAppearance ? "anim_sun_reverse" : "anim_sun", colors: iconColors(theme: self.presentationData.theme)) self.animationNode.setAnimation(name: self.isDarkAppearance ? "anim_sun_reverse" : "anim_sun", colors: iconColors(theme: self.presentationData.theme))
self.animationNode.playOnce() self.animationNode.playOnce()
@ -975,16 +1009,10 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
let _ = ApplicationSpecificNotice.incrementChatSpecificThemesDarkPreviewTip(accountManager: self.context.sharedContext.accountManager, count: 3).start() let _ = ApplicationSpecificNotice.incrementChatSpecificThemesDarkPreviewTip(accountManager: self.context.sharedContext.accountManager, count: 3).start()
} }
@objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) { private func animateCrossfade(animateIcon: Bool = true) {
if self.dismissByTapOutside, case .ended = recognizer.state {
self.cancelButtonPressed()
}
}
private func animateCrossfade(animateBackground: Bool = true, updateSunIcon: Bool = false) {
let delay: Double = 0.2 let delay: Double = 0.2
if let snapshotView = self.animationNode.view.snapshotView(afterScreenUpdates: false) { if animateIcon, let snapshotView = self.animationNode.view.snapshotView(afterScreenUpdates: false) {
snapshotView.frame = self.animationNode.frame snapshotView.frame = self.animationNode.frame
self.animationNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.animationNode.view) self.animationNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.animationNode.view)
@ -993,13 +1021,17 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
}) })
} }
if animateBackground, let snapshotView = self.backgroundNode.view.snapshotView(afterScreenUpdates: false) { Queue.mainQueue().after(delay) {
snapshotView.frame = self.backgroundNode.frame if let effectView = self.effectNode.view as? UIVisualEffectView {
self.backgroundNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.backgroundNode.view) UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveEaseInOut) {
effectView.effect = UIBlurEffect(style: self.presentationData.theme.actionSheet.backgroundType == .light ? .light : .dark)
} completion: { _ in
}
}
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, delay: delay, removeOnCompletion: false, completion: { [weak snapshotView] _ in let previousColor = self.contentBackgroundNode.backgroundColor ?? .clear
snapshotView?.removeFromSuperview() self.contentBackgroundNode.backgroundColor = self.presentationData.theme.actionSheet.itemBackgroundColor
}) self.contentBackgroundNode.layer.animate(from: previousColor.cgColor, to: (self.contentBackgroundNode.backgroundColor ?? .clear).cgColor, keyPath: "backgroundColor", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.3)
} }
if let snapshotView = self.contentContainerNode.view.snapshotView(afterScreenUpdates: false) { if let snapshotView = self.contentContainerNode.view.snapshotView(afterScreenUpdates: false) {
@ -1055,33 +1087,26 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
func animateOut(completion: (() -> Void)? = nil) { func animateOut(completion: (() -> Void)? = nil) {
self.animatedOut = true self.animatedOut = true
var dimCompleted = false let offset = self.bounds.size.height - self.contentBackgroundNode.frame.minY
var offsetCompleted = false self.wrappingScrollNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: -offset, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { [weak self] _ in
if let strongSelf = self {
let internalCompletion: () -> Void = { [weak self] in
if let strongSelf = self, dimCompleted && offsetCompleted {
strongSelf.dismiss?() strongSelf.dismiss?()
}
completion?() completion?()
} }
self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { _ in
dimCompleted = true
internalCompletion()
})
let offset = self.bounds.size.height - self.contentBackgroundNode.frame.minY
let dimPosition = self.dimNode.layer.position
self.dimNode.layer.animatePosition(from: dimPosition, to: CGPoint(x: dimPosition.x, y: dimPosition.y - offset), duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false)
self.layer.animateBoundsOriginYAdditive(from: 0.0, to: -offset, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in
offsetCompleted = true
internalCompletion()
}) })
} }
var passthroughHitTestImpl: ((CGPoint) -> UIView?)? var passthroughHitTestImpl: ((CGPoint) -> UIView?)?
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.bounds.contains(point) { var presentingAlertController = false
self.controller?.forEachController({ c in
if c is AlertController {
presentingAlertController = true
}
return true
})
if !presentingAlertController && self.bounds.contains(point) {
if !self.contentBackgroundNode.bounds.contains(self.convert(point, to: self.contentBackgroundNode)) { if !self.contentBackgroundNode.bounds.contains(self.convert(point, to: self.contentBackgroundNode)) {
if let result = self.passthroughHitTestImpl?(point) { if let result = self.passthroughHitTestImpl?(point) {
return result return result
@ -1136,7 +1161,8 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
let switchThemeSize = CGSize(width: 44.0, height: 44.0) let switchThemeSize = CGSize(width: 44.0, height: 44.0)
let switchThemeFrame = CGRect(origin: CGPoint(x: 3.0, y: 6.0), size: switchThemeSize) let switchThemeFrame = CGRect(origin: CGPoint(x: 3.0, y: 6.0), size: switchThemeSize)
transition.updateFrame(node: self.switchThemeButton, frame: switchThemeFrame) transition.updateFrame(node: self.switchThemeButton, frame: switchThemeFrame)
transition.updateFrame(node: self.animationNode, frame: switchThemeFrame.insetBy(dx: 9.0, dy: 9.0)) transition.updateFrame(node: self.animationContainerNode, frame: switchThemeFrame.insetBy(dx: 9.0, dy: 9.0))
transition.updateFrame(node: self.animationNode, frame: CGRect(origin: CGPoint(), size: self.animationContainerNode.frame.size))
let cancelSize = CGSize(width: 44.0, height: 44.0) let cancelSize = CGSize(width: 44.0, height: 44.0)
let cancelFrame = CGRect(origin: CGPoint(x: contentFrame.width - cancelSize.width - 3.0, y: 6.0), size: cancelSize) let cancelFrame = CGRect(origin: CGPoint(x: contentFrame.width - cancelSize.width - 3.0, y: 6.0), size: cancelSize)