iOS 15 fixes

This commit is contained in:
Shadowfacts 2024-08-15 23:40:07 -07:00
parent 17c67a3d5d
commit f001e8edcd
2 changed files with 54 additions and 2 deletions

View File

@ -116,6 +116,8 @@ public struct NavigationTitlePreferenceKey: PreferenceKey {
private struct ToolbarActions: ToolbarContent { private struct ToolbarActions: ToolbarContent {
@ObservedObject var draft: Draft @ObservedObject var draft: Draft
// Prior to iOS 16, the toolbar content doesn't seem to have access
// to the environment form the containing view.
let controller: ComposeController let controller: ComposeController
var body: some ToolbarContent { var body: some ToolbarContent {

View File

@ -8,6 +8,8 @@
import SwiftUI import SwiftUI
struct NewMainTextView: View { struct NewMainTextView: View {
static var minHeight: CGFloat { 150 }
@Binding var value: String @Binding var value: String
@FocusState.Binding var focusedField: FocusableField? @FocusState.Binding var focusedField: FocusableField?
@State private var becomeFirstResponder = true @State private var becomeFirstResponder = true
@ -16,6 +18,7 @@ struct NewMainTextView: View {
NewMainTextViewRepresentable(value: $value, becomeFirstResponder: $becomeFirstResponder) NewMainTextViewRepresentable(value: $value, becomeFirstResponder: $becomeFirstResponder)
.focused($focusedField, equals: .body) .focused($focusedField, equals: .body)
.modifier(FocusedInputModifier()) .modifier(FocusedInputModifier())
.modifier(HeightExpandingModifier(minHeight: Self.minHeight))
.overlay(alignment: .topLeading) { .overlay(alignment: .topLeading) {
if value.isEmpty { if value.isEmpty {
PlaceholderView() PlaceholderView()
@ -34,6 +37,9 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
@Environment(\.composeUIConfig.useTwitterKeyboard) private var useTwitterKeyboard @Environment(\.composeUIConfig.useTwitterKeyboard) private var useTwitterKeyboard
// TODO: test textSelectionStartsAtBeginning // TODO: test textSelectionStartsAtBeginning
@Environment(\.composeUIConfig.textSelectionStartsAtBeginning) private var textSelectionStartsAtBeginning @Environment(\.composeUIConfig.textSelectionStartsAtBeginning) private var textSelectionStartsAtBeginning
#if !os(visionOS)
@Environment(\.textViewContentHeight) @Binding private var textViewContentHeight
#endif
func makeUIView(context: Context) -> UITextView { func makeUIView(context: Context) -> UITextView {
let view: UITextView let view: UITextView
@ -86,6 +92,16 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
becomeFirstResponder = false becomeFirstResponder = false
} }
} }
#if !os(visionOS)
if #unavailable(iOS 16.0) {
DispatchQueue.main.async {
let targetSize = CGSize(width: uiView.bounds.width, height: UIView.layoutFittingCompressedSize.height)
let fittingSize = uiView.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .defaultHigh)
textViewContentHeight = fittingSize.height
}
}
#endif
} }
func makeCoordinator() -> WrappedTextViewCoordinator { func makeCoordinator() -> WrappedTextViewCoordinator {
@ -96,12 +112,11 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
return coordinator return coordinator
} }
// TODO: fallback for this on iOS 15
@available(iOS 16.0, *) @available(iOS 16.0, *)
func sizeThatFits(_ proposal: ProposedViewSize, uiView: UIViewType, context: Context) -> CGSize? { func sizeThatFits(_ proposal: ProposedViewSize, uiView: UIViewType, context: Context) -> CGSize? {
let width = proposal.width ?? 10 let width = proposal.width ?? 10
let size = uiView.sizeThatFits(CGSize(width: width, height: 0)) let size = uiView.sizeThatFits(CGSize(width: width, height: 0))
return CGSize(width: width, height: max(150, size.height)) return CGSize(width: width, height: max(NewMainTextView.minHeight, size.height))
} }
} }
@ -261,3 +276,38 @@ private struct PlaceholderView: View {
.allowsHitTesting(false) .allowsHitTesting(false)
} }
} }
#if !os(visionOS)
@available(iOS, obsoleted: 16.0)
private struct HeightExpandingModifier: ViewModifier {
let minHeight: CGFloat
@State private var height: CGFloat?
private var effectiveHeight: CGFloat {
height.map { max($0, minHeight) } ?? minHeight
}
func body(content: Content) -> some View {
if #available(iOS 16.0, *) {
content
} else {
content
.frame(height: effectiveHeight)
.environment(\.textViewContentHeight, $height)
}
}
}
@available(iOS, obsoleted: 16.0)
private struct TextViewContentHeightKey: EnvironmentKey {
static var defaultValue: Binding<CGFloat?> { .constant(nil) }
}
@available(iOS, obsoleted: 16.0)
private extension EnvironmentValues {
var textViewContentHeight: Binding<CGFloat?> {
get { self[TextViewContentHeightKey.self] }
set { self[TextViewContentHeightKey.self] = newValue }
}
}
#endif