This commit is contained in:
Isaac 2025-09-28 15:01:52 +08:00
parent f5ca87fb23
commit 5728de8df8
3 changed files with 157 additions and 73 deletions

View File

@ -66,7 +66,10 @@ public let chatTextInputMinFontSize: CGFloat = 5.0
private let minInputFontSize = chatTextInputMinFontSize
private func calclulateTextFieldMinHeight(_ presentationInterfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
var baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
if "".isEmpty {
baseFontSize = 17.0
}
var result: CGFloat
if baseFontSize.isEqual(to: 26.0) {
result = 42.0
@ -82,15 +85,14 @@ private func calclulateTextFieldMinHeight(_ presentationInterfaceState: ChatPres
result = 31.0
}
if case .regular = metrics.widthClass {
result = max(33.0, result)
}
return result
}
private func calculateTextFieldRealInsets(presentationInterfaceState: ChatPresentationInterfaceState, accessoryButtonsWidth: CGFloat) -> UIEdgeInsets {
let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
var baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
if "".isEmpty {
baseFontSize = 17.0
}
let top: CGFloat
let bottom: CGFloat
if baseFontSize.isEqual(to: 14.0) {
@ -452,6 +454,9 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
}
if "".isEmpty {
baseFontSize = 17.0
}
textInputNode.attributedText = NSAttributedString(string: value, font: Font.regular(baseFontSize), textColor: textColor)
self.chatInputTextNodeDidUpdateText()
}
@ -1038,7 +1043,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
var accessoryButtonsWidth: CGFloat = 0.0
var firstButton = true
for (_, button) in self.accessoryItemButtons {
for (item, button) in self.accessoryItemButtons {
if firstButton {
firstButton = false
accessoryButtonsWidth += self.accessoryButtonInset
@ -1046,6 +1051,12 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
accessoryButtonsWidth += self.accessoryButtonSpacing
}
accessoryButtonsWidth += button.buttonWidth
switch item {
case .input:
accessoryButtonsWidth -= 2.0
default:
break
}
}
var textFieldMinHeight: CGFloat = 35.0
@ -1081,11 +1092,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
}
private func textFieldInsets(metrics: LayoutMetrics) -> UIEdgeInsets {
var insets = UIEdgeInsets(top: 0.0, left: 54.0, bottom: 0.0, right: 54.0)
if case .regular = metrics.widthClass, case .regular = metrics.heightClass {
insets.top += 1.0
insets.bottom += 1.0
}
let insets = UIEdgeInsets(top: 0.0, left: 54.0, bottom: 0.0, right: 54.0)
return insets
}
@ -1097,10 +1104,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
override public func minimalHeight(interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
let textFieldMinHeight = calclulateTextFieldMinHeight(interfaceState, metrics: metrics)
var minimalHeight: CGFloat = 14.0 + textFieldMinHeight
if case .regular = metrics.widthClass, case .regular = metrics.heightClass {
minimalHeight += 2.0
}
let minimalHeight: CGFloat = 14.0 + textFieldMinHeight
return minimalHeight
}
@ -1563,7 +1567,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
if self.theme == nil || !self.theme!.chat.inputPanel.inputTextColor.isEqual(interfaceState.theme.chat.inputPanel.inputTextColor) {
let textColor = interfaceState.theme.chat.inputPanel.inputTextColor
let baseFontSize = max(minInputFontSize, interfaceState.fontSize.baseDisplaySize)
var baseFontSize = max(minInputFontSize, interfaceState.fontSize.baseDisplaySize)
if "".isEmpty {
baseFontSize = 17.0
}
if let textInputNode = self.textInputNode {
if let text = textInputNode.attributedText {
@ -2505,6 +2512,12 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
transition.updateAlpha(layer: button.layer, alpha: audioRecordingItemsAlpha)
nextButtonTopRight.x -= buttonSize.width
nextButtonTopRight.x -= accessoryButtonSpacing
switch item.key {
case .input:
nextButtonTopRight.x += 2.0
default:
break
}
}
let textInputBackgroundFrame = CGRect(x: hideOffset.x + leftInset + textFieldInsets.left, y: hideOffset.y + textFieldInsets.top + textFieldTopContentOffset, width: baseWidth - textFieldInsets.left - textFieldInsets.right, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom + self.textInputViewInternalInsets.top + self.textInputViewInternalInsets.bottom)
@ -2518,7 +2531,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
if (updatedPlaceholder != nil && self.currentPlaceholder != updatedPlaceholder) || themeUpdated {
let currentPlaceholder = updatedPlaceholder ?? self.currentPlaceholder ?? ""
self.currentPlaceholder = currentPlaceholder
let baseFontSize = max(minInputFontSize, interfaceState.fontSize.baseDisplaySize)
var baseFontSize = max(minInputFontSize, interfaceState.fontSize.baseDisplaySize)
if "".isEmpty {
baseFontSize = 17.0
}
let attributedPlaceholder = NSMutableAttributedString(string: currentPlaceholder, font: Font.regular(baseFontSize), textColor: placeholderColor.withAlphaComponent(1.0))
if placeholderHasStar, let range = attributedPlaceholder.string.range(of: "#") {
@ -2923,7 +2939,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
var rects: [CGRect] = []
var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute, CGFloat)] = []
let fontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
var fontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
if "".isEmpty {
fontSize = 17.0
}
if let attributedText = textInputNode.attributedText {
let beginning = textInputNode.textView.beginningOfDocument
@ -3949,7 +3968,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
self.inputMenu.hide()
}
let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
var baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
if "".isEmpty {
baseFontSize = 17.0
}
refreshChatTextInputTypingAttributes(textInputNode.textView, theme: presentationInterfaceState.theme, baseFontSize: baseFontSize)
self.updateSpoilersRevealed()
@ -4338,6 +4360,9 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
accentTextColor = presentationInterfaceState.theme.chat.inputPanel.panelControlAccentColor
baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
if "".isEmpty {
baseFontSize = 17.0
}
}
let cleanReplacementString = textAttributedStringForStateText(context: context, stateText: NSAttributedString(string: cleanText), fontSize: baseFontSize, textColor: textColor, accentTextColor: accentTextColor, writingDirection: nil, spoilersRevealed: self.spoilersRevealed, availableEmojis: (self.context?.animatedEmojiStickersValue.keys).flatMap(Set.init) ?? Set(), emojiViewProvider: self.emojiViewProvider, makeCollapsedQuoteAttachment: { text, attributes in
return ChatInputTextCollapsedQuoteAttachmentImpl(text: text, attributes: attributes)

View File

@ -577,7 +577,9 @@ public extension GlassBackgroundView {
size.width += inset * 2.0
size.height += inset * 2.0
return generateImage(size, rotatedContext: { size, context in
return UIGraphicsImageRenderer(size: size).image { ctx in
let context = ctx.cgContext
context.clear(CGRect(origin: CGPoint(), size: size))
func pathApplyingSpread(_ path: CGPath, spread: CGFloat) -> CGPath {
@ -606,8 +608,14 @@ public extension GlassBackgroundView {
}
return result
}
let maskImage = UIGraphicsImageRenderer(size: size).image { ctx in
let context = ctx.cgContext
context.setFillColor(UIColor.black.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(x: inset, y: inset), size: innerSize))
}
let addShadow: (Bool, CGPoint, CGFloat, CGFloat, UIColor, Bool) -> Void = { isOuter, position, blur, spread, shadowColor, isMultiply in
let addShadow: (Bool, CGPoint, CGFloat, CGFloat, UIColor, CGBlendMode) -> Void = { isOuter, position, blur, spread, shadowColor, blendMode in
var blur = blur
blur += abs(spread)
@ -641,72 +649,119 @@ public extension GlassBackgroundView {
context.fillPath()
context.setBlendMode(.normal)
} else {
if let image = generateImage(size, rotatedContext: { size, context in
let image = UIGraphicsImageRenderer(size: size).image(actions: { ctx in
let context = ctx.cgContext
context.clear(CGRect(origin: CGPoint(), size: size))
let spreadRect = CGRect(origin: CGPoint(x: inset, y: inset), size: innerSize).insetBy(dx: -0.25, dy: -0.25)
let spreadRect = CGRect(origin: CGPoint(x: inset, y: inset), size: innerSize).insetBy(dx: -spread - 1.0, dy: -spread - 1.0)
let spreadPath = UIBezierPath(
roundedRect: spreadRect,
cornerRadius: min(spreadRect.width, spreadRect.height) * 0.5
).cgPath
context.setShadow(offset: CGSize(width: position.x, height: position.y), blur: blur, color: shadowColor.cgColor)
context.setFillColor(UIColor.black.withAlphaComponent(1.0).cgColor)
context.setFillColor(UIColor.red.cgColor)
let enclosingRect = spreadRect.insetBy(dx: -10000.0, dy: -10000.0)
context.addPath(UIBezierPath(rect: enclosingRect).cgPath)
context.addPath(spreadPath)
context.fillPath(using: .evenOdd)
let cleanRect = CGRect(origin: CGPoint(x: inset, y: inset), size: innerSize)
let cleanPath = UIBezierPath(
roundedRect: cleanRect,
cornerRadius: min(cleanRect.width, cleanRect.height) * 0.5
).cgPath
context.setBlendMode(.copy)
context.setFillColor(UIColor.clear.cgColor)
context.addPath(UIBezierPath(rect: enclosingRect).cgPath)
context.addPath(cleanPath)
context.fillPath(using: .evenOdd)
context.setBlendMode(.normal)
}) {
UIGraphicsPushContext(context)
image.draw(in: CGRect(origin: .zero, size: size), blendMode: isMultiply ? .destinationOut : .normal, alpha: 1.0)
UIGraphicsPopContext()
}
maskImage.draw(at: CGPoint(), blendMode: .destinationIn, alpha: 1.0)
})
UIGraphicsPushContext(context)
image.draw(in: CGRect(origin: .zero, size: size), blendMode: blendMode, alpha: 1.0)
UIGraphicsPopContext()
}
}
if isDark {
addShadow(true, CGPoint(), 16.0, 0.0, UIColor(white: 0.0, alpha: 0.12), false)
addShadow(true, CGPoint(), 8.0, 0.0, UIColor(white: 0.0, alpha: 0.1), false)
context.setFillColor(fillColor.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset))
addShadow(false, CGPoint(x: 0.0, y: 0.0), 3.0, 0.0, UIColor(white: 1.0, alpha: 0.25), false)
addShadow(false, CGPoint(x: 2.0, y: -2.0), 1.0, 0.0, UIColor(white: 1.0, alpha: 0.125), false)
addShadow(false, CGPoint(x: -2.0, y: 2.0), 1.0, 0.0, UIColor(white: 1.0, alpha: 0.125), false)
} else {
addShadow(true, CGPoint(), 16.0, 0.0, UIColor(white: 0.0, alpha: 0.08), false)
context.setFillColor(fillColor.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset))
let highlightColor: UIColor
if fillColor.hsb.s > 0.5 {
var (h, s, v) = fillColor.hsb
s = max(0.0, min(1.0, s * 0.25))
v = max(v, 0.95)
h = max(0.0, min(1.0, h - 0.1))
highlightColor = UIColor(hue: h, saturation: s, brightness: v, alpha: fillColor.alpha)
} else {
highlightColor = UIColor(white: 1.0, alpha: min(1.0, fillColor.alpha * 1.2))
addShadow(true, CGPoint(), 16.0, 0.0, UIColor(white: 0.0, alpha: 0.08), .normal)
context.setFillColor(fillColor.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: inset, dy: inset).insetBy(dx: 0.1, dy: 0.1))
/*
case normal = 0
case multiply = 1
case screen = 2
case overlay = 3
case darken = 4
case lighten = 5
case colorDodge = 6
case colorBurn = 7
case softLight = 8
case hardLight = 9
case difference = 10
case exclusion = 11
case hue = 12
case saturation = 13
case color = 14
case luminosity = 15
case clear = 16
case copy = 17
case sourceIn = 18
case sourceOut = 19
case sourceAtop = 20
case destinationOver = 21
case destinationIn = 22
case destinationOut = 23
case destinationAtop = 24
case xor = 25
case plusDarker = 26
case plusLighter = 27
*/
var a: CGFloat = 0.0
var b: CGFloat = 0.0
fillColor.getHue(nil, saturation: nil, brightness: &b, alpha: &a)
addShadow(true, CGPoint(x: 0.0, y: 0.0), 20.0, 0.0, UIColor(white: 0.0, alpha: 0.04), .normal)
addShadow(true, CGPoint(x: 0.0, y: 0.0), 5.0, 0.0, UIColor(white: 0.0, alpha: 0.04), .normal)
let edgeWidth: CGFloat = 0.5
let edgeAlpha: CGFloat = max(0.2, min(0.8, a * a * a))
if b >= 0.2 {
for _ in 0 ..< 3 {
addShadow(false, CGPoint(x: 0.0, y: 0.0), 1.0, 0.0, UIColor(white: 1.0, alpha: edgeAlpha), .overlay)
addShadow(false, CGPoint(x: edgeWidth, y: edgeWidth), 1.4, 0.0, UIColor(white: 1.0, alpha: edgeAlpha * 0.9), .overlay)
addShadow(false, CGPoint(x: -edgeWidth, y: -edgeWidth), 1.4, 0.0, UIColor(white: 1.0, alpha: edgeAlpha * 0.9), .overlay)
}
} else {
for _ in 0 ..< 3 {
addShadow(false, CGPoint(x: 0.0, y: 0.0), 1.0, 0.0, UIColor(white: 1.0, alpha: edgeAlpha), .normal)
addShadow(false, CGPoint(x: edgeWidth, y: edgeWidth), 1.4, 0.0, UIColor(white: 1.0, alpha: edgeAlpha * 0.9), .normal)
addShadow(false, CGPoint(x: -edgeWidth, y: -edgeWidth), 1.4, 0.0, UIColor(white: 1.0, alpha: edgeAlpha * 0.9), .normal)
}
addShadow(false, CGPoint(x: 2.0, y: -2.0), 1.0, 0.0, highlightColor, false)
addShadow(false, CGPoint(x: -2.0, y: 2.0), 1.0, 0.0, highlightColor, false)
}
})!.stretchableImage(withLeftCapWidth: Int(size.width * 0.5), topCapHeight: Int(size.height * 0.5))
}.stretchableImage(withLeftCapWidth: Int(size.width * 0.5), topCapHeight: Int(size.height * 0.5))
}
static func generateForegroundImage(size: CGSize, isDark: Bool, fillColor: UIColor) -> UIImage {

View File

@ -3784,11 +3784,15 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
}
self.searchNavigationNode?.deactivate()
self.view.window?.endEditing(true)
if let firstResponder = self.view.window?.findFirstResponder() {
firstResponder.resignFirstResponder()
}
}
func dismissTextInput() {
self.view.window?.endEditing(true)
if let firstResponder = self.view.window?.findFirstResponder() {
firstResponder.resignFirstResponder()
}
}
func collapseInput() {