mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Attachment menu improvements
This commit is contained in:
@@ -15,8 +15,8 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode {
|
||||
let sendButton: HighlightTrackingButtonNode
|
||||
var sendButtonHasApplyIcon = false
|
||||
var animatingSendButton = false
|
||||
let expandMediaInputButton: HighlightableButtonNode
|
||||
|
||||
let textNode: ImmediateTextNode
|
||||
|
||||
var sendButtonLongPressed: ((ASDisplayNode, ContextGesture) -> Void)?
|
||||
|
||||
private var gestureRecognizer: ContextGesture?
|
||||
@@ -40,8 +40,10 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode {
|
||||
self.backgroundNode.backgroundColor = theme.chat.inputPanel.actionControlFillColor
|
||||
self.backgroundNode.clipsToBounds = true
|
||||
self.sendButton = HighlightTrackingButtonNode(pointerStyle: .lift)
|
||||
|
||||
self.expandMediaInputButton = HighlightableButtonNode(pointerStyle: .default)
|
||||
|
||||
self.textNode = ImmediateTextNode()
|
||||
self.textNode.attributedText = NSAttributedString(string: self.strings.MediaPicker_Send, font: Font.semibold(17.0), textColor: theme.chat.inputPanel.actionControlForegroundColor)
|
||||
self.textNode.isUserInteractionEnabled = false
|
||||
|
||||
super.init()
|
||||
|
||||
@@ -71,7 +73,7 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode {
|
||||
self.addSubnode(self.sendContainerNode)
|
||||
self.sendContainerNode.addSubnode(self.backgroundNode)
|
||||
self.sendContainerNode.addSubnode(self.sendButton)
|
||||
self.addSubnode(self.expandMediaInputButton)
|
||||
self.sendContainerNode.addSubnode(self.textNode)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@@ -91,9 +93,9 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
func updateTheme(theme: PresentationTheme, wallpaper: TelegramWallpaper) {
|
||||
self.expandMediaInputButton.setImage(PresentationResourcesChat.chatInputPanelExpandButtonImage(theme), for: [])
|
||||
|
||||
self.backgroundNode.backgroundColor = theme.chat.inputPanel.actionControlFillColor
|
||||
|
||||
self.textNode.attributedText = NSAttributedString(string: self.strings.MediaPicker_Send, font: Font.semibold(17.0), textColor: theme.chat.inputPanel.actionControlForegroundColor)
|
||||
}
|
||||
|
||||
private var absoluteRect: (CGRect, CGSize)?
|
||||
@@ -101,22 +103,31 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode {
|
||||
self.absoluteRect = (rect, containerSize)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) {
|
||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition, minimized: Bool, interfaceState: ChatPresentationInterfaceState) -> CGSize {
|
||||
self.validLayout = size
|
||||
|
||||
transition.updateFrame(layer: self.sendButton.layer, frame: CGRect(origin: CGPoint(), size: size))
|
||||
transition.updateFrame(node: self.sendContainerNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
let backgroundSize = CGSize(width: 33.0, height: 33.0)
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - backgroundSize.width) / 2.0), y: floorToScreenPixels((size.height - backgroundSize.height) / 2.0)), size: backgroundSize))
|
||||
self.backgroundNode.cornerRadius = backgroundSize.width / 2.0
|
||||
|
||||
transition.updateFrame(node: self.expandMediaInputButton, frame: CGRect(origin: CGPoint(), size: size))
|
||||
var expanded = false
|
||||
if case let .media(_, maybeExpanded, _) = interfaceState.inputMode, maybeExpanded != nil {
|
||||
expanded = true
|
||||
let width: CGFloat
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: 100.0, height: size.height))
|
||||
if minimized {
|
||||
width = 44.0
|
||||
} else {
|
||||
width = textSize.width + 36.0
|
||||
}
|
||||
transition.updateSublayerTransformScale(node: self.expandMediaInputButton, scale: CGPoint(x: 1.0, y: expanded ? 1.0 : -1.0))
|
||||
|
||||
let buttonSize = CGSize(width: width, height: size.height)
|
||||
|
||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((width - textSize.width) / 2.0), y: floorToScreenPixels((buttonSize.height - textSize.height) / 2.0)), size: textSize))
|
||||
transition.updateAlpha(node: self.textNode, alpha: minimized ? 0.0 : 1.0)
|
||||
transition.updateAlpha(node: self.sendButton.imageNode, alpha: minimized ? 1.0 : 0.0)
|
||||
|
||||
transition.updateFrame(layer: self.sendButton.layer, frame: CGRect(origin: CGPoint(), size: buttonSize))
|
||||
transition.updateFrame(node: self.sendContainerNode, frame: CGRect(origin: CGPoint(), size: buttonSize))
|
||||
|
||||
let backgroundSize = CGSize(width: width - 11.0, height: 33.0)
|
||||
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
|
||||
|
||||
return buttonSize
|
||||
}
|
||||
|
||||
func updateAccessibility() {
|
||||
|
||||
@@ -287,7 +287,6 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
|
||||
self.actionButtons.sendButton.addTarget(self, action: #selector(self.sendButtonPressed), forControlEvents: .touchUpInside)
|
||||
self.actionButtons.sendButton.alpha = 1.0
|
||||
self.actionButtons.expandMediaInputButton.alpha = 0.0
|
||||
self.actionButtons.updateAccessibility()
|
||||
|
||||
self.addSubnode(self.textInputContainer)
|
||||
@@ -590,9 +589,9 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
}
|
||||
self.actionButtons.sendButtonHasApplyIcon = sendButtonHasApplyIcon
|
||||
if self.actionButtons.sendButtonHasApplyIcon {
|
||||
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelApplyButtonImage(interfaceState.theme), for: [])
|
||||
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelApplyIconImage(interfaceState.theme), for: [])
|
||||
} else {
|
||||
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(interfaceState.theme), for: [])
|
||||
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelSendIconImage(interfaceState.theme), for: [])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -608,9 +607,6 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: baseWidth, maxHeight: maxHeight, metrics: metrics)
|
||||
var panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics)
|
||||
|
||||
var composeButtonsOffset: CGFloat = 0.0
|
||||
let textInputBackgroundWidthOffset: CGFloat = 0.0
|
||||
|
||||
self.updateCounterTextNode(transition: transition)
|
||||
|
||||
var inputHasText = false
|
||||
@@ -629,7 +625,15 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
}
|
||||
|
||||
if self.isCaption {
|
||||
if !self.isFocused {
|
||||
if self.isFocused {
|
||||
self.oneLineNode.alpha = 0.0
|
||||
self.oneLineDustNode?.alpha = 0.0
|
||||
self.textInputNode?.alpha = 1.0
|
||||
|
||||
transition.updateAlpha(node: self.actionButtons, alpha: 1.0)
|
||||
transition.updateTransformScale(node: self.actionButtons, scale: 1.0)
|
||||
transition.updateAlpha(node: self.textInputBackgroundImageNode, alpha: 1.0)
|
||||
} else {
|
||||
panelHeight = minimalHeight
|
||||
|
||||
transition.updateAlpha(node: self.oneLineNode, alpha: inputHasText ? 1.0 : 0.0)
|
||||
@@ -639,12 +643,12 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
if let textInputNode = self.textInputNode {
|
||||
transition.updateAlpha(node: textInputNode, alpha: inputHasText ? 0.0 : 1.0)
|
||||
}
|
||||
} else {
|
||||
self.oneLineNode.alpha = 0.0
|
||||
self.oneLineDustNode?.alpha = 0.0
|
||||
self.textInputNode?.alpha = 1.0
|
||||
|
||||
transition.updateAlpha(node: self.actionButtons, alpha: 0.0)
|
||||
transition.updateTransformScale(node: self.actionButtons, scale: 0.001)
|
||||
transition.updateAlpha(node: self.textInputBackgroundImageNode, alpha: inputHasText ? 1.0 : 0.0)
|
||||
}
|
||||
|
||||
|
||||
let oneLineSize = self.oneLineNode.updateLayout(CGSize(width: baseWidth - textFieldInsets.left - textFieldInsets.right, height: CGFloat.greatestFiniteMagnitude))
|
||||
let oneLineFrame = CGRect(origin: CGPoint(x: leftInset + textFieldInsets.left + self.textInputViewInternalInsets.left, y: textFieldInsets.top + self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel), size: oneLineSize)
|
||||
self.oneLineNode.frame = oneLineFrame
|
||||
@@ -652,34 +656,9 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
self.updateOneLineSpoiler()
|
||||
}
|
||||
self.textPlaceholderNode.isHidden = inputHasText
|
||||
|
||||
if self.isCaption {
|
||||
if self.isFocused {
|
||||
transition.updateAlpha(node: self.actionButtons, alpha: 1.0)
|
||||
transition.updateTransformScale(node: self.actionButtons, scale: 1.0)
|
||||
composeButtonsOffset = 0.0
|
||||
|
||||
transition.updateAlpha(node: self.textInputBackgroundImageNode, alpha: 1.0)
|
||||
} else {
|
||||
transition.updateAlpha(node: self.actionButtons, alpha: 0.0)
|
||||
transition.updateTransformScale(node: self.actionButtons, scale: 0.001)
|
||||
composeButtonsOffset = 36.0
|
||||
|
||||
transition.updateAlpha(node: self.textInputBackgroundImageNode, alpha: inputHasText ? 1.0 : 0.0)
|
||||
}
|
||||
}
|
||||
|
||||
let actionButtonsFrame = CGRect(origin: CGPoint(x: width - rightInset - 43.0 - UIScreenPixel + composeButtonsOffset, y: panelHeight - minimalHeight), size: CGSize(width: 44.0, height: minimalHeight))
|
||||
transition.updateFrame(node: self.actionButtons, frame: actionButtonsFrame)
|
||||
|
||||
if let presentationInterfaceState = self.presentationInterfaceState {
|
||||
self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), transition: transition, interfaceState: presentationInterfaceState)
|
||||
}
|
||||
|
||||
let textInputFrame = CGRect(x: leftInset + textFieldInsets.left, y: textFieldInsets.top, width: baseWidth - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom)
|
||||
let textInputBackgroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: textInputFrame.size.width + composeButtonsOffset, height: textInputFrame.size.height))
|
||||
|
||||
let textInputFrame = CGRect(x: leftInset + textFieldInsets.left, y: textFieldInsets.top, width: baseWidth - textFieldInsets.left - textFieldInsets.right, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom)
|
||||
transition.updateFrame(node: self.textInputContainer, frame: textInputFrame)
|
||||
transition.updateFrame(node: self.textInputContainerBackgroundNode, frame: textInputBackgroundFrame)
|
||||
|
||||
if let textInputNode = self.textInputNode {
|
||||
let textFieldFrame = CGRect(origin: CGPoint(x: self.textInputViewInternalInsets.left, y: self.textInputViewInternalInsets.top), size: CGSize(width: textInputFrame.size.width - (self.textInputViewInternalInsets.left + self.textInputViewInternalInsets.right), height: textInputFrame.size.height - self.textInputViewInternalInsets.top - textInputViewInternalInsets.bottom))
|
||||
@@ -690,20 +669,72 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
}
|
||||
}
|
||||
|
||||
self.updateFieldAndButtonsLayout(inputHasText: inputHasText, panelHeight: panelHeight, transition: transition)
|
||||
|
||||
self.actionButtons.updateAccessibility()
|
||||
|
||||
return panelHeight
|
||||
}
|
||||
|
||||
private func updateFieldAndButtonsLayout(inputHasText: Bool, panelHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
guard let (width, leftInset, rightInset, additionalSideInsets, _, metrics, _) = self.validLayout else {
|
||||
return
|
||||
}
|
||||
var textFieldMinHeight: CGFloat = 33.0
|
||||
if let presentationInterfaceState = self.presentationInterfaceState {
|
||||
textFieldMinHeight = calclulateTextFieldMinHeight(presentationInterfaceState, metrics: metrics)
|
||||
}
|
||||
let minimalHeight: CGFloat = 14.0 + textFieldMinHeight
|
||||
|
||||
var panelHeight = panelHeight
|
||||
var composeButtonsOffset: CGFloat = 0.0
|
||||
if self.isCaption {
|
||||
if self.isFocused {
|
||||
composeButtonsOffset = 0.0
|
||||
} else {
|
||||
composeButtonsOffset = 36.0
|
||||
panelHeight = minimalHeight
|
||||
}
|
||||
}
|
||||
|
||||
let baseWidth = width - leftInset - rightInset
|
||||
let textInputFrame = self.textInputContainer.frame
|
||||
|
||||
var textBackgroundInset: CGFloat = 0.0
|
||||
let actionButtonsSize: CGSize
|
||||
if let presentationInterfaceState = self.presentationInterfaceState {
|
||||
actionButtonsSize = self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), transition: transition, minimized: !self.isAttachment || inputHasText, interfaceState: presentationInterfaceState)
|
||||
textBackgroundInset = 44.0 - actionButtonsSize.width
|
||||
} else {
|
||||
actionButtonsSize = CGSize(width: 44.0, height: minimalHeight)
|
||||
}
|
||||
|
||||
var textFieldInsets = self.textFieldInsets(metrics: metrics)
|
||||
if additionalSideInsets.right > 0.0 {
|
||||
textFieldInsets.right += additionalSideInsets.right / 3.0
|
||||
}
|
||||
|
||||
let actionButtonsFrame = CGRect(origin: CGPoint(x: width - rightInset - actionButtonsSize.width + 1.0 - UIScreenPixel + composeButtonsOffset, y: panelHeight - minimalHeight), size: actionButtonsSize)
|
||||
transition.updateFrame(node: self.actionButtons, frame: actionButtonsFrame)
|
||||
|
||||
let textInputBackgroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: textInputFrame.size.width + composeButtonsOffset + textBackgroundInset, height: textInputFrame.size.height))
|
||||
transition.updateFrame(node: self.textInputContainerBackgroundNode, frame: textInputBackgroundFrame)
|
||||
|
||||
transition.updateFrame(layer: self.textInputBackgroundNode.layer, frame: CGRect(x: leftInset + textFieldInsets.left, y: textFieldInsets.top, width: baseWidth - textFieldInsets.left - textFieldInsets.right + composeButtonsOffset + textBackgroundInset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom))
|
||||
transition.updateFrame(layer: self.textInputBackgroundImageNode.layer, frame: CGRect(x: 0.0, y: 0.0, width: baseWidth - textFieldInsets.left - textFieldInsets.right + composeButtonsOffset + textBackgroundInset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom))
|
||||
|
||||
var textInputViewRealInsets = UIEdgeInsets()
|
||||
if let presentationInterfaceState = self.presentationInterfaceState {
|
||||
textInputViewRealInsets = calculateTextFieldRealInsets(presentationInterfaceState)
|
||||
}
|
||||
|
||||
let placeholderFrame: CGRect
|
||||
if self.isCaption && !self.isFocused {
|
||||
placeholderFrame = CGRect(origin: CGPoint(x: textInputFrame.minX + floorToScreenPixels((textInputBackgroundFrame.width - self.textPlaceholderNode.frame.width) / 2.0), y: textFieldInsets.top + self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel), size: self.textPlaceholderNode.frame.size)
|
||||
} else {
|
||||
placeholderFrame = CGRect(origin: CGPoint(x: leftInset + textFieldInsets.left + self.textInputViewInternalInsets.left, y: textFieldInsets.top + self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel), size: self.textPlaceholderNode.frame.size)
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.textPlaceholderNode, frame: placeholderFrame)
|
||||
transition.updateFrame(layer: self.textInputBackgroundNode.layer, frame: CGRect(x: leftInset + textFieldInsets.left, y: textFieldInsets.top, width: baseWidth - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset + composeButtonsOffset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom))
|
||||
transition.updateFrame(layer: self.textInputBackgroundImageNode.layer, frame: CGRect(x: 0.0, y: 0.0, width: baseWidth - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset + composeButtonsOffset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom))
|
||||
|
||||
self.actionButtons.updateAccessibility()
|
||||
|
||||
return panelHeight
|
||||
}
|
||||
|
||||
private var skipUpdate = false
|
||||
@@ -952,7 +983,10 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
self.oneLineNode.attributedText = nil
|
||||
}
|
||||
|
||||
self.updateTextHeight(animated: animated)
|
||||
let panelHeight = self.updateTextHeight(animated: animated)
|
||||
if self.isAttachment, let panelHeight = panelHeight {
|
||||
self.updateFieldAndButtonsLayout(inputHasText: inputHasText, panelHeight: panelHeight, transition: .animated(duration: 0.2, curve: .easeInOut))
|
||||
}
|
||||
}
|
||||
|
||||
private func updateOneLineSpoiler() {
|
||||
@@ -977,7 +1011,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
}
|
||||
}
|
||||
|
||||
private func updateTextHeight(animated: Bool) {
|
||||
private func updateTextHeight(animated: Bool) -> CGFloat? {
|
||||
if let (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, _) = self.validLayout {
|
||||
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset - additionalSideInsets.right, maxHeight: maxHeight, metrics: metrics)
|
||||
let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics)
|
||||
@@ -985,6 +1019,9 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
self.updateHeight(animated)
|
||||
self.heightUpdated?(animated)
|
||||
}
|
||||
return panelHeight
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1002,12 +1039,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.chatInputPanelApplyButtonImage(interfaceState.theme), for: [])
|
||||
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelApplyIconImage(interfaceState.theme), for: [])
|
||||
} else {
|
||||
if case .scheduledMessages = interfaceState.subject {
|
||||
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelScheduleButtonImage(interfaceState.theme), for: [])
|
||||
} else {
|
||||
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(interfaceState.theme), for: [])
|
||||
self.actionButtons.sendButton.setImage(PresentationResourcesChat.chatInputPanelSendIconImage(interfaceState.theme), for: [])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user