Фикс многострочного input (iOS 17-18), скругления glass iOS 26, откат swizzle таб-бара
This commit is contained in:
@@ -112,6 +112,9 @@ struct ChatTextInput: UIViewRepresentable {
|
||||
var onKeyboardHeightChange: (CGFloat) -> Void
|
||||
var onUserTextInsertion: () -> Void = {}
|
||||
var onMultilineChange: (Bool) -> Void = { _ in }
|
||||
/// Reports the ideal height (clamped to max 5 lines) on every text change.
|
||||
/// Used to drive `@State` frame height in the composer layout.
|
||||
var onTextHeightChange: (CGFloat) -> Void = { _ in }
|
||||
var font: UIFont = .systemFont(ofSize: 17, weight: .regular)
|
||||
var textColor: UIColor = .white
|
||||
var placeholderColor: UIColor = UIColor.white.withAlphaComponent(0.35)
|
||||
@@ -255,6 +258,22 @@ struct ChatTextInput: UIViewRepresentable {
|
||||
tv.setNeedsLayout()
|
||||
tv.layoutIfNeeded()
|
||||
checkMultiline(tv)
|
||||
reportHeight(tv)
|
||||
}
|
||||
|
||||
/// Computes the ideal height (clamped to max 5 lines) and reports to SwiftUI.
|
||||
/// This drives `@State textInputHeight` in the composer → forces relayout.
|
||||
private func reportHeight(_ tv: UITextView) {
|
||||
let lineHeight = tv.font?.lineHeight ?? 20
|
||||
let maxLines: CGFloat = 5
|
||||
let insets = tv.textContainerInset
|
||||
let maxTextHeight = lineHeight * maxLines
|
||||
let maxTotalHeight = maxTextHeight + insets.top + insets.bottom
|
||||
let fittingSize = tv.sizeThatFits(
|
||||
CGSize(width: tv.bounds.width, height: .greatestFiniteMagnitude)
|
||||
)
|
||||
let height = max(36, min(fittingSize.height, maxTotalHeight))
|
||||
parent.onTextHeightChange(height)
|
||||
}
|
||||
|
||||
private func checkMultiline(_ tv: UITextView) {
|
||||
|
||||
@@ -39,6 +39,7 @@ struct ChatDetailView: View {
|
||||
|
||||
@State private var messageText = ""
|
||||
@State private var isMultilineInput = false
|
||||
@State private var textInputHeight: CGFloat = 36
|
||||
@State private var sendError: String?
|
||||
@State private var isViewActive = false
|
||||
// markReadTask removed — read receipts no longer sent from .onChange(of: messages.count)
|
||||
@@ -995,11 +996,17 @@ private extension ChatDetailView {
|
||||
isMultilineInput = multiline
|
||||
}
|
||||
},
|
||||
onTextHeightChange: { h in
|
||||
withAnimation(.easeInOut(duration: 0.2)) {
|
||||
textInputHeight = h
|
||||
}
|
||||
},
|
||||
textColor: UIColor(RosettaColors.Adaptive.text),
|
||||
placeholderColor: UIColor(RosettaColors.Adaptive.textSecondary.opacity(0.5))
|
||||
)
|
||||
.padding(.leading, 6)
|
||||
.frame(maxWidth: .infinity, minHeight: 36, alignment: .bottomLeading)
|
||||
.frame(maxWidth: .infinity, alignment: .bottomLeading)
|
||||
.frame(height: textInputHeight)
|
||||
|
||||
HStack(alignment: .center, spacing: 0) {
|
||||
Button {
|
||||
@@ -1052,6 +1059,7 @@ private extension ChatDetailView {
|
||||
.padding(3)
|
||||
.frame(minHeight: 42, alignment: .bottom)
|
||||
.background { glass(shape: .rounded(isMultilineInput ? 16 : 21), strokeOpacity: 0.18) }
|
||||
.clipShape(RoundedRectangle(cornerRadius: isMultilineInput ? 16 : 21, style: .continuous))
|
||||
.padding(.leading, 6)
|
||||
|
||||
Button(action: trailingAction) {
|
||||
|
||||
Reference in New Issue
Block a user