react-native-keyboard-controller 1.14.1 → 1.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,7 +20,7 @@ class FocusedInputLayoutChangedEvent(
20
20
  viewId: Int,
21
21
  private val event: FocusedInputLayoutChangedEventData,
22
22
  ) : Event<FocusedInputLayoutChangedEvent>(surfaceId, viewId) {
23
- override fun getEventName() = "topFocusedInputLayoutChanged"
23
+ override fun getEventName() = EVENT_NAME
24
24
 
25
25
  // All events for a given view can be coalesced
26
26
  override fun getCoalescingKey(): Short = 0
@@ -41,4 +41,8 @@ class FocusedInputLayoutChangedEvent(
41
41
  },
42
42
  )
43
43
  }
44
+
45
+ companion object {
46
+ const val EVENT_NAME = "topFocusedInputLayoutChanged"
47
+ }
44
48
  }
@@ -19,7 +19,7 @@ class FocusedInputSelectionChangedEvent(
19
19
  viewId: Int,
20
20
  private val event: FocusedInputSelectionChangedEventData,
21
21
  ) : Event<FocusedInputSelectionChangedEvent>(surfaceId, viewId) {
22
- override fun getEventName() = "topFocusedInputSelectionChanged"
22
+ override fun getEventName() = EVENT_NAME
23
23
 
24
24
  // All events for a given view can be coalesced
25
25
  override fun getCoalescingKey(): Short = 0
@@ -49,4 +49,8 @@ class FocusedInputSelectionChangedEvent(
49
49
  },
50
50
  )
51
51
  }
52
+
53
+ companion object {
54
+ const val EVENT_NAME = "topFocusedInputSelectionChanged"
55
+ }
52
56
  }
@@ -9,7 +9,7 @@ class FocusedInputTextChangedEvent(
9
9
  viewId: Int,
10
10
  private val text: String,
11
11
  ) : Event<FocusedInputTextChangedEvent>(surfaceId, viewId) {
12
- override fun getEventName() = "topFocusedInputTextChanged"
12
+ override fun getEventName() = EVENT_NAME
13
13
 
14
14
  // All events for a given view can be coalesced
15
15
  override fun getCoalescingKey(): Short = 0
@@ -18,4 +18,8 @@ class FocusedInputTextChangedEvent(
18
18
  Arguments.createMap().apply {
19
19
  putString("text", text)
20
20
  }
21
+
22
+ companion object {
23
+ const val EVENT_NAME = "topFocusedInputTextChanged"
24
+ }
21
25
  }
@@ -8,13 +8,13 @@ import com.facebook.react.uimanager.events.Event
8
8
  class KeyboardTransitionEvent(
9
9
  surfaceId: Int,
10
10
  viewId: Int,
11
- private val event: String,
11
+ private val event: EventName,
12
12
  private val height: Double,
13
13
  private val progress: Double,
14
14
  private val duration: Int,
15
15
  private val target: Int,
16
16
  ) : Event<KeyboardTransitionEvent>(surfaceId, viewId) {
17
- override fun getEventName() = event
17
+ override fun getEventName() = event.value
18
18
 
19
19
  // All events for a given view can be coalesced?
20
20
  override fun getCoalescingKey(): Short = 0
@@ -26,4 +26,20 @@ class KeyboardTransitionEvent(
26
26
  putInt("duration", duration)
27
27
  putInt("target", target)
28
28
  }
29
+
30
+ companion object {
31
+ enum class EventName(
32
+ val value: String,
33
+ ) {
34
+ Move("topKeyboardMove"),
35
+ Start("topKeyboardMoveStart"),
36
+ End("topKeyboardMoveEnd"),
37
+ Interactive("topKeyboardMoveInteractive"),
38
+ }
39
+
40
+ val Move = EventName.Move
41
+ val Start = EventName.Start
42
+ val End = EventName.End
43
+ val Interactive = EventName.Interactive
44
+ }
29
45
  }
@@ -79,7 +79,7 @@ class KeyboardAnimationCallback(
79
79
  KeyboardTransitionEvent(
80
80
  surfaceId,
81
81
  eventPropagationView.id,
82
- "topKeyboardMoveStart",
82
+ KeyboardTransitionEvent.Start,
83
83
  this.persistentKeyboardHeight,
84
84
  1.0,
85
85
  0,
@@ -91,7 +91,7 @@ class KeyboardAnimationCallback(
91
91
  KeyboardTransitionEvent(
92
92
  surfaceId,
93
93
  eventPropagationView.id,
94
- "topKeyboardMoveEnd",
94
+ KeyboardTransitionEvent.End,
95
95
  this.persistentKeyboardHeight,
96
96
  1.0,
97
97
  0,
@@ -203,7 +203,7 @@ class KeyboardAnimationCallback(
203
203
  KeyboardTransitionEvent(
204
204
  surfaceId,
205
205
  eventPropagationView.id,
206
- "topKeyboardMoveStart",
206
+ KeyboardTransitionEvent.Start,
207
207
  keyboardHeight,
208
208
  if (!isKeyboardVisible) 0.0 else 1.0,
209
209
  duration,
@@ -258,7 +258,12 @@ class KeyboardAnimationCallback(
258
258
  "DiffY: $diffY $height $progress ${InteractiveKeyboardProvider.isInteractive} $viewTagFocused",
259
259
  )
260
260
 
261
- val event = if (InteractiveKeyboardProvider.isInteractive) "topKeyboardMoveInteractive" else "topKeyboardMove"
261
+ val event =
262
+ if (InteractiveKeyboardProvider.isInteractive) {
263
+ KeyboardTransitionEvent.Interactive
264
+ } else {
265
+ KeyboardTransitionEvent.Move
266
+ }
262
267
  context.dispatchEvent(
263
268
  eventPropagationView.id,
264
269
  KeyboardTransitionEvent(
@@ -315,7 +320,7 @@ class KeyboardAnimationCallback(
315
320
  KeyboardTransitionEvent(
316
321
  surfaceId,
317
322
  eventPropagationView.id,
318
- "topKeyboardMoveEnd",
323
+ KeyboardTransitionEvent.End,
319
324
  keyboardHeight,
320
325
  if (!isKeyboardVisible) 0.0 else 1.0,
321
326
  duration,
@@ -343,7 +348,7 @@ class KeyboardAnimationCallback(
343
348
  getEventParams(keyboardHeight),
344
349
  )
345
350
  // dispatch `onMove` to update RN animated value and `onEnd` to indicate that transition finished
346
- listOf("topKeyboardMove", "topKeyboardMoveEnd").forEach { eventName ->
351
+ listOf(KeyboardTransitionEvent.Move, KeyboardTransitionEvent.End).forEach { eventName ->
347
352
  context.dispatchEvent(
348
353
  eventPropagationView.id,
349
354
  KeyboardTransitionEvent(
@@ -371,7 +376,11 @@ class KeyboardAnimationCallback(
371
376
  duration = 0
372
377
 
373
378
  context.emitEvent("KeyboardController::keyboardWillShow", getEventParams(keyboardHeight))
374
- listOf("topKeyboardMoveStart", "topKeyboardMove", "topKeyboardMoveEnd").forEach { eventName ->
379
+ listOf(
380
+ KeyboardTransitionEvent.Start,
381
+ KeyboardTransitionEvent.Move,
382
+ KeyboardTransitionEvent.End,
383
+ ).forEach { eventName ->
375
384
  context.dispatchEvent(
376
385
  eventPropagationView.id,
377
386
  KeyboardTransitionEvent(
@@ -3,6 +3,10 @@ package com.reactnativekeyboardcontroller.managers
3
3
  import com.facebook.react.bridge.ReactApplicationContext
4
4
  import com.facebook.react.common.MapBuilder
5
5
  import com.facebook.react.uimanager.ThemedReactContext
6
+ import com.reactnativekeyboardcontroller.events.FocusedInputLayoutChangedEvent
7
+ import com.reactnativekeyboardcontroller.events.FocusedInputSelectionChangedEvent
8
+ import com.reactnativekeyboardcontroller.events.FocusedInputTextChangedEvent
9
+ import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
6
10
  import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
7
11
 
8
12
  @Suppress("detekt:UnusedPrivateProperty")
@@ -36,19 +40,19 @@ class KeyboardControllerViewManagerImpl(
36
40
  fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
37
41
  val map: MutableMap<String, Any> =
38
42
  MapBuilder.of(
39
- "topKeyboardMove",
43
+ KeyboardTransitionEvent.Move.value,
40
44
  MapBuilder.of("registrationName", "onKeyboardMove"),
41
- "topKeyboardMoveStart",
45
+ KeyboardTransitionEvent.Start.value,
42
46
  MapBuilder.of("registrationName", "onKeyboardMoveStart"),
43
- "topKeyboardMoveEnd",
47
+ KeyboardTransitionEvent.End.value,
44
48
  MapBuilder.of("registrationName", "onKeyboardMoveEnd"),
45
- "topKeyboardMoveInteractive",
49
+ KeyboardTransitionEvent.Interactive.value,
46
50
  MapBuilder.of("registrationName", "onKeyboardMoveInteractive"),
47
- "topFocusedInputLayoutChanged",
51
+ FocusedInputLayoutChangedEvent.EVENT_NAME,
48
52
  MapBuilder.of("registrationName", "onFocusedInputLayoutChanged"),
49
- "topFocusedInputTextChanged",
53
+ FocusedInputTextChangedEvent.EVENT_NAME,
50
54
  MapBuilder.of("registrationName", "onFocusedInputTextChanged"),
51
- "topFocusedInputSelectionChanged",
55
+ FocusedInputSelectionChangedEvent.EVENT_NAME,
52
56
  MapBuilder.of("registrationName", "onFocusedInputSelectionChanged"),
53
57
  )
54
58
 
@@ -26,7 +26,7 @@ public extension UIApplication {
26
26
  }
27
27
 
28
28
  static func topViewController(
29
- base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController
29
+ base: UIViewController? = UIApplication.shared.activeWindow?.rootViewController
30
30
  ) -> UIViewController? {
31
31
  if let nav = base as? UINavigationController {
32
32
  return topViewController(base: nav.visibleViewController)
@@ -11,9 +11,29 @@ import UIKit
11
11
 
12
12
  public extension UIView {
13
13
  var globalFrame: CGRect? {
14
- let rootView = UIApplication.shared.keyWindow?.rootViewController?.view
14
+ let rootView = UIApplication.shared.activeWindow?.rootViewController?.view
15
15
  return superview?.convert(frame, to: rootView)
16
16
  }
17
+
18
+ func isVisibleInHierarchy(initial: Bool = true) -> Bool {
19
+ guard let window = window else {
20
+ return false
21
+ }
22
+ if isHidden || alpha == 0.0 {
23
+ return false
24
+ }
25
+ if superview === window {
26
+ return true
27
+ } else if let superview = superview {
28
+ if initial, frame.minY >= superview.frame.height {
29
+ return false
30
+ } else {
31
+ return superview.isVisibleInHierarchy(initial: false)
32
+ }
33
+ } else {
34
+ return false
35
+ }
36
+ }
17
37
  }
18
38
 
19
39
  public extension Optional where Wrapped == UIView {
@@ -32,4 +52,11 @@ public extension Optional where Wrapped == UIView {
32
52
 
33
53
  return (position, frameY)
34
54
  }
55
+
56
+ func isVisibleInHierarchy(initial: Bool = true) -> Bool {
57
+ guard let view = self else {
58
+ return false
59
+ }
60
+ return view.isVisibleInHierarchy(initial: initial)
61
+ }
35
62
  }
@@ -37,8 +37,11 @@ public extension UIWindow {
37
37
  }
38
38
 
39
39
  func getTopWindow() -> UIWindow? {
40
- // Return the keyboard window if it's available, otherwise return the last window
41
- return keyboardWindow ?? UIApplication.shared.activeWindow
40
+ let keyboardView = KeyboardView.find()
41
+ // return the keyboard window if it's available and keyboard is visible, otherwise return the last window
42
+ return (keyboardWindow != nil && keyboardView.isVisibleInHierarchy())
43
+ ? keyboardWindow
44
+ : UIApplication.shared.activeWindow
42
45
  }
43
46
  }
44
47
 
@@ -204,10 +204,10 @@ public class FocusedInputObserver: NSObject {
204
204
  }
205
205
 
206
206
  private func substituteDelegateBack(_ input: UIResponder?) {
207
- if let textField = input as? UITextField {
208
- textField.delegate = delegate.activeDelegate as? UITextFieldDelegate
209
- } else if let textView = input as? UITextView {
210
- (textView as? RCTUITextView)?.setForceDelegate(delegate.activeDelegate as? UITextViewDelegate)
207
+ if let textField = input as? UITextField, let oldDelegate = delegate.activeDelegate as? UITextFieldDelegate {
208
+ textField.delegate = oldDelegate
209
+ } else if let textView = input as? UITextView, let oldDelegate = delegate.activeDelegate as? UITextViewDelegate {
210
+ (textView as? RCTUITextView)?.setForceDelegate(oldDelegate)
211
211
  }
212
212
  }
213
213
 
@@ -102,10 +102,27 @@ RCT_EXPORT_VIEW_PROPERTY(visible, BOOL)
102
102
  _touchHandler = [[RCTTouchHandler alloc] initWithBridge:bridge];
103
103
  _contentView = [[UIView alloc] initWithFrame:CGRectZero];
104
104
  }
105
+ [[NSNotificationCenter defaultCenter] addObserver:self
106
+ selector:@selector(hide)
107
+ name:RCTJavaScriptWillStartLoadingNotification
108
+ object:nil];
105
109
  return self;
106
110
  }
107
111
  #endif
108
112
 
113
+ - (void)dealloc
114
+ {
115
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
116
+ }
117
+
118
+ // MARK: lifecycle methods
119
+ - (void)didMoveToSuperview
120
+ {
121
+ if (self.superview == nil) {
122
+ [self hide];
123
+ }
124
+ }
125
+
109
126
  // MARK: touch handling
110
127
  - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
111
128
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-keyboard-controller",
3
- "version": "1.14.1",
3
+ "version": "1.14.2",
4
4
  "description": "Keyboard manager which works in identical way on both iOS and Android",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",