From 9397ece5a800488641d33d4677917e2dbd9775fa Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 31 Oct 2025 18:23:12 +0400 Subject: [PATCH] Update --- .../ContainedViewLayoutTransition.swift | 77 +++++++++++++++++++ .../Sources/SolidRoundedButtonNode.swift | 4 +- .../ChatMessageActionButtonsNode.swift | 12 ++- .../Sources/ChatTextInputPanelNode.swift | 2 +- .../ChatInterfaceTitlePanelNodes.swift | 14 +++- 5 files changed, 102 insertions(+), 7 deletions(-) diff --git a/submodules/Display/Source/ContainedViewLayoutTransition.swift b/submodules/Display/Source/ContainedViewLayoutTransition.swift index d7ff761a96..b8b231b0f4 100644 --- a/submodules/Display/Source/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Source/ContainedViewLayoutTransition.swift @@ -1998,6 +1998,7 @@ public protocol ControlledTransitionAnimator: AnyObject { func updateContentsRect(layer: CALayer, contentsRect: CGRect, completion: ((Bool) -> Void)?) func updateTransform(layer: CALayer, transform: CATransform3D, completion: ((Bool) -> Void)?) func updateBackgroundColor(layer: CALayer, color: UIColor, completion: ((Bool) -> Void)?) + func updateShapeLayerPath(layer: CAShapeLayer, path: CGPath, completion: ((Bool) -> Void)?) } protocol AnyValueProviding { @@ -2214,6 +2215,37 @@ extension CGColor: AnyValueProviding { } } +extension CGPath: AnyValueProviding { + func interpolate(with other: CGPath, fraction: CGFloat) -> CGPath { + if fraction == 0.0 { + return self + } else { + return other + } + } + + var anyValue: ControlledTransitionProperty.AnyValue { + return ControlledTransitionProperty.AnyValue( + value: self, + nsValue: self, + stringValue: { "\(self)" }, + isEqual: { other in + if CFGetTypeID(other.value as CFTypeRef) == CGPath.typeID { + return self == (other.value as! CGPath) + } else { + return false + } + }, + interpolate: { other, fraction in + guard CFGetTypeID(other.value as CFTypeRef) == CGColor.typeID else { + preconditionFailure() + } + return self.interpolate(with: other.value as! CGPath, fraction: fraction).anyValue + } + ) + } +} + final class ControlledTransitionProperty { final class AnyValue: Equatable, CustomStringConvertible { let value: Any @@ -2549,6 +2581,47 @@ public final class ControlledTransition { )) } + public func updateShapeLayerPath(layer: CAShapeLayer, path: CGPath, completion: ((Bool) -> Void)?) { + if let currentPath = layer.path, currentPath == path { + if let completion = completion { + completion(true) + } + return + } + + let fromValue: CGPath? + if let animationKeys = layer.animationKeys(), animationKeys.contains(where: { key in + guard let animation = layer.animation(forKey: key) as? CAPropertyAnimation else { + return false + } + if animation.keyPath == "path" { + return true + } else { + return false + } + }) { + fromValue = layer.presentation()?.path ?? layer.path + } else { + fromValue = layer.path + } + + var mappedFromValue: CGPath + if let fromValue { + mappedFromValue = fromValue + } else { + mappedFromValue = CGMutablePath() + } + + layer.path = path + self.add(animation: ControlledTransitionProperty( + layer: layer, + path: "path", + fromValue: mappedFromValue, + toValue: path, + completion: completion + )) + } + public func updateCornerRadius(layer: CALayer, cornerRadius: CGFloat, completion: ((Bool) -> Void)?) { if layer.cornerRadius == cornerRadius { return @@ -2630,6 +2703,10 @@ public final class ControlledTransition { self.transition.updateBackgroundColor(layer: layer, color: color, completion: completion) } + public func updateShapeLayerPath(layer: CAShapeLayer, path: CGPath, completion: ((Bool) -> Void)?) { + self.transition.updatePath(layer: layer, path: path, completion: completion) + } + public func animatePosition(layer: CALayer, from fromValue: CGPoint, to toValue: CGPoint, completion: ((Bool) -> Void)?) { self.transition.animatePosition(layer: layer, from: fromValue, to: toValue, completion: completion) } diff --git a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift index 16f4a349ad..264e6422e4 100644 --- a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift +++ b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift @@ -166,6 +166,7 @@ private final class BadgeNode: ASDisplayNode { public final class SolidRoundedButtonNode: ASDisplayNode { private var theme: SolidRoundedButtonTheme private var glass: Bool + private var glassInset: Bool private var fontSize: CGFloat private let isShimmering: Bool @@ -342,9 +343,10 @@ public final class SolidRoundedButtonNode: ASDisplayNode { } } - public init(title: String? = nil, icon: UIImage? = nil, theme: SolidRoundedButtonTheme, glass: Bool = false, font: SolidRoundedButtonFont = .bold, fontSize: CGFloat = 17.0, height: CGFloat = 48.0, cornerRadius: CGFloat = 24.0, isShimmering: Bool = false) { + public init(title: String? = nil, icon: UIImage? = nil, theme: SolidRoundedButtonTheme, glass: Bool = false, glassInset: Bool = false, font: SolidRoundedButtonFont = .bold, fontSize: CGFloat = 17.0, height: CGFloat = 48.0, cornerRadius: CGFloat = 24.0, isShimmering: Bool = false) { self.theme = theme self.glass = glass + self.glassInset = glassInset self.font = font self.fontSize = fontSize self.buttonHeight = height diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageActionButtonsNode/Sources/ChatMessageActionButtonsNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageActionButtonsNode/Sources/ChatMessageActionButtonsNode.swift index 4ce3474be7..80adb8f267 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageActionButtonsNode/Sources/ChatMessageActionButtonsNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageActionButtonsNode/Sources/ChatMessageActionButtonsNode.swift @@ -387,7 +387,7 @@ private final class ChatMessageActionButtonNode: ASDisplayNode { if let backgroundContent = node.backgroundContent { //node.backgroundBlurNode.isHidden = true node.backgroundBlurView?.view.isHidden = true - backgroundContent.frame = CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0)) + animation.animator.updateFrame(layer: backgroundContent.layer, frame: CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0)), completion: nil) node.backgroundColorNode?.frame = backgroundContent.bounds @@ -424,9 +424,13 @@ private final class ChatMessageActionButtonNode: ASDisplayNode { if currentMaskPath != effectiveMaskPath { if let effectiveMaskPath = effectiveMaskPath { - let shapeLayer = CAShapeLayer() - shapeLayer.path = effectiveMaskPath - node.layer.mask = shapeLayer + if let shapeLayer = node.layer.mask as? SimpleShapeLayer { + animation.animator.updateShapeLayerPath(layer: shapeLayer, path: effectiveMaskPath, completion: nil) + } else { + let shapeLayer = SimpleShapeLayer() + shapeLayer.path = effectiveMaskPath + node.layer.mask = shapeLayer + } } else { node.layer.mask = nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index 1661246cc6..045df51160 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -625,7 +625,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg self.menuButtonIconNode.customColor = presentationInterfaceState.theme.chat.inputPanel.actionControlForegroundColor self.menuButtonTextNode = ImmediateTextNode() - self.startButton = SolidRoundedButtonNode(title: presentationInterfaceState.strings.Bot_Start, theme: SolidRoundedButtonTheme(theme: presentationInterfaceState.theme), height: 50.0, cornerRadius: 11.0, isShimmering: true) + self.startButton = SolidRoundedButtonNode(title: presentationInterfaceState.strings.Bot_Start, theme: SolidRoundedButtonTheme(theme: presentationInterfaceState.theme), glass: true, glassInset: true, height: 50.0, cornerRadius: 50.0 * 0.5, isShimmering: true) self.startButton.progressType = .embedded self.startButton.isHidden = true diff --git a/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift b/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift index 4891167b25..84423c2c11 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift @@ -233,10 +233,22 @@ func floatingTopicsPanelForChatPresentationInterfaceState(_ chatPresentationInte guard let peerId = chatPresentationInterfaceState.chatLocation.peerId else { return nil } - if chatPresentationInterfaceState.subject?.isService ?? false { return nil } + if peerId.namespace == Namespaces.Peer.CloudUser { + guard let chatHistoryState = chatPresentationInterfaceState.chatHistoryState else { + return nil + } + switch chatHistoryState { + case .loading: + return nil + case let .loaded(isEmpty, _): + if isEmpty { + return nil + } + } + } if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.manageDirect), chatPresentationInterfaceState.search == nil { let topicListDisplayModeOnTheSide = chatPresentationInterfaceState.persistentData.topicListPanelLocation