mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit 'c22ca26aae8630b165c1648952f360dae03f5cac'
This commit is contained in:
commit
fde7516cf4
@ -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";
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
})
|
})
|
||||||
|
@ -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
|
|
||||||
var offsetCompleted = false
|
|
||||||
|
|
||||||
let internalCompletion: () -> Void = { [weak self] in
|
|
||||||
if let strongSelf = self, dimCompleted && offsetCompleted {
|
|
||||||
strongSelf.dismiss?()
|
|
||||||
}
|
|
||||||
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 offset = self.bounds.size.height - self.contentBackgroundNode.frame.minY
|
||||||
let dimPosition = self.dimNode.layer.position
|
self.wrappingScrollNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: -offset, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { [weak self] _ in
|
||||||
self.dimNode.layer.animatePosition(from: dimPosition, to: CGPoint(x: dimPosition.x, y: dimPosition.y - offset), duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false)
|
if let strongSelf = self {
|
||||||
self.layer.animateBoundsOriginYAdditive(from: 0.0, to: -offset, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in
|
strongSelf.dismiss?()
|
||||||
offsetCompleted = true
|
completion?()
|
||||||
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user