Skip to content

Commit

Permalink
Introduces a backport for TextInputCapitalization
Browse files Browse the repository at this point in the history
Rate limit · GitHub

Access has been restricted

You have triggered a rate limit.

Please wait a few minutes before you try again;
in some cases this may take up to an hour.

shaps80 committed May 8, 2023
1 parent affe67f commit 5a294a7
Showing 3 changed files with 74 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -2,22 +2,64 @@ import SwiftUI
import SwiftBackports

#if os(iOS)
extension Backport where Wrapped: View {
@available(iOS, deprecated: 15)
public extension Backport where Wrapped: View {
/// Sets how often the shift key in the keyboard is automatically enabled.
///
/// Use `backport.textInputAutocapitalization(_:)` when you need to automatically
/// capitalize words, sentences, or other text like proper nouns.
///
/// In example below, as the user enters text the shift key is
/// automatically enabled before every word:
///
/// TextField("Last, First", text: $fullName)
/// .backport.textInputAutocapitalization(.words)
///
/// The ``TextInputAutocapitalization`` struct defines the available
/// autocapitalizing behavior. Providing `nil` to this view modifier does
/// not change the autocapitalization behavior. The default is
/// `Backport<Any>.TextInputAutocapitalization.sentences`.
///
/// - Parameter autocapitalization: One of the capitalizing behaviors
/// defined in the `Backport<Any>.TextInputAutocapitalization` struct or nil.
@ViewBuilder
func textInputAutocapitalization(_ autocapitalization: Backport<Any>.TextInputAutocapitalization?) -> some View {
wrapped.modifier(
AutoCapitalizationModifier(
capitalization: autocapitalization?.capitalization ?? .none
)
)
Group {
if #available(iOS 16, *) {
var type: SwiftUI.TextInputAutocapitalization {
switch autocapitalization {
case .none:
return .sentences
case .some(let wrapped):
switch wrapped {
case .never: return .never
case .words: return .words
case .sentences: return .sentences
case .characters: return .characters
default: return .sentences
}
}
}
wrapped.textInputAutocapitalization(type)
} else {
wrapped.modifier(
AutoCapitalizationModifier(
capitalization: autocapitalization?.capitalization ?? .none
)
)
}
}
.environment(\.textInputAutocapitalization, autocapitalization)
}
}

@available(iOS, introduced: 13, deprecated: 15)
@available(macOS, unavailable)
@available(tvOS, unavailable)
@available(watchOS, unavailable)
@available(iOS, deprecated: 15)
extension Backport<Any> {
public struct TextInputAutocapitalization {
/// The kind of autocapitalization behavior applied during text input.
///
/// Pass an instance of `Backport<Any>.TextInputAutocapitalization` to the
/// ``View/backport.textInputAutocapitalization(_:)`` view modifier.
public struct TextInputAutocapitalization: Equatable {
internal let capitalization: UITextAutocapitalizationType

fileprivate init(capitalization: UITextAutocapitalizationType) {
@@ -38,27 +80,41 @@ extension Backport<Any> {
/// Defines an autocapitalizing behavior that will capitalize every letter.
public static var characters: TextInputAutocapitalization { .init(capitalization: .allCharacters) }

/// Creates a new `Backport<Any>.TextInputAutocapitalization` struct from a
/// `UITextAutocapitalizationType` enum.
public init?(_ type: UITextAutocapitalizationType) {
self.capitalization = type
}
}
}

@available(iOS, deprecated: 15)
private struct AutoCapitalizationModifier: ViewModifier {
let capitalization: UITextAutocapitalizationType

func body(content: Content) -> some View {
content
.inspect { inspector in
inspector.ancestor(ofType: UITextField.self)
inspector.any(ofType: UITextField.self)
} customize: { view in
view.autocapitalizationType = capitalization
}
.inspect { inspector in
inspector.ancestor(ofType: UITextView.self)
inspector.any(ofType: UITextView.self)
} customize: { view in
view.autocapitalizationType = capitalization
}
}
}

private struct AutoCapitalizationEnvironmentKey: EnvironmentKey {
static var defaultValue: Backport<Any>.TextInputAutocapitalization? = .sentences
}

internal extension EnvironmentValues {
var textInputAutocapitalization: Backport<Any>.TextInputAutocapitalization? {
get { self[AutoCapitalizationEnvironmentKey.self] }
set { self[AutoCapitalizationEnvironmentKey.self] = newValue }
}
}
#endif
4 changes: 2 additions & 2 deletions Sources/SwiftUIBackports/iOS/Submit/Submit.swift
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ public extension Backport where Wrapped: View {
/// Different views may have different triggers for the provided action. A TextField, or SecureField will trigger this action when the user hits the hardware or software return key. This modifier may also bind this action to a default action keyboard shortcut. You may set this action on an individual view or an entire view hierarchy.
///
/// TextField("Username", text: $username)
/// .onSubmit {
/// .backport.onSubmit {
/// guard viewModel.validate() else { return }
/// viewModel.login()
/// }
@@ -31,7 +31,7 @@ public extension Backport where Wrapped: View {
/// A semantic label describing the label of submission within a view hierarchy.
///
/// A submit label is a description of a submission action provided to a
/// view hierarchy using the ``View/onSubmit(of:_:)`` modifier.
/// view hierarchy using the ``View/backport.onSubmit(of:_:)`` modifier.
@ViewBuilder
func submitLabel(_ label: Backport<Any>.SubmitLabel) -> some View {
Group {
5 changes: 3 additions & 2 deletions Sources/SwiftUIBackports/iOS/TextEditor/TextEditor.swift
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ extension Backport where Wrapped == Any {
/// @State private var fullText: String = "This is some editable text..."
///
/// var body: some View {
/// TextEditor(text: $fullText)
/// Backport.TextEditor(text: $fullText)
/// .foregroundColor(Color.gray)
/// .font(.custom("HelveticaNeue", size: 13))
/// .lineSpacing(5)
@@ -42,7 +42,7 @@ extension Backport where Wrapped == Any {
/// @State private var fullText: String = "This is some editable text..."
///
/// var body: some View {
/// TextEditor(text: $fullText)
/// Backport.TextEditor(text: $fullText)
/// .foregroundColor(Color.gray)
/// .font(.custom("HelveticaNeue", size: 13))
/// .lineSpacing(5)
@@ -100,6 +100,7 @@ extension Backport where Wrapped == Any {
view.backgroundColor = .clear
view.dataDetectorTypes = []
view.returnKeyType = parent.environment.backportSubmitLabel.returnKeyType
view.autocapitalizationType = parent.environment.textInputAutocapitalization?.capitalization ?? .sentences

switch parent.environment.autocorrectionDisabled {
case true:

0 comments on commit 5a294a7

Please sign in to comment.