diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index 11f8e2384c..3c0b2ef2c5 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -62,7 +62,7 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel self.scrollNode = ASScrollNode() - self.chatBackgroundNode = WallpaperBackgroundNode(context: context) + self.chatBackgroundNode = createWallpaperBackgroundNode(context: context) self.chatBackgroundNode.displaysAsynchronously = false self.messagesContainerNode = ASDisplayNode() diff --git a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift index f9acade286..6db765af58 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift @@ -132,7 +132,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { return { item, params, neighbors in if currentBackgroundNode == nil { - currentBackgroundNode = WallpaperBackgroundNode(context: item.context) + currentBackgroundNode = createWallpaperBackgroundNode(context: item.context) } currentBackgroundNode?.update(wallpaper: item.wallpaper) currentBackgroundNode?.updateBubbleTheme(bubbleTheme: item.theme, bubbleCorners: item.chatBubbleCorners) diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index a60c77180c..ea3fb677f8 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -74,7 +74,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView self.pageControlNode = PageControlNode(dotSpacing: 7.0, dotColor: .white, inactiveDotColor: UIColor.white.withAlphaComponent(0.4)) self.chatListBackgroundNode = ASDisplayNode() - self.chatBackgroundNode = WallpaperBackgroundNode(context: context) + self.chatBackgroundNode = createWallpaperBackgroundNode(context: context) self.chatBackgroundNode.displaysAsynchronously = false self.messagesContainerNode = ASDisplayNode() diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index 85ef7f6e27..08afc2236b 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -285,7 +285,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate self.backgroundContainerNode = ASDisplayNode() self.backgroundContainerNode.clipsToBounds = true self.backgroundWrapperNode = ASDisplayNode() - self.backgroundNode = WallpaperBackgroundNode(context: context) + self.backgroundNode = createWallpaperBackgroundNode(context: context) self.messagesContainerNode = ASDisplayNode() self.messagesContainerNode.clipsToBounds = true @@ -1354,7 +1354,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate @objc private func playPressed() { if self.state.backgroundColors.count >= 3 || self.state.messagesColors.count >= 3 { - self.backgroundNode.animateEvent(transition: .animated(duration: 0.5, curve: .spring)) + self.backgroundNode.animateEvent(transition: .animated(duration: 0.5, curve: .spring), extendAnimation: false) } else { self.updateState({ state in var state = state diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index 81426ab556..7cb2af7755 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -107,7 +107,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { self.messagesContainerNode.clipsToBounds = true self.messagesContainerNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0) - self.instantChatBackgroundNode = WallpaperBackgroundNode(context: context) + self.instantChatBackgroundNode = createWallpaperBackgroundNode(context: context) self.instantChatBackgroundNode.displaysAsynchronously = false self.ready.set(.single(true)) @@ -121,7 +121,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { self.blurredNode = BlurredImageNode() self.blurredNode.blurView.contentMode = .scaleAspectFill - self.wallpaperNode = WallpaperBackgroundNode(context: context) + self.wallpaperNode = createWallpaperBackgroundNode(context: context) self.toolbarNode = WallpaperGalleryToolbarNode(theme: self.previewTheme, strings: self.presentationData.strings, doneButtonType: .set) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index 464280933b..064fa3e245 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -138,7 +138,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { return { item, params, neighbors in if currentBackgroundNode == nil { - currentBackgroundNode = WallpaperBackgroundNode(context: item.context) + currentBackgroundNode = createWallpaperBackgroundNode(context: item.context) } currentBackgroundNode?.update(wallpaper: item.wallpaper) currentBackgroundNode?.updateBubbleTheme(bubbleTheme: item.componentTheme, bubbleCorners: item.chatBubbleCorners) diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift index 55a93b4304..8d5a1921dc 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift @@ -136,7 +136,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode { self.wrapperNode = ASDisplayNode() self.imageNode = TransformImageNode() self.imageNode.contentAnimations = .subsequentUpdates - self.nativeNode = WallpaperBackgroundNode(context: context) + self.nativeNode = createWallpaperBackgroundNode(context: context) self.cropNode = WallpaperCropNode() self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.6)) self.statusNode.frame = CGRect(x: 0.0, y: 0.0, width: progressDiameter, height: progressDiameter) @@ -812,7 +812,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode { switch wallpaper { case let .gradient(gradient): if gradient.colors.count >= 3 { - self.nativeNode.animateEvent(transition: .animated(duration: 0.5, curve: .spring)) + self.nativeNode.animateEvent(transition: .animated(duration: 0.5, curve: .spring), extendAnimation: false) } else { let rotation = gradient.settings.rotation ?? 0 self.requestRotateGradient?((rotation + 90) % 360) @@ -820,7 +820,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode { case let .file(file): if file.isPattern { if file.settings.colors.count >= 3 { - self.nativeNode.animateEvent(transition: .animated(duration: 0.5, curve: .spring)) + self.nativeNode.animateEvent(transition: .animated(duration: 0.5, curve: .spring), extendAnimation: false) } else { let rotation = file.settings.rotation ?? 0 self.requestRotateGradient?((rotation + 90) % 360) diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index 5af7a8504e..424eb02b38 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -964,7 +964,7 @@ final class MessageStoryRenderer { self.containerNode = ASDisplayNode() - self.instantChatBackgroundNode = WallpaperBackgroundNode(context: context) + self.instantChatBackgroundNode = createWallpaperBackgroundNode(context: context) self.instantChatBackgroundNode.displaysAsynchronously = false self.messagesContainerNode = ASDisplayNode() diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 72986c4a17..208e5d0d30 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -508,7 +508,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G default: break } - self.chatBackgroundNode = WallpaperBackgroundNode(context: context, useSharedAnimationPhase: useSharedAnimationPhase) + self.chatBackgroundNode = createWallpaperBackgroundNode(context: context, useSharedAnimationPhase: useSharedAnimationPhase) self.wallpaperReady.set(self.chatBackgroundNode.isReady) var locationBroadcastPanelSource: LocationBroadcastPanelSource diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 492a7e02f4..d71507c2f3 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -370,7 +370,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if (strongSelf.context.sharedContext.currentPresentationData.with({ $0 })).reduceMotion { return } - strongSelf.backgroundNode.animateEvent(transition: transition) + strongSelf.backgroundNode.animateEvent(transition: transition, extendAnimation: false) } getMessageTransitionNode = { [weak self] in @@ -1648,7 +1648,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if (self.context.sharedContext.currentPresentationData.with({ $0 })).reduceMotion { return } - self.backgroundNode.animateEvent(transition: transition) + self.backgroundNode.animateEvent(transition: transition, extendAnimation: false) } //self.historyNode.didScrollWithOffset?(listBottomInset - previousListBottomInset, transition, nil) } diff --git a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift index 0559c304d1..2bcb2e1bf1 100644 --- a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift @@ -24,7 +24,7 @@ private func attributedServiceMessageString(theme: ChatPresentationThemeData, st class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { let labelNode: TextNode - var backgroundNode: WallpaperBackgroundNode.BubbleBackgroundNode? + var backgroundNode: WallpaperBubbleBackgroundNode? var backgroundColorNode: ASDisplayNode let backgroundMaskNode: ASImageNode var linkHighlightingNode: LinkHighlightingNode? @@ -327,7 +327,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { var backgroundFrame = backgroundNode.frame backgroundFrame.origin.x += rect.minX backgroundFrame.origin.y += rect.minY - backgroundNode.update(rect: backgroundFrame, within: containerSize) + backgroundNode.update(rect: backgroundFrame, within: containerSize, transition: .immediate) } } diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index e12c5e7da6..58a6272838 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -165,7 +165,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { private let containerNode: ContextControllerSourceNode let imageNode: TransformImageNode private var enableSynchronousImageApply: Bool = false - private var backgroundNode: WallpaperBackgroundNode.BubbleBackgroundNode? + private var backgroundNode: WallpaperBubbleBackgroundNode? private(set) var placeholderNode: StickerShimmerEffectNode private(set) var animationNode: GenericAnimatedStickerNode? private var animationSize: CGSize? @@ -650,7 +650,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { self.placeholderNode.updateAbsoluteRect(CGRect(origin: CGPoint(x: rect.minX + self.placeholderNode.frame.minX, y: rect.minY + self.placeholderNode.frame.minY), size: self.placeholderNode.frame.size), within: containerSize) if let backgroundNode = self.backgroundNode { - backgroundNode.update(rect: CGRect(origin: CGPoint(x: rect.minX + self.placeholderNode.frame.minX, y: rect.minY + self.placeholderNode.frame.minY), size: self.placeholderNode.frame.size), within: containerSize) + backgroundNode.update(rect: CGRect(origin: CGPoint(x: rect.minX + self.placeholderNode.frame.minX, y: rect.minY + self.placeholderNode.frame.minY), size: self.placeholderNode.frame.size), within: containerSize, transition: .immediate) } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleBackdrop.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleBackdrop.swift index f6ffd5ad36..a07d186ee2 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleBackdrop.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleBackdrop.swift @@ -55,7 +55,7 @@ func bubbleMaskForType(_ type: ChatMessageBackgroundType, graphics: PrincipalThe } final class ChatMessageBubbleBackdrop: ASDisplayNode { - private var backgroundContent: WallpaperBackgroundNode.BubbleBackgroundNode? + private var backgroundContent: WallpaperBubbleBackgroundNode? private var currentType: ChatMessageBackgroundType? private var currentMaskMode: Bool? @@ -86,7 +86,7 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode { var backgroundFrame = backgroundContent.frame backgroundFrame.origin.x += rect.minX backgroundFrame.origin.y += rect.minY - backgroundContent.update(rect: backgroundFrame, within: containerSize) + backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) } } } @@ -142,7 +142,7 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode { var backgroundFrame = backgroundContent.frame backgroundFrame.origin.x += rect.minX backgroundFrame.origin.y += rect.minY - backgroundContent.update(rect: backgroundFrame, within: containerSize) + backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) } } @@ -162,7 +162,7 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode { var backgroundFrame = backgroundContent.frame backgroundFrame.origin.x += rect.minX backgroundFrame.origin.y += rect.minY - backgroundContent.update(rect: backgroundFrame, within: containerSize) + backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) } self.backgroundContent = backgroundContent self.insertSubnode(backgroundContent, at: 0) @@ -174,7 +174,7 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode { var backgroundFrame = backgroundContent.frame backgroundFrame.origin.x += rect.minX backgroundFrame.origin.y += rect.minY - backgroundContent.update(rect: backgroundFrame, within: containerSize) + backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) } self.backgroundContent = backgroundContent self.insertSubnode(backgroundContent, at: 0) diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index 0cd36aa674..df013a2e16 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -22,7 +22,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { let contextSourceNode: ContextExtractedContentContainingNode private let containerNode: ContextControllerSourceNode let imageNode: TransformImageNode - private var backgroundNode: WallpaperBackgroundNode.BubbleBackgroundNode? + private var backgroundNode: WallpaperBubbleBackgroundNode? private var placeholderNode: StickerShimmerEffectNode var textNode: TextNode? @@ -250,7 +250,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { self.placeholderNode.updateAbsoluteRect(CGRect(origin: CGPoint(x: rect.minX + placeholderNode.frame.minX, y: rect.minY + placeholderNode.frame.minY), size: placeholderNode.frame.size), within: containerSize) if let backgroundNode = self.backgroundNode { - backgroundNode.update(rect: CGRect(origin: CGPoint(x: rect.minX + self.placeholderNode.frame.minX, y: rect.minY + self.placeholderNode.frame.minY), size: self.placeholderNode.frame.size), within: containerSize) + backgroundNode.update(rect: CGRect(origin: CGPoint(x: rect.minX + self.placeholderNode.frame.minX, y: rect.minY + self.placeholderNode.frame.minY), size: self.placeholderNode.frame.size), within: containerSize, transition: .immediate) } } } diff --git a/submodules/TelegramUI/Sources/ChatOverscrollControl.swift b/submodules/TelegramUI/Sources/ChatOverscrollControl.swift index 9f8ed51efd..42f36a207b 100644 --- a/submodules/TelegramUI/Sources/ChatOverscrollControl.swift +++ b/submodules/TelegramUI/Sources/ChatOverscrollControl.swift @@ -353,7 +353,7 @@ final class BadgeComponent: CombinedComponent { if lhs.withinSize != rhs.withinSize { return false } - if lhs.wallpaperNode != rhs.wallpaperNode { + if lhs.wallpaperNode !== rhs.wallpaperNode { return false } return true @@ -564,7 +564,7 @@ final class AvatarComponent: Component { } private final class WallpaperBlurNode: ASDisplayNode { - private var backgroundNode: WallpaperBackgroundNode.BubbleBackgroundNode? + private var backgroundNode: WallpaperBubbleBackgroundNode? private let colorNode: ASDisplayNode override init() { diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 2b4d58df4b..7268d74939 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -99,7 +99,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { self.automaticMediaDownloadSettings = context.sharedContext.currentAutomaticMediaDownloadSettings.with { $0 } - self.backgroundNode = WallpaperBackgroundNode(context: context) + self.backgroundNode = createWallpaperBackgroundNode(context: context) self.backgroundNode.isUserInteractionEnabled = false self.panelBackgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.chat.inputPanel.panelBackgroundColor) diff --git a/submodules/TelegramUI/Sources/ChatReplyCountItem.swift b/submodules/TelegramUI/Sources/ChatReplyCountItem.swift index 36aee95303..90eba140c6 100644 --- a/submodules/TelegramUI/Sources/ChatReplyCountItem.swift +++ b/submodules/TelegramUI/Sources/ChatReplyCountItem.swift @@ -64,7 +64,7 @@ class ChatReplyCountItem: ListViewItem { class ChatReplyCountItemNode: ListViewItemNode { var item: ChatReplyCountItem? private let labelNode: TextNode - private var backgroundNode: WallpaperBackgroundNode.BubbleBackgroundNode? + private var backgroundNode: WallpaperBubbleBackgroundNode? private let backgroundColorNode: ASDisplayNode private var theme: ChatPresentationThemeData? @@ -201,7 +201,7 @@ class ChatReplyCountItemNode: ListViewItemNode { backgroundFrame.origin.x += rect.minX backgroundFrame.origin.y += rect.minY - backgroundNode.update(rect: backgroundFrame, within: containerSize) + backgroundNode.update(rect: backgroundFrame, within: containerSize, transition: .immediate) } } diff --git a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift index c150c744e9..47fc43592d 100644 --- a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift +++ b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift @@ -27,25 +27,47 @@ private func generateBlurredContents(image: UIImage) -> UIImage? { return context.generateImage() } -public final class WallpaperBackgroundNode: ASDisplayNode { - public final class BubbleBackgroundNode: ASDisplayNode { - public enum BubbleType { - case incoming - case outgoing - case free - } +public enum WallpaperBubbleType { + case incoming + case outgoing + case free +} - private let bubbleType: BubbleType +public protocol WallpaperBubbleBackgroundNode: ASDisplayNode { + var frame: CGRect { get set } + + func update(rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition) + func update(rect: CGRect, within containerSize: CGSize, transition: CombinedTransition) + func offset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) + func offsetSpring(value: CGFloat, duration: Double, damping: CGFloat) +} + +public protocol WallpaperBackgroundNode: ASDisplayNode { + var isReady: Signal { get } + var rotation: CGFloat { get set } + + func update(wallpaper: TelegramWallpaper) + func _internalUpdateIsSettingUpWallpaper() + func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) + func animateEvent(transition: ContainedViewLayoutTransition, extendAnimation: Bool) + func updateBubbleTheme(bubbleTheme: PresentationTheme, bubbleCorners: PresentationChatBubbleCorners) + func hasBubbleBackground(for type: WallpaperBubbleType) -> Bool + func makeBubbleBackground(for type: WallpaperBubbleType) -> WallpaperBubbleBackgroundNode? +} + +final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode { + final class BubbleBackgroundNodeImpl: ASDisplayNode, WallpaperBubbleBackgroundNode { + private let bubbleType: WallpaperBubbleType private let contentNode: ASImageNode private var cleanWallpaperNode: ASDisplayNode? private var gradientWallpaperNode: GradientBackgroundNode.CloneNode? - private weak var backgroundNode: WallpaperBackgroundNode? - private var index: SparseBag.Index? + private weak var backgroundNode: WallpaperBackgroundNodeImpl? + private var index: SparseBag.Index? private var currentLayout: (rect: CGRect, containerSize: CGSize)? - public override var frame: CGRect { + override var frame: CGRect { didSet { if oldValue.size != self.bounds.size { self.contentNode.frame = self.bounds @@ -59,7 +81,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - init(backgroundNode: WallpaperBackgroundNode, bubbleType: BubbleType) { + init(backgroundNode: WallpaperBackgroundNodeImpl, bubbleType: WallpaperBubbleType) { self.backgroundNode = backgroundNode self.bubbleType = bubbleType @@ -210,7 +232,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - public func update(rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition = .immediate) { + func update(rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition = .immediate) { self.currentLayout = (rect, containerSize) let shiftedContentsRect = CGRect(origin: CGPoint(x: rect.minX / containerSize.width, y: rect.minY / containerSize.height), size: CGSize(width: rect.width / containerSize.width, height: rect.height / containerSize.height)) @@ -233,7 +255,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - public func update(rect: CGRect, within containerSize: CGSize, transition: CombinedTransition) { + func update(rect: CGRect, within containerSize: CGSize, transition: CombinedTransition) { self.currentLayout = (rect, containerSize) let shiftedContentsRect = CGRect(origin: CGPoint(x: rect.minX / containerSize.width, y: rect.minY / containerSize.height), size: CGSize(width: rect.width / containerSize.width, height: rect.height / containerSize.height)) @@ -250,7 +272,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - public func offset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) { + func offset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) { guard let (_, containerSize) = self.currentLayout else { return } @@ -267,7 +289,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - public func offsetSpring(value: CGFloat, duration: Double, damping: CGFloat) { + func offsetSpring(value: CGFloat, duration: Double, damping: CGFloat) { guard let (_, containerSize) = self.currentLayout else { return } @@ -285,9 +307,9 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } private final class BubbleBackgroundNodeReference { - weak var node: BubbleBackgroundNode? + weak var node: BubbleBackgroundNodeImpl? - init(node: BubbleBackgroundNode) { + init(node: BubbleBackgroundNodeImpl) { self.node = node } } @@ -303,6 +325,8 @@ public final class WallpaperBackgroundNode: ASDisplayNode { private let patternImageNode: ASImageNode private var isGeneratingPatternImage: Bool = false + private let bakedBackgroundView: UIImageView + private var validLayout: CGSize? private var wallpaper: TelegramWallpaper? private var isSettingUpWallpaper: Bool = false @@ -367,7 +391,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - public var rotation: CGFloat = 0.0 { + var rotation: CGFloat = 0.0 { didSet { var fromValue: CGFloat = 0.0 if let value = (self.layer.value(forKeyPath: "transform.rotation.z") as? NSNumber)?.floatValue { @@ -400,11 +424,11 @@ public final class WallpaperBackgroundNode: ASDisplayNode { private static var cachedSharedPattern: (PatternKey, UIImage)? private let _isReady = ValuePromise(false, ignoreRepeated: true) - public var isReady: Signal { + var isReady: Signal { return self._isReady.get() } - public init(context: AccountContext, useSharedAnimationPhase: Bool = false) { + init(context: AccountContext, useSharedAnimationPhase: Bool) { self.context = context self.useSharedAnimationPhase = useSharedAnimationPhase self.imageContentMode = .scaleAspectFill @@ -413,6 +437,9 @@ public final class WallpaperBackgroundNode: ASDisplayNode { self.contentNode.contentMode = self.imageContentMode self.patternImageNode = ASImageNode() + + self.bakedBackgroundView = UIImageView() + self.bakedBackgroundView.isHidden = true super.init() @@ -420,6 +447,8 @@ public final class WallpaperBackgroundNode: ASDisplayNode { self.contentNode.frame = self.bounds self.addSubnode(self.contentNode) self.addSubnode(self.patternImageNode) + + //self.view.addSubview(self.bakedBackgroundView) } deinit { @@ -428,7 +457,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { self.imageDisposable.dispose() } - public func update(wallpaper: TelegramWallpaper) { + func update(wallpaper: TelegramWallpaper) { if self.wallpaper == wallpaper { return } @@ -539,7 +568,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - public func _internalUpdateIsSettingUpWallpaper() { + func _internalUpdateIsSettingUpWallpaper() { self.isSettingUpWallpaper = true } @@ -622,7 +651,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { self.validPatternGeneratedImage = nil self.validPatternImage = nil - if let cachedValidPatternImage = WallpaperBackgroundNode.cachedValidPatternImage, cachedValidPatternImage.generated.wallpaper == wallpaper { + if let cachedValidPatternImage = WallpaperBackgroundNodeImpl.cachedValidPatternImage, cachedValidPatternImage.generated.wallpaper == wallpaper { self.validPatternImage = ValidPatternImage(wallpaper: cachedValidPatternImage.generated.wallpaper, generate: cachedValidPatternImage.generate) } else { func reference(for resource: EngineMediaResource, media: EngineMedia) -> MediaResourceReference { @@ -688,7 +717,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { if self.validPatternGeneratedImage != updatedGeneratedImage { self.validPatternGeneratedImage = updatedGeneratedImage - if let cachedValidPatternImage = WallpaperBackgroundNode.cachedValidPatternImage, cachedValidPatternImage.generated == updatedGeneratedImage { + if let cachedValidPatternImage = WallpaperBackgroundNodeImpl.cachedValidPatternImage, cachedValidPatternImage.generated == updatedGeneratedImage { self.patternImageNode.image = cachedValidPatternImage.image self.updatePatternPresentation() } else { @@ -700,7 +729,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { self.updatePatternPresentation() if self.useSharedAnimationPhase { - WallpaperBackgroundNode.cachedValidPatternImage = CachedValidPatternImage(generate: validPatternImage.generate, generated: updatedGeneratedImage, image: image) + WallpaperBackgroundNodeImpl.cachedValidPatternImage = CachedValidPatternImage(generate: validPatternImage.generate, generated: updatedGeneratedImage, image: image) } } else { self.updatePatternPresentation() @@ -721,7 +750,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { strongSelf.updatePatternPresentation() if let image = image, strongSelf.useSharedAnimationPhase { - WallpaperBackgroundNode.cachedValidPatternImage = CachedValidPatternImage(generate: validPatternImage.generate, generated: updatedGeneratedImage, image: image) + WallpaperBackgroundNodeImpl.cachedValidPatternImage = CachedValidPatternImage(generate: validPatternImage.generate, generated: updatedGeneratedImage, image: image) } } } @@ -743,7 +772,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { transition.updateFrame(node: self.patternImageNode, frame: CGRect(origin: CGPoint(), size: size)) } - public func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { + func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { let isFirstLayout = self.validLayout == nil self.validLayout = size @@ -767,12 +796,25 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - public func animateEvent(transition: ContainedViewLayoutTransition, extendAnimation: Bool = false) { + func animateEvent(transition: ContainedViewLayoutTransition, extendAnimation: Bool) { self.gradientBackgroundNode?.animateEvent(transition: transition, extendAnimation: extendAnimation) self.outgoingBubbleGradientBackgroundNode?.animateEvent(transition: transition, extendAnimation: extendAnimation) } - public func updateBubbleTheme(bubbleTheme: PresentationTheme, bubbleCorners: PresentationChatBubbleCorners) { + private func updateBakedBackground() { + guard let size = self.validLayout else { + return + } + let context = DrawingContext(size: size, scale: UIScreenScale, opaque: true) + + context.withContext { context in + context.clear(CGRect(origin: CGPoint(), size: size)) + } + + self.bakedBackgroundView.image = context.generateImage() + } + + func updateBubbleTheme(bubbleTheme: PresentationTheme, bubbleCorners: PresentationChatBubbleCorners) { if self.bubbleTheme !== bubbleTheme || self.bubbleCorners != bubbleCorners { self.bubbleTheme = bubbleTheme self.bubbleCorners = bubbleCorners @@ -801,7 +843,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - public func hasBubbleBackground(for type: WallpaperBackgroundNode.BubbleBackgroundNode.BubbleType) -> Bool { + func hasBubbleBackground(for type: WallpaperBubbleType) -> Bool { guard let bubbleTheme = self.bubbleTheme, let bubbleCorners = self.bubbleCorners else { return false } @@ -846,12 +888,138 @@ public final class WallpaperBackgroundNode: ASDisplayNode { return false } - public func makeBubbleBackground(for type: WallpaperBackgroundNode.BubbleBackgroundNode.BubbleType) -> WallpaperBackgroundNode.BubbleBackgroundNode? { + func makeBubbleBackground(for type: WallpaperBubbleType) -> WallpaperBubbleBackgroundNode? { if !self.hasBubbleBackground(for: type) { return nil } - let node = WallpaperBackgroundNode.BubbleBackgroundNode(backgroundNode: self, bubbleType: type) + let node = WallpaperBackgroundNodeImpl.BubbleBackgroundNodeImpl(backgroundNode: self, bubbleType: type) node.updateContents() return node } } + +final class WallpaperBackgroundNodeMergedImpl: ASDisplayNode, WallpaperBackgroundNode { + final class SharedStorage { + } + + private class WallpaperComponentView: UIView { + let updated: () -> Void + + init(updated: @escaping () -> Void) { + self.updated = updated + + super.init(frame: CGRect()) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } + + private final class WallpaperGradiendComponentView: WallpaperComponentView { + struct Spec { + var colors: [UInt32] + } + } + + private final class WallpaperPatternComponentView: WallpaperComponentView { + struct Spec { + } + } + + private let context: AccountContext + private let storage: SharedStorage + + private let staticView: UIImageView + private var gradient: WallpaperGradiendComponentView? + private var pattern: WallpaperPatternComponentView? + + private let _isReady = ValuePromise(false, ignoreRepeated: true) + var isReady: Signal { + return self._isReady.get() + } + + var rotation: CGFloat = 0.0 { + didSet { + } + } + + init(context: AccountContext, storage: SharedStorage?) { + self.context = context + self.storage = storage ?? SharedStorage() + + self.staticView = UIImageView() + + super.init() + + self.view.addSubview(self.staticView) + } + + func update(wallpaper: TelegramWallpaper) { + var gradientSpec: WallpaperGradiendComponentView.Spec? + + switch wallpaper { + case let .builtin(wallpaperSettings): + let _ = wallpaperSettings + case let .color(color): + let _ = color + case let .gradient(gradient): + if gradient.colors.count >= 3 { + gradientSpec = WallpaperGradiendComponentView.Spec(colors: gradient.colors) + } + case let .image(representations, settings): + let _ = representations + let _ = settings + case let .file(file): + if file.settings.colors.count >= 3 { + gradientSpec = WallpaperGradiendComponentView.Spec(colors: file.settings.colors) + } + } + + if let gradientSpec = gradientSpec { + let gradient: WallpaperGradiendComponentView + if let current = self.gradient { + gradient = current + } else { + gradient = WallpaperGradiendComponentView(updated: { [weak self] in + self?.componentsUpdated() + }) + } + let _ = gradient + let _ = gradientSpec + } else if let gradient = self.gradient { + self.gradient = nil + gradient.removeFromSuperview() + } + } + + private func componentsUpdated() { + } + + func _internalUpdateIsSettingUpWallpaper() { + } + + func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { + + } + + func animateEvent(transition: ContainedViewLayoutTransition, extendAnimation: Bool) { + + } + + func updateBubbleTheme(bubbleTheme: PresentationTheme, bubbleCorners: PresentationChatBubbleCorners) { + + } + + func hasBubbleBackground(for type: WallpaperBubbleType) -> Bool { + return false + } + + func makeBubbleBackground(for type: WallpaperBubbleType) -> WallpaperBubbleBackgroundNode? { + return nil + } +} + +public func createWallpaperBackgroundNode(context: AccountContext, useSharedAnimationPhase: Bool = false) -> WallpaperBackgroundNode { + return WallpaperBackgroundNodeImpl(context: context, useSharedAnimationPhase: useSharedAnimationPhase) +}