Skip to content

Commit ae9e72c

Browse files
committed
DiffableTextField now better matches the behavior of SwiftUI.TextField: triggers now stack, and submit actions now automatically dismisses the keyboard.
1 parent 05599c6 commit ae9e72c

File tree

3 files changed

+101
-36
lines changed

3 files changed

+101
-36
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//=----------------------------------------------------------------------------=
2+
// This source file is part of the DiffableTextViews open source project.
3+
//
4+
// Copyright (c) 2022 Oscar Byström Ericsson
5+
// Licensed under Apache License, Version 2.0
6+
//
7+
// See http://www.apache.org/licenses/LICENSE-2.0 for license information.
8+
//=----------------------------------------------------------------------------=
9+
10+
//*============================================================================*
11+
// MARK: * Trigger
12+
//*============================================================================*
13+
14+
public struct Trigger<Context> {
15+
16+
//=------------------------------------------------------------------------=
17+
// MARK: State
18+
//=------------------------------------------------------------------------=
19+
20+
@usableFromInline var action: (Context) -> Void
21+
22+
//=------------------------------------------------------------------------=
23+
// MARK: Initializers
24+
//=------------------------------------------------------------------------=
25+
26+
@inlinable public init(_ action: @escaping (Context) -> Void = { _ in }) {
27+
self.action = action
28+
}
29+
30+
//=------------------------------------------------------------------------=
31+
// MARK: Utilities
32+
//=------------------------------------------------------------------------=
33+
34+
@inlinable public func callAsFunction(_ context: Context) {
35+
self.action(context)
36+
}
37+
38+
//=------------------------------------------------------------------------=
39+
// MARK: Transformations
40+
//=------------------------------------------------------------------------=
41+
42+
@inlinable public mutating func append(_ other: Self) {
43+
self.action = { [self] context in
44+
//=----------------------------------=
45+
// MARK: Call This Then Other
46+
//=----------------------------------=
47+
self .action(context)
48+
other.action(context)
49+
}
50+
}
51+
52+
@inlinable public static func += (lhs: inout Self, rhs: Self) {
53+
lhs.append(rhs)
54+
}
55+
}

Sources/DiffableTextViewsXUIKit/DiffableTextField.swift

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -108,22 +108,6 @@ public struct DiffableTextField<Style: DiffableTextStyle>: UIViewRepresentable {
108108
self.downstream.transform(environment.diffableTextField_onUpdate)
109109
}
110110

111-
//=--------------------------------------------------------------------=
112-
// MARK: Events
113-
//=--------------------------------------------------------------------=
114-
115-
@inlinable public func textFieldDidBeginEditing(_ textField: UITextField) {
116-
synchronize()
117-
}
118-
119-
@inlinable public func textFieldDidEndEditing(_ textField: UITextField) {
120-
synchronize()
121-
}
122-
123-
@inlinable public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
124-
downstream.transform(environment.diffableTextField_onSubmit); return true
125-
}
126-
127111
//=--------------------------------------------------------------------=
128112
// MARK: Events
129113
//=--------------------------------------------------------------------=
@@ -178,6 +162,24 @@ public struct DiffableTextField<Style: DiffableTextStyle>: UIViewRepresentable {
178162
}
179163
}
180164

165+
//=--------------------------------------------------------------------=
166+
// MARK: Events
167+
//=--------------------------------------------------------------------=
168+
169+
@inlinable public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
170+
downstream.transform(environment.diffableTextField_onSubmit)
171+
downstream.wrapped.resignFirstResponder()
172+
return true
173+
}
174+
175+
@inlinable public func textFieldDidBeginEditing(_ textField: UITextField) {
176+
synchronize()
177+
}
178+
179+
@inlinable public func textFieldDidEndEditing(_ textField: UITextField) {
180+
synchronize()
181+
}
182+
181183
//=--------------------------------------------------------------------=
182184
// MARK: Synchronization
183185
//=--------------------------------------------------------------------=
@@ -232,22 +234,24 @@ public struct DiffableTextField<Style: DiffableTextStyle>: UIViewRepresentable {
232234
// MARK: * DiffableTextField x ID
233235
//*============================================================================*
234236

235-
public struct DiffableTextFieldID { public static let diffableTextField = Self() }
237+
public struct DiffableTextFieldID {
238+
public static let diffableTextField = Self()
239+
}
236240

237241
//*============================================================================*
238242
// MARK: * DiffableTextField x Environment
239243
//*============================================================================*
240244

241-
@usableFromInline enum DiffableTextField_OnSetup: EnvironmentKey {
242-
@usableFromInline static let defaultValue: (ProxyTextField) -> Void = { _ in }
245+
@usableFromInline enum DiffableTextField_OnSetup: EnvironmentKey {
246+
@usableFromInline static let defaultValue = Trigger<ProxyTextField>()
243247
}
244248

245249
@usableFromInline enum DiffableTextField_OnUpdate: EnvironmentKey {
246-
@usableFromInline static let defaultValue: (ProxyTextField) -> Void = { _ in }
250+
@usableFromInline static let defaultValue = Trigger<ProxyTextField>()
247251
}
248252

249253
@usableFromInline enum DiffableTextField_OnSubmit: EnvironmentKey {
250-
@usableFromInline static let defaultValue: (ProxyTextField) -> Void = { _ in }
254+
@usableFromInline static let defaultValue = Trigger<ProxyTextField>()
251255
}
252256

253257
//*============================================================================*
@@ -260,19 +264,19 @@ extension EnvironmentValues {
260264
// MARK: Accessors
261265
//=------------------------------------------------------------------------=
262266

263-
@inlinable var diffableTextField_onSetup: (ProxyTextField) -> Void {
264-
get { self[DiffableTextField_OnSetup .self] }
265-
set { self[DiffableTextField_OnSetup .self] = newValue }
267+
@inlinable var diffableTextField_onSetup: Trigger<ProxyTextField> {
268+
get { self[DiffableTextField_OnSetup.self] }
269+
set { self[DiffableTextField_OnSetup.self] += newValue }
266270
}
267271

268-
@inlinable var diffableTextField_onUpdate: (ProxyTextField) -> Void {
272+
@inlinable var diffableTextField_onUpdate: Trigger<ProxyTextField> {
269273
get { self[DiffableTextField_OnUpdate.self] }
270-
set { self[DiffableTextField_OnUpdate.self] = newValue }
274+
set { self[DiffableTextField_OnUpdate.self] += newValue }
271275
}
272276

273-
@inlinable var diffableTextField_onSubmit: (ProxyTextField) -> Void {
277+
@inlinable var diffableTextField_onSubmit: Trigger<ProxyTextField> {
274278
get { self[DiffableTextField_OnSubmit.self] }
275-
set { self[DiffableTextField_OnSubmit.self] = newValue }
279+
set { self[DiffableTextField_OnSubmit.self] += newValue }
276280
}
277281
}
278282

@@ -286,19 +290,19 @@ public extension View {
286290
// MARK: Transformations
287291
//=------------------------------------------------------------------------=
288292

289-
@inlinable func onSetup(of view: DiffableTextFieldID,
293+
@inlinable func onSetup(of view: DiffableTextFieldID,
290294
_ action: @escaping (ProxyTextField) -> Void) -> some View {
291-
environment(\.diffableTextField_onSetup, action)
295+
environment(\.diffableTextField_onSetup, Trigger(action))
292296
}
293297

294298
@inlinable func onUpdate(of view: DiffableTextFieldID,
295299
_ action: @escaping (ProxyTextField) -> Void) -> some View {
296-
environment(\.diffableTextField_onUpdate, action)
300+
environment(\.diffableTextField_onUpdate, Trigger(action))
297301
}
298302

299303
@inlinable func onSubmit(of view: DiffableTextFieldID,
300304
_ action: @escaping (ProxyTextField) -> Void) -> some View {
301-
environment(\.diffableTextField_onSubmit, action)
305+
environment(\.diffableTextField_onSubmit, Trigger(action))
302306
}
303307
}
304308

Sources/DiffableTextViewsXUIKit/Helpers/Downstream.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ import UIKit
1818

1919
@usableFromInline final class Downstream {
2020
@usableFromInline typealias Position = DiffableTextKit.Position<UTF16>
21-
21+
@usableFromInline typealias Proxy = DiffableTextKitXUIKit.ProxyTextField
22+
@usableFromInline typealias Wrapped = DiffableTextKitXUIKit.BasicTextField
23+
2224
//=------------------------------------------------------------------------=
2325
// MARK: State
2426
//=------------------------------------------------------------------------=
2527

26-
@usableFromInline var wrapped = BasicTextField()
28+
@usableFromInline var wrapped = Wrapped()
2729

2830
//=------------------------------------------------------------------------=
2931
// MARK: Initializers
@@ -63,8 +65,12 @@ import UIKit
6365
wrapped.selectedTextRange = offsets(selection)
6466
}
6567

66-
@inlinable func transform(_ transform: (ProxyTextField) -> Void) {
67-
transform(ProxyTextField(wrapped))
68+
@inlinable func transform(_ transform: Trigger<Proxy>) {
69+
transform(Proxy(wrapped))
70+
}
71+
72+
@inlinable func transform(_ transform: (Proxy) -> Void) {
73+
transform(Proxy(wrapped))
6874
}
6975

7076
//=------------------------------------------------------------------------=

0 commit comments

Comments
 (0)