Various improvements

This commit is contained in:
Ilya Laktyushin
2025-11-13 07:18:15 +04:00
parent 29b24d9d57
commit 9527b2d8be
21 changed files with 410 additions and 225 deletions

View File

@@ -9,19 +9,18 @@ import ChatPresentationInterfaceState
import ComponentFlow
import AccountContext
import AnimatedCountLabelNode
import GlassBackgroundComponent
final class AttachmentTextInputActionButtonsNode: ASDisplayNode, ChatSendMessageActionSheetControllerSourceSendButtonNode {
private let strings: PresentationStrings
private let glass: Bool
let sendContainerNode: ASDisplayNode
let backgroundView: GlassBackgroundView?
let backgroundNode: ASDisplayNode?
let backgroundNode: ASDisplayNode
let sendButton: HighlightTrackingButtonNode
var sendButtonHasApplyIcon = false
var animatingSendButton = false
let textNode: ImmediateAnimatedCountLabelNode
let iconNode: ASImageNode
private var theme: PresentationTheme
@@ -46,21 +45,18 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode, ChatSendMessage
self.sendContainerNode = ASDisplayNode()
self.sendContainerNode.layer.allowsGroupOpacity = true
if glass {
self.backgroundView = GlassBackgroundView()
self.backgroundNode = nil
} else {
self.backgroundNode = ASDisplayNode()
self.backgroundNode?.backgroundColor = theme.chat.inputPanel.actionControlFillColor
self.backgroundNode?.clipsToBounds = true
self.backgroundView = nil
}
self.backgroundNode = ASDisplayNode()
self.backgroundNode.backgroundColor = self.theme.chat.inputPanel.actionControlFillColor
self.backgroundNode.clipsToBounds = true
self.sendButton = HighlightTrackingButtonNode(pointerStyle: nil)
self.textNode = ImmediateAnimatedCountLabelNode()
self.textNode.isUserInteractionEnabled = false
self.iconNode = ASImageNode()
self.iconNode.displaysAsynchronously = false
super.init()
self.isAccessibilityElement = true
@@ -89,13 +85,10 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode, ChatSendMessage
}
self.addSubnode(self.sendContainerNode)
if let backgroundView = self.backgroundView {
self.sendContainerNode.view.addSubview(backgroundView)
} else if let backgroundNode = self.backgroundNode {
self.sendContainerNode.addSubnode(backgroundNode)
}
self.sendContainerNode.addSubnode(self.backgroundNode)
self.sendContainerNode.addSubnode(self.sendButton)
self.sendContainerNode.addSubnode(self.textNode)
self.backgroundNode.addSubnode(self.iconNode)
}
override func didLoad() {
@@ -114,13 +107,15 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode, ChatSendMessage
}
}
if let backgroundNode = self.backgroundNode {
self.sendButtonPointerInteraction = PointerInteraction(view: self.sendButton.view, customInteractionView: backgroundNode.view, style: .lift)
}
self.sendButtonPointerInteraction = PointerInteraction(view: self.sendButton.view, customInteractionView: self.backgroundNode.view, style: .lift)
}
func setImage(_ image: UIImage?) {
self.iconNode.image = image
}
func updateTheme(theme: PresentationTheme, wallpaper: TelegramWallpaper) {
self.backgroundNode?.backgroundColor = theme.chat.inputPanel.actionControlFillColor
self.backgroundNode.backgroundColor = theme.chat.inputPanel.actionControlFillColor
}
private var absoluteRect: (CGRect, CGSize)?
@@ -128,9 +123,15 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode, ChatSendMessage
self.absoluteRect = (rect, containerSize)
}
public func animateIn(transition: ContainedViewLayoutTransition) {
transition.animatePositionAdditive(layer: self.iconNode.layer, offset: CGPoint(x: -22.0, y: 18.0))
}
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition, minimized: Bool, text: String, interfaceState: ChatPresentationInterfaceState) -> CGSize {
self.validLayout = size
let height: CGFloat = self.glass ? 34.0 : 33.0
let width: CGFloat
var titleOffset: CGFloat = 0.0
@@ -158,7 +159,7 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode, ChatSendMessage
let textSize = self.textNode.updateLayout(size: CGSize(width: 100.0, height: 100.0), animated: transition.isAnimated)
if minimized {
width = 53.0
width = self.glass ? 51.0 : 53.0
} else {
width = textSize.width + buttonInset * 2.0
}
@@ -172,15 +173,12 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode, ChatSendMessage
transition.updateFrame(layer: self.sendButton.layer, frame: CGRect(origin: CGPoint(), size: buttonSize))
transition.updateFrame(node: self.sendContainerNode, frame: CGRect(origin: CGPoint(), size: buttonSize))
if let backgroundView = self.backgroundView {
let backgroundSize = CGSize(width: width - 13.0, height: 40.0)
let backgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - backgroundSize.width) / 2.0), y: floorToScreenPixels((size.height - backgroundSize.height) / 2.0)), size: backgroundSize)
transition.updateFrame(view: backgroundView, frame: backgroundFrame)
backgroundView.update(size: backgroundSize, cornerRadius: backgroundSize.height * 0.5, isDark: false, tintColor: .init(kind: .custom, color: self.theme.chat.inputPanel.actionControlFillColor), transition: ComponentTransition(transition))
} else if let backgroundNode {
let backgroundSize = CGSize(width: width - 11.0, height: 33.0)
transition.updateFrame(node: backgroundNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((width - backgroundSize.width) / 2.0), y: floorToScreenPixels((size.height - backgroundSize.height) / 2.0)), size: backgroundSize))
backgroundNode.cornerRadius = backgroundSize.height / 2.0
let backgroundSize = CGSize(width: width - 11.0, height: height)
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((width - backgroundSize.width) / 2.0), y: floorToScreenPixels((size.height - backgroundSize.height) / 2.0)), size: backgroundSize))
self.backgroundNode.cornerRadius = backgroundSize.height / 2.0
if let iconSize = self.iconNode.image?.size {
transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - iconSize.width) / 2.0), y: floorToScreenPixels((backgroundSize.height - iconSize.height) / 2.0)), size: iconSize))
}
return buttonSize

View File

@@ -329,6 +329,10 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
public var interfaceInteraction: ChatPanelInterfaceInteraction?
public func animateIn(transition: ContainedViewLayoutTransition) {
self.actionButtons.animateIn(transition: transition)
}
public func updateSendButtonEnabled(_ enabled: Bool, animated: Bool) {
self.actionButtons.isUserInteractionEnabled = enabled
@@ -652,7 +656,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
private func calculateTextFieldMetrics(width: CGFloat, maxHeight: CGFloat, metrics: LayoutMetrics) -> (accessoryButtonsWidth: CGFloat, textFieldHeight: CGFloat) {
var textFieldInsets = self.textFieldInsets(metrics: metrics)
if self.actionButtons.frame.width > 44.0 {
textFieldInsets.right = self.actionButtons.frame.width
textFieldInsets.right = self.actionButtons.frame.width - 6.0
}
let fieldMaxHeight = textFieldMaxHeight(maxHeight, metrics: metrics)
@@ -846,9 +850,9 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
}
self.actionButtons.sendButtonHasApplyIcon = sendButtonHasApplyIcon
if self.actionButtons.sendButtonHasApplyIcon {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelApplyIconImage(interfaceState.theme), for: [])
self.actionButtons.setImage(PresentationResourcesChat.chatInputPanelApplyIconImage(interfaceState.theme))
} else {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelSendIconImage(interfaceState.theme), for: [])
self.actionButtons.setImage(PresentationResourcesChat.chatInputPanelSendIconImage(interfaceState.theme))
}
}
}
@@ -1013,17 +1017,17 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
text = "⭐️\(sendPaidMessageStars.value * Int64(count))"
isPaidMessage = true
} else {
isMinimized = !self.isAttachment || inputHasText
isMinimized = !self.isAttachment || inputHasText || self.glass
text = presentationInterfaceState.strings.MediaPicker_Send
}
actionButtonsSize = self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), transition: transition, minimized: isMinimized && !self.glass, text: text, interfaceState: presentationInterfaceState)
actionButtonsSize = self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), transition: transition, minimized: isMinimized, text: text, interfaceState: presentationInterfaceState)
textBackgroundInset = actionButtonsSize.width - 44.0
} else {
actionButtonsSize = CGSize(width: 44.0, height: minimalHeight)
}
let actionButtonsOriginOffset: CGFloat = self.glass ? -3.0 : 0.0
let actionButtonsFrame = CGRect(origin: CGPoint(x: width - rightInset - actionButtonsSize.width + 1.0 - UIScreenPixel + composeButtonsOffset + actionButtonsOriginOffset, y: panelHeight - minimalHeight), size: actionButtonsSize)
let actionButtonsOriginOffset: CGFloat = self.glass ? -6.0 : 0.0
let actionButtonsFrame = CGRect(origin: CGPoint(x: width - rightInset - actionButtonsSize.width + 1.0 - UIScreenPixel + composeButtonsOffset + actionButtonsOriginOffset, y: panelHeight - minimalHeight - 1.0), size: actionButtonsSize)
transition.updateFrame(node: self.actionButtons, frame: actionButtonsFrame)
let textInputHeight = panelHeight - textFieldInsets.top - textFieldInsets.bottom
@@ -1065,7 +1069,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
)
var inputNodeOffset: CGPoint = CGPoint(x: -1.0, y: -1.0)
if self.glass {
inputNodeOffset = CGPoint(x: -4.0, y: -4.0)
inputNodeOffset = CGPoint(x: -6.0, y: -4.0)
}
transition.updateFrame(view: self.inputModeView, frame: CGRect(origin: CGPoint(x: textInputBackgroundFrame.maxX - inputNodeSize.width + inputNodeOffset.x, y: textInputBackgroundFrame.maxY - inputNodeSize.height + inputNodeOffset.y), size: inputNodeSize))
}
@@ -1503,12 +1507,12 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
if sendButtonHasApplyIcon != self.actionButtons.sendButtonHasApplyIcon {
self.actionButtons.sendButtonHasApplyIcon = sendButtonHasApplyIcon
if self.actionButtons.sendButtonHasApplyIcon {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelApplyIconImage(interfaceState.theme), for: [])
self.actionButtons.setImage(PresentationResourcesChat.chatInputPanelApplyIconImage(interfaceState.theme))
} else {
if case .scheduledMessages = interfaceState.subject {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelScheduleButtonImage(interfaceState.theme), for: [])
self.actionButtons.setImage(PresentationResourcesChat.chatInputPanelScheduleButtonImage(interfaceState.theme))
} else {
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelSendIconImage(interfaceState.theme), for: [])
self.actionButtons.setImage(PresentationResourcesChat.chatInputPanelSendIconImage(interfaceState.theme))
}
}
}
@@ -1956,7 +1960,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
public func frameForInputActionButton() -> CGRect? {
if !self.actionButtons.alpha.isZero {
return self.actionButtons.frame.insetBy(dx: 0.0, dy: 6.0).offsetBy(dx: 4.0, dy: 0.0)
return self.actionButtons.frame.insetBy(dx: 0.0, dy: self.glass ? 0.0 : 6.0).offsetBy(dx: 4.0, dy: 0.0)
}
return nil
}