Фикс многострочного input (iOS 17-18), скругления glass iOS 26, откат swizzle таб-бара
This commit is contained in:
@@ -530,7 +530,7 @@
|
|||||||
853F296C2F4B50420092AD05 /* Release */,
|
853F296C2F4B50420092AD05 /* Release */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Debug;
|
||||||
};
|
};
|
||||||
853F296D2F4B50420092AD05 /* Build configuration list for PBXNativeTarget "Rosetta" */ = {
|
853F296D2F4B50420092AD05 /* Build configuration list for PBXNativeTarget "Rosetta" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
@@ -539,7 +539,7 @@
|
|||||||
853F296F2F4B50420092AD05 /* Release */,
|
853F296F2F4B50420092AD05 /* Release */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Debug;
|
||||||
};
|
};
|
||||||
B5D2E60ADEB8AE2E8F7615C6 /* Build configuration list for PBXNativeTarget "RosettaNotificationService" */ = {
|
B5D2E60ADEB8AE2E8F7615C6 /* Build configuration list for PBXNativeTarget "RosettaNotificationService" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
@@ -548,7 +548,7 @@
|
|||||||
0140D6320A9CF4B5E933E0B1 /* Debug */,
|
0140D6320A9CF4B5E933E0B1 /* Debug */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Debug;
|
||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
shouldAutocreateTestPlan = "YES">
|
shouldAutocreateTestPlan = "YES">
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
|
|||||||
@@ -112,6 +112,9 @@ struct ChatTextInput: UIViewRepresentable {
|
|||||||
var onKeyboardHeightChange: (CGFloat) -> Void
|
var onKeyboardHeightChange: (CGFloat) -> Void
|
||||||
var onUserTextInsertion: () -> Void = {}
|
var onUserTextInsertion: () -> Void = {}
|
||||||
var onMultilineChange: (Bool) -> Void = { _ in }
|
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 font: UIFont = .systemFont(ofSize: 17, weight: .regular)
|
||||||
var textColor: UIColor = .white
|
var textColor: UIColor = .white
|
||||||
var placeholderColor: UIColor = UIColor.white.withAlphaComponent(0.35)
|
var placeholderColor: UIColor = UIColor.white.withAlphaComponent(0.35)
|
||||||
@@ -255,6 +258,22 @@ struct ChatTextInput: UIViewRepresentable {
|
|||||||
tv.setNeedsLayout()
|
tv.setNeedsLayout()
|
||||||
tv.layoutIfNeeded()
|
tv.layoutIfNeeded()
|
||||||
checkMultiline(tv)
|
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) {
|
private func checkMultiline(_ tv: UITextView) {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ struct ChatDetailView: View {
|
|||||||
|
|
||||||
@State private var messageText = ""
|
@State private var messageText = ""
|
||||||
@State private var isMultilineInput = false
|
@State private var isMultilineInput = false
|
||||||
|
@State private var textInputHeight: CGFloat = 36
|
||||||
@State private var sendError: String?
|
@State private var sendError: String?
|
||||||
@State private var isViewActive = false
|
@State private var isViewActive = false
|
||||||
// markReadTask removed — read receipts no longer sent from .onChange(of: messages.count)
|
// markReadTask removed — read receipts no longer sent from .onChange(of: messages.count)
|
||||||
@@ -995,11 +996,17 @@ private extension ChatDetailView {
|
|||||||
isMultilineInput = multiline
|
isMultilineInput = multiline
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onTextHeightChange: { h in
|
||||||
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
|
textInputHeight = h
|
||||||
|
}
|
||||||
|
},
|
||||||
textColor: UIColor(RosettaColors.Adaptive.text),
|
textColor: UIColor(RosettaColors.Adaptive.text),
|
||||||
placeholderColor: UIColor(RosettaColors.Adaptive.textSecondary.opacity(0.5))
|
placeholderColor: UIColor(RosettaColors.Adaptive.textSecondary.opacity(0.5))
|
||||||
)
|
)
|
||||||
.padding(.leading, 6)
|
.padding(.leading, 6)
|
||||||
.frame(maxWidth: .infinity, minHeight: 36, alignment: .bottomLeading)
|
.frame(maxWidth: .infinity, alignment: .bottomLeading)
|
||||||
|
.frame(height: textInputHeight)
|
||||||
|
|
||||||
HStack(alignment: .center, spacing: 0) {
|
HStack(alignment: .center, spacing: 0) {
|
||||||
Button {
|
Button {
|
||||||
@@ -1052,6 +1059,7 @@ private extension ChatDetailView {
|
|||||||
.padding(3)
|
.padding(3)
|
||||||
.frame(minHeight: 42, alignment: .bottom)
|
.frame(minHeight: 42, alignment: .bottom)
|
||||||
.background { glass(shape: .rounded(isMultilineInput ? 16 : 21), strokeOpacity: 0.18) }
|
.background { glass(shape: .rounded(isMultilineInput ? 16 : 21), strokeOpacity: 0.18) }
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: isMultilineInput ? 16 : 21, style: .continuous))
|
||||||
.padding(.leading, 6)
|
.padding(.leading, 6)
|
||||||
|
|
||||||
Button(action: trailingAction) {
|
Button(action: trailingAction) {
|
||||||
|
|||||||
Reference in New Issue
Block a user