react-native-keyboard-controller 1.17.2 → 1.17.4
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.
- package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +15 -4
- package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt +20 -5
- package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt +4 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt +13 -4
- package/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +14 -2
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +12 -6
- package/android/src/main/java/com/reactnativekeyboardcontroller/views/overlay/OverKeyboardViewGroup.kt +11 -0
- package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +13 -3
- package/ios/KeyboardControllerModule.mm +2 -0
- package/ios/swizzling/UIResponderSwizzle.swift +57 -10
- package/ios/views/KeyboardControllerView.mm +18 -0
- package/ios/views/KeyboardControllerViewManager.swift +19 -0
- package/ios/views/KeyboardGestureAreaManager.mm +1 -0
- package/lib/commonjs/components/KeyboardAvoidingView/index.js +3 -2
- package/lib/commonjs/components/KeyboardAvoidingView/index.js.map +1 -1
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js +3 -0
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/commonjs/hooks/useWindowDimensions/index.js +29 -6
- package/lib/commonjs/hooks/useWindowDimensions/index.js.map +1 -1
- package/lib/module/components/KeyboardAvoidingView/index.js +3 -2
- package/lib/module/components/KeyboardAvoidingView/index.js.map +1 -1
- package/lib/module/components/KeyboardAwareScrollView/index.js +5 -2
- package/lib/module/components/KeyboardAwareScrollView/index.js.map +1 -1
- package/lib/module/hooks/useWindowDimensions/index.js +28 -1
- package/lib/module/hooks/useWindowDimensions/index.js.map +1 -1
- package/lib/typescript/hooks/useWindowDimensions/index.d.ts +2 -1
- package/package.json +1 -1
- package/src/components/KeyboardAvoidingView/index.tsx +3 -2
- package/src/components/KeyboardAwareScrollView/index.tsx +6 -1
- package/src/hooks/useWindowDimensions/index.ts +41 -1
- package/lib/commonjs/hooks/useWindowDimensions/index.android.js +0 -34
- package/lib/commonjs/hooks/useWindowDimensions/index.android.js.map +0 -1
- package/lib/module/hooks/useWindowDimensions/index.android.js +0 -27
- package/lib/module/hooks/useWindowDimensions/index.android.js.map +0 -1
- package/lib/typescript/hooks/useWindowDimensions/index.android.d.ts +0 -2
- package/src/hooks/useWindowDimensions/index.android.ts +0 -38
package/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt
CHANGED
|
@@ -18,17 +18,21 @@ class KeyboardControllerViewManager(
|
|
|
18
18
|
private val manager = KeyboardControllerViewManagerImpl(mReactContext)
|
|
19
19
|
private val mDelegate = KeyboardControllerViewManagerDelegate(this)
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
override fun getName(): String = KeyboardControllerViewManagerImpl.NAME
|
|
24
|
-
|
|
21
|
+
// region Lifecycle
|
|
25
22
|
override fun createViewInstance(context: ThemedReactContext): ReactViewGroup = manager.createViewInstance(context)
|
|
26
23
|
|
|
24
|
+
override fun invalidate() {
|
|
25
|
+
super.invalidate()
|
|
26
|
+
manager.invalidate()
|
|
27
|
+
}
|
|
28
|
+
|
|
27
29
|
override fun onAfterUpdateTransaction(view: ReactViewGroup) {
|
|
28
30
|
super.onAfterUpdateTransaction(view)
|
|
29
31
|
manager.setEdgeToEdge(view as EdgeToEdgeReactViewGroup)
|
|
30
32
|
}
|
|
33
|
+
// endregion
|
|
31
34
|
|
|
35
|
+
// region Props setters
|
|
32
36
|
@ReactProp(name = "statusBarTranslucent")
|
|
33
37
|
override fun setStatusBarTranslucent(
|
|
34
38
|
view: ReactViewGroup,
|
|
@@ -52,7 +56,14 @@ class KeyboardControllerViewManager(
|
|
|
52
56
|
view: ReactViewGroup,
|
|
53
57
|
value: Boolean,
|
|
54
58
|
) = manager.setEnabled(view as EdgeToEdgeReactViewGroup, value)
|
|
59
|
+
// endregion
|
|
55
60
|
|
|
61
|
+
// region Getters
|
|
56
62
|
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
|
|
57
63
|
manager.getExportedCustomDirectEventTypeConstants()
|
|
64
|
+
|
|
65
|
+
override fun getDelegate(): ViewManagerDelegate<ReactViewGroup> = mDelegate
|
|
66
|
+
|
|
67
|
+
override fun getName(): String = KeyboardControllerViewManagerImpl.NAME
|
|
68
|
+
// endregion
|
|
58
69
|
}
|
package/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt
CHANGED
|
@@ -2,6 +2,7 @@ package com.reactnativekeyboardcontroller.extensions
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.os.Build
|
|
5
|
+
import com.facebook.react.bridge.Arguments
|
|
5
6
|
import com.facebook.react.bridge.ReactContext
|
|
6
7
|
import com.facebook.react.bridge.WritableMap
|
|
7
8
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
@@ -9,13 +10,8 @@ import com.facebook.react.uimanager.ThemedReactContext
|
|
|
9
10
|
import com.facebook.react.uimanager.UIManagerHelper
|
|
10
11
|
import com.facebook.react.uimanager.events.Event
|
|
11
12
|
import com.facebook.react.uimanager.events.EventDispatcher
|
|
12
|
-
import com.reactnativekeyboardcontroller.listeners.WindowDimensionListener
|
|
13
13
|
import com.reactnativekeyboardcontroller.log.Logger
|
|
14
14
|
|
|
15
|
-
fun ThemedReactContext.setupWindowDimensionsListener() {
|
|
16
|
-
WindowDimensionListener(this)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
15
|
fun ThemedReactContext?.dispatchEvent(
|
|
20
16
|
viewId: Int,
|
|
21
17
|
event: Event<*>,
|
|
@@ -37,6 +33,25 @@ fun ThemedReactContext?.emitEvent(
|
|
|
37
33
|
Logger.i("ThemedReactContext", event)
|
|
38
34
|
}
|
|
39
35
|
|
|
36
|
+
fun ThemedReactContext?.keepShadowNodesInSync(viewId: Int) {
|
|
37
|
+
// originally by viewId we should lookup all connected nodes
|
|
38
|
+
// and send them to JS
|
|
39
|
+
// but at the moment JS side broadcasts events to all ViewType
|
|
40
|
+
// instances, so we can send even empty array
|
|
41
|
+
val tags = intArrayOf(viewId)
|
|
42
|
+
|
|
43
|
+
val tagsArray = Arguments.createArray()
|
|
44
|
+
for (tag in tags) {
|
|
45
|
+
tagsArray.pushInt(tag)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// emit the event to JS to re-sync the trees
|
|
49
|
+
val onAnimationEndedData = Arguments.createMap()
|
|
50
|
+
onAnimationEndedData.putArray("tags", tagsArray)
|
|
51
|
+
|
|
52
|
+
this?.reactApplicationContext?.emitDeviceEvent("onUserDrivenAnimationEnded", onAnimationEndedData)
|
|
53
|
+
}
|
|
54
|
+
|
|
40
55
|
val ThemedReactContext?.appearance: String
|
|
41
56
|
get() =
|
|
42
57
|
when {
|
|
@@ -20,6 +20,7 @@ import com.reactnativekeyboardcontroller.extensions.dispatchEvent
|
|
|
20
20
|
import com.reactnativekeyboardcontroller.extensions.dp
|
|
21
21
|
import com.reactnativekeyboardcontroller.extensions.emitEvent
|
|
22
22
|
import com.reactnativekeyboardcontroller.extensions.isKeyboardAnimation
|
|
23
|
+
import com.reactnativekeyboardcontroller.extensions.keepShadowNodesInSync
|
|
23
24
|
import com.reactnativekeyboardcontroller.extensions.keyboardType
|
|
24
25
|
import com.reactnativekeyboardcontroller.interactive.InteractiveKeyboardProvider
|
|
25
26
|
import com.reactnativekeyboardcontroller.log.Logger
|
|
@@ -327,6 +328,8 @@ class KeyboardAnimationCallback(
|
|
|
327
328
|
|
|
328
329
|
// reset to initial state
|
|
329
330
|
duration = 0
|
|
331
|
+
|
|
332
|
+
context.keepShadowNodesInSync(eventPropagationView.id)
|
|
330
333
|
}
|
|
331
334
|
|
|
332
335
|
if (isKeyboardInteractive) {
|
|
@@ -401,6 +404,7 @@ class KeyboardAnimationCallback(
|
|
|
401
404
|
)
|
|
402
405
|
}
|
|
403
406
|
context.emitEvent("KeyboardController::keyboardDidShow", getEventParams(keyboardHeight))
|
|
407
|
+
context.keepShadowNodesInSync(eventPropagationView.id)
|
|
404
408
|
|
|
405
409
|
this.persistentKeyboardHeight = keyboardHeight
|
|
406
410
|
}
|
package/android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.reactnativekeyboardcontroller.listeners
|
|
2
2
|
|
|
3
3
|
import android.view.ViewGroup
|
|
4
|
+
import android.view.ViewTreeObserver
|
|
4
5
|
import com.facebook.react.bridge.Arguments
|
|
5
6
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
7
|
import com.reactnativekeyboardcontroller.extensions.content
|
|
@@ -16,8 +17,9 @@ class WindowDimensionListener(
|
|
|
16
17
|
private val context: ThemedReactContext?,
|
|
17
18
|
) {
|
|
18
19
|
private var lastDispatchedDimensions = Dimensions(0.0, 0.0)
|
|
20
|
+
private var layoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
public fun attachListener() {
|
|
21
23
|
// attach to content view only once per app instance
|
|
22
24
|
if (context != null && listenerID != context.hashCode()) {
|
|
23
25
|
listenerID = context.hashCode()
|
|
@@ -26,12 +28,19 @@ class WindowDimensionListener(
|
|
|
26
28
|
|
|
27
29
|
updateWindowDimensions(content)
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
layoutListener =
|
|
32
|
+
ViewTreeObserver.OnGlobalLayoutListener {
|
|
33
|
+
updateWindowDimensions(content)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
content?.viewTreeObserver?.addOnGlobalLayoutListener(layoutListener)
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
39
|
|
|
40
|
+
public fun detachListener() {
|
|
41
|
+
context?.content?.viewTreeObserver?.removeOnGlobalLayoutListener(layoutListener)
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
private fun updateWindowDimensions(content: ViewGroup?) {
|
|
36
45
|
if (content == null) {
|
|
37
46
|
return
|
|
@@ -7,14 +7,26 @@ import com.reactnativekeyboardcontroller.events.FocusedInputLayoutChangedEvent
|
|
|
7
7
|
import com.reactnativekeyboardcontroller.events.FocusedInputSelectionChangedEvent
|
|
8
8
|
import com.reactnativekeyboardcontroller.events.FocusedInputTextChangedEvent
|
|
9
9
|
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
|
|
10
|
+
import com.reactnativekeyboardcontroller.listeners.WindowDimensionListener
|
|
10
11
|
import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
|
|
11
12
|
|
|
12
13
|
@Suppress("detekt:UnusedPrivateProperty")
|
|
13
14
|
class KeyboardControllerViewManagerImpl(
|
|
14
15
|
mReactContext: ReactApplicationContext,
|
|
15
16
|
) {
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
private var listener: WindowDimensionListener? = null
|
|
18
|
+
|
|
19
|
+
fun createViewInstance(reactContext: ThemedReactContext): EdgeToEdgeReactViewGroup {
|
|
20
|
+
if (listener == null) {
|
|
21
|
+
listener = WindowDimensionListener(reactContext)
|
|
22
|
+
listener?.attachListener()
|
|
23
|
+
}
|
|
24
|
+
return EdgeToEdgeReactViewGroup(reactContext)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
fun invalidate() {
|
|
28
|
+
listener?.detachListener()
|
|
29
|
+
}
|
|
18
30
|
|
|
19
31
|
fun setEnabled(
|
|
20
32
|
view: EdgeToEdgeReactViewGroup,
|
package/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt
CHANGED
|
@@ -15,7 +15,6 @@ import com.reactnativekeyboardcontroller.extensions.content
|
|
|
15
15
|
import com.reactnativekeyboardcontroller.extensions.removeSelf
|
|
16
16
|
import com.reactnativekeyboardcontroller.extensions.requestApplyInsetsWhenAttached
|
|
17
17
|
import com.reactnativekeyboardcontroller.extensions.rootView
|
|
18
|
-
import com.reactnativekeyboardcontroller.extensions.setupWindowDimensionsListener
|
|
19
18
|
import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallback
|
|
20
19
|
import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallbackConfig
|
|
21
20
|
import com.reactnativekeyboardcontroller.log.Logger
|
|
@@ -51,7 +50,6 @@ class EdgeToEdgeReactViewGroup(
|
|
|
51
50
|
private val modalAttachedWatcher = ModalAttachedWatcher(this, reactContext, config, ::getKeyboardCallback)
|
|
52
51
|
|
|
53
52
|
init {
|
|
54
|
-
reactContext.setupWindowDimensionsListener()
|
|
55
53
|
tag = VIEW_TAG
|
|
56
54
|
}
|
|
57
55
|
|
|
@@ -65,13 +63,13 @@ class EdgeToEdgeReactViewGroup(
|
|
|
65
63
|
return
|
|
66
64
|
}
|
|
67
65
|
|
|
68
|
-
this.
|
|
66
|
+
this.activate()
|
|
69
67
|
}
|
|
70
68
|
|
|
71
69
|
override fun onDetachedFromWindow() {
|
|
72
70
|
super.onDetachedFromWindow()
|
|
73
71
|
|
|
74
|
-
this.
|
|
72
|
+
this.deactivate()
|
|
75
73
|
}
|
|
76
74
|
|
|
77
75
|
override fun onConfigurationChanged(newConfig: Configuration?) {
|
|
@@ -189,12 +187,20 @@ class EdgeToEdgeReactViewGroup(
|
|
|
189
187
|
// region State managers
|
|
190
188
|
private fun enable() {
|
|
191
189
|
this.setupWindowInsets()
|
|
192
|
-
this.
|
|
193
|
-
modalAttachedWatcher.enable()
|
|
190
|
+
this.activate()
|
|
194
191
|
}
|
|
195
192
|
|
|
196
193
|
private fun disable() {
|
|
197
194
|
this.setupWindowInsets()
|
|
195
|
+
this.deactivate()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private fun activate() {
|
|
199
|
+
this.setupKeyboardCallbacks()
|
|
200
|
+
modalAttachedWatcher.enable()
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private fun deactivate() {
|
|
198
204
|
this.removeKeyboardCallbacks()
|
|
199
205
|
modalAttachedWatcher.disable()
|
|
200
206
|
}
|
|
@@ -6,6 +6,7 @@ import android.graphics.PixelFormat
|
|
|
6
6
|
import android.view.MotionEvent
|
|
7
7
|
import android.view.View
|
|
8
8
|
import android.view.WindowManager
|
|
9
|
+
import android.view.accessibility.AccessibilityEvent
|
|
9
10
|
import com.facebook.react.bridge.UiThreadUtil
|
|
10
11
|
import com.facebook.react.bridge.WritableMap
|
|
11
12
|
import com.facebook.react.bridge.WritableNativeMap
|
|
@@ -84,6 +85,16 @@ class OverKeyboardHostView(
|
|
|
84
85
|
}
|
|
85
86
|
// endregion
|
|
86
87
|
|
|
88
|
+
// region Accessibility
|
|
89
|
+
override fun addChildrenForAccessibility(outChildren: ArrayList<View>) {
|
|
90
|
+
// Don’t let Android try to reach children that are not actual descendants
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Explicitly override this to prevent accessibility events being passed down to children
|
|
94
|
+
// Those will be handled by the `hostView` which lives in the `windowManager`
|
|
95
|
+
override fun dispatchPopulateAccessibilityEvent(event: AccessibilityEvent): Boolean = false
|
|
96
|
+
// endregion
|
|
97
|
+
|
|
87
98
|
fun show() {
|
|
88
99
|
val layoutParams =
|
|
89
100
|
WindowManager.LayoutParams(
|
package/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt
CHANGED
|
@@ -13,16 +13,21 @@ class KeyboardControllerViewManager(
|
|
|
13
13
|
) : ReactViewManager() {
|
|
14
14
|
private val manager = KeyboardControllerViewManagerImpl(mReactContext)
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// region Lifecycle
|
|
17
|
+
override fun createViewInstance(context: ThemedReactContext): ReactViewGroup = manager.createViewInstance(context)
|
|
17
18
|
|
|
18
|
-
override fun
|
|
19
|
-
|
|
19
|
+
override fun invalidate() {
|
|
20
|
+
super.invalidate()
|
|
21
|
+
manager.invalidate()
|
|
22
|
+
}
|
|
20
23
|
|
|
21
24
|
override fun onAfterUpdateTransaction(view: ReactViewGroup) {
|
|
22
25
|
super.onAfterUpdateTransaction(view)
|
|
23
26
|
manager.setEdgeToEdge(view as EdgeToEdgeReactViewGroup)
|
|
24
27
|
}
|
|
28
|
+
// endregion
|
|
25
29
|
|
|
30
|
+
// region Props setters
|
|
26
31
|
@ReactProp(name = "enabled")
|
|
27
32
|
fun setEnabled(
|
|
28
33
|
view: EdgeToEdgeReactViewGroup,
|
|
@@ -54,7 +59,12 @@ class KeyboardControllerViewManager(
|
|
|
54
59
|
) {
|
|
55
60
|
manager.setPreserveEdgeToEdge(view, isPreservingEdgeToEdge)
|
|
56
61
|
}
|
|
62
|
+
// endregion
|
|
57
63
|
|
|
64
|
+
// region Getters
|
|
58
65
|
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
|
|
59
66
|
manager.getExportedCustomDirectEventTypeConstants()
|
|
67
|
+
|
|
68
|
+
override fun getName(): String = KeyboardControllerViewManagerImpl.NAME
|
|
69
|
+
// endregion
|
|
60
70
|
}
|
|
@@ -119,6 +119,8 @@ RCT_EXPORT_METHOD(setFocusTo : (nonnull NSString *)direction)
|
|
|
119
119
|
@"KeyboardController::keyboardDidHide",
|
|
120
120
|
// focused input
|
|
121
121
|
@"KeyboardController::focusDidSet",
|
|
122
|
+
// window dimensions
|
|
123
|
+
@"KeyboardController::windowDidResize",
|
|
122
124
|
];
|
|
123
125
|
}
|
|
124
126
|
|
|
@@ -8,29 +8,64 @@
|
|
|
8
8
|
import Foundation
|
|
9
9
|
import UIKit
|
|
10
10
|
|
|
11
|
+
private var pendingBecomeResponder: TextInput?
|
|
11
12
|
private var originalResignFirstResponder: IMP?
|
|
13
|
+
private var originalBecomeFirstResponder: IMP?
|
|
12
14
|
|
|
13
15
|
@objc
|
|
14
16
|
extension UIResponder {
|
|
17
|
+
public static func swizzleBecomeFirstResponder() {
|
|
18
|
+
let originalBecomeSelector = #selector(becomeFirstResponder)
|
|
19
|
+
guard
|
|
20
|
+
let originalBecomeMethod = class_getInstanceMethod(UIResponder.self, originalBecomeSelector)
|
|
21
|
+
else {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
originalBecomeFirstResponder = method_getImplementation(originalBecomeMethod)
|
|
26
|
+
|
|
27
|
+
let swizzledBecomeImplementation: @convention(block) (UIResponder) -> Bool = { (self) in
|
|
28
|
+
pendingBecomeResponder = self as? TextInput
|
|
29
|
+
|
|
30
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + UIUtils.nextFrame) {
|
|
31
|
+
pendingBecomeResponder = nil
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return self.callOriginalBecomeFirstResponder(originalBecomeSelector)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let implementation = imp_implementationWithBlock(swizzledBecomeImplementation)
|
|
38
|
+
method_setImplementation(originalBecomeMethod, implementation)
|
|
39
|
+
}
|
|
40
|
+
|
|
15
41
|
public static func swizzleResignFirstResponder() {
|
|
16
|
-
let
|
|
42
|
+
let originalResignSelector = #selector(resignFirstResponder)
|
|
17
43
|
|
|
18
|
-
guard
|
|
44
|
+
guard
|
|
45
|
+
let originalResignMethod = class_getInstanceMethod(UIResponder.self, originalResignSelector)
|
|
46
|
+
else {
|
|
19
47
|
return
|
|
20
48
|
}
|
|
21
49
|
|
|
22
|
-
originalResignFirstResponder = method_getImplementation(
|
|
50
|
+
originalResignFirstResponder = method_getImplementation(originalResignMethod)
|
|
23
51
|
|
|
24
|
-
let
|
|
52
|
+
let swizzledResignImplementation: @convention(block) (UIResponder) -> Bool = { (self) in
|
|
25
53
|
// Check the type of responder
|
|
26
54
|
if let textField = self as? TextInput {
|
|
27
55
|
// check inputAccessoryView and call original method immediately if not InvisibleInputAccessoryView
|
|
28
56
|
if !(textField.inputAccessoryView is InvisibleInputAccessoryView) {
|
|
29
|
-
return self.callOriginalResignFirstResponder(
|
|
57
|
+
return self.callOriginalResignFirstResponder(originalResignSelector)
|
|
58
|
+
} else if pendingBecomeResponder != nil {
|
|
59
|
+
// if we already have a new focus request
|
|
60
|
+
pendingBecomeResponder = nil
|
|
61
|
+
KeyboardAreaExtender.shared.hide()
|
|
62
|
+
(self as? TextInput)?.inputAccessoryView = nil
|
|
63
|
+
KeyboardAreaExtender.shared.remove()
|
|
64
|
+
return self.callOriginalResignFirstResponder(originalResignSelector)
|
|
30
65
|
}
|
|
31
66
|
} else {
|
|
32
67
|
// If casting to TextInput fails
|
|
33
|
-
return self.callOriginalResignFirstResponder(
|
|
68
|
+
return self.callOriginalResignFirstResponder(originalResignSelector)
|
|
34
69
|
}
|
|
35
70
|
|
|
36
71
|
KeyboardAreaExtender.shared.hide()
|
|
@@ -39,22 +74,34 @@ extension UIResponder {
|
|
|
39
74
|
DispatchQueue.main.asyncAfter(deadline: .now() + UIUtils.nextFrame) {
|
|
40
75
|
(self as? TextInput)?.inputAccessoryView = nil
|
|
41
76
|
KeyboardAreaExtender.shared.remove()
|
|
42
|
-
_ = self.callOriginalResignFirstResponder(
|
|
77
|
+
_ = self.callOriginalResignFirstResponder(originalResignSelector)
|
|
43
78
|
}
|
|
44
79
|
|
|
45
80
|
// We need to return a value immediately, even though the actual action is delayed
|
|
46
81
|
return false
|
|
47
82
|
}
|
|
48
83
|
|
|
49
|
-
let implementation = imp_implementationWithBlock(
|
|
50
|
-
method_setImplementation(
|
|
84
|
+
let implementation = imp_implementationWithBlock(swizzledResignImplementation)
|
|
85
|
+
method_setImplementation(originalResignMethod, implementation)
|
|
51
86
|
}
|
|
52
87
|
|
|
53
88
|
private func callOriginalResignFirstResponder(_ selector: Selector) -> Bool {
|
|
54
89
|
guard let originalResignFirstResponder = originalResignFirstResponder else { return false }
|
|
55
90
|
typealias Function = @convention(c) (AnyObject, Selector) -> Bool
|
|
56
|
-
let castOriginalResignFirstResponder = unsafeBitCast(
|
|
91
|
+
let castOriginalResignFirstResponder = unsafeBitCast(
|
|
92
|
+
originalResignFirstResponder, to: Function.self
|
|
93
|
+
)
|
|
57
94
|
let result = castOriginalResignFirstResponder(self, selector)
|
|
58
95
|
return result
|
|
59
96
|
}
|
|
97
|
+
|
|
98
|
+
private func callOriginalBecomeFirstResponder(_ selector: Selector) -> Bool {
|
|
99
|
+
guard let originalBecomeFirstResponder = originalBecomeFirstResponder else { return false }
|
|
100
|
+
typealias Function = @convention(c) (AnyObject, Selector) -> Bool
|
|
101
|
+
let castOriginalBecomeFirstResponder = unsafeBitCast(
|
|
102
|
+
originalBecomeFirstResponder, to: Function.self
|
|
103
|
+
)
|
|
104
|
+
let result = castOriginalBecomeFirstResponder(self, selector)
|
|
105
|
+
return result
|
|
106
|
+
}
|
|
60
107
|
}
|
|
@@ -37,6 +37,8 @@ using namespace facebook::react;
|
|
|
37
37
|
@implementation KeyboardControllerView {
|
|
38
38
|
KeyboardMovementObserver *keyboardObserver;
|
|
39
39
|
FocusedInputObserver *inputObserver;
|
|
40
|
+
|
|
41
|
+
CGSize _lastScreenSize;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
@@ -211,6 +213,22 @@ using namespace facebook::react;
|
|
|
211
213
|
return self;
|
|
212
214
|
}
|
|
213
215
|
|
|
216
|
+
- (void)layoutSubviews
|
|
217
|
+
{
|
|
218
|
+
[super layoutSubviews];
|
|
219
|
+
|
|
220
|
+
CGSize screenSize = [UIScreen mainScreen].bounds.size;
|
|
221
|
+
if (CGSizeEqualToSize(screenSize, _lastScreenSize)) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
_lastScreenSize = screenSize;
|
|
226
|
+
|
|
227
|
+
NSDictionary *data = @{@"width" : @(screenSize.width), @"height" : @(screenSize.height)};
|
|
228
|
+
|
|
229
|
+
[KeyboardController.shared sendEvent:@"KeyboardController::windowDidResize" body:data];
|
|
230
|
+
}
|
|
231
|
+
|
|
214
232
|
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
215
233
|
{
|
|
216
234
|
const auto &oldViewProps = *std::static_pointer_cast<const KeyboardControllerViewProps>(_props);
|
|
@@ -15,6 +15,8 @@ class KeyboardControllerView: UIView {
|
|
|
15
15
|
private var inputObserver: FocusedInputObserver?
|
|
16
16
|
private var eventDispatcher: RCTEventDispatcherProtocol
|
|
17
17
|
private var bridge: RCTBridge
|
|
18
|
+
// internal state
|
|
19
|
+
private var lastScreenSize: CGSize = .zero
|
|
18
20
|
// react callbacks
|
|
19
21
|
/// keyboard
|
|
20
22
|
@objc var onKeyboardMoveStart: RCTDirectEventBlock?
|
|
@@ -83,6 +85,23 @@ class KeyboardControllerView: UIView {
|
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
|
|
88
|
+
override func layoutSubviews() {
|
|
89
|
+
super.layoutSubviews()
|
|
90
|
+
|
|
91
|
+
let screenSize = UIScreen.main.bounds.size
|
|
92
|
+
|
|
93
|
+
if lastScreenSize == screenSize {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
lastScreenSize = screenSize
|
|
98
|
+
|
|
99
|
+
var data = [AnyHashable: Any]()
|
|
100
|
+
data["width"] = screenSize.width
|
|
101
|
+
data["height"] = screenSize.height
|
|
102
|
+
onNotify(event: "KeyboardController::windowDidResize", data: data)
|
|
103
|
+
}
|
|
104
|
+
|
|
86
105
|
func onLayoutChanged(event: NSObject) {
|
|
87
106
|
guard isJSThreadReady() else { return }
|
|
88
107
|
|
|
@@ -80,11 +80,12 @@ const KeyboardAvoidingView = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
80
80
|
const translateY = interpolateToRelativeKeyboardHeight(translate.value);
|
|
81
81
|
const paddingBottom = interpolateToRelativeKeyboardHeight(padding.value);
|
|
82
82
|
const bottomHeight = enabled ? bottom : 0;
|
|
83
|
+
const height = frame.value.height - bottomHeight;
|
|
83
84
|
switch (behavior) {
|
|
84
85
|
case "height":
|
|
85
|
-
if (!keyboard.isClosed.value) {
|
|
86
|
+
if (!keyboard.isClosed.value && height > 0) {
|
|
86
87
|
return {
|
|
87
|
-
height
|
|
88
|
+
height,
|
|
88
89
|
flex: 0
|
|
89
90
|
};
|
|
90
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_hooks","_hooks2","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","_extends","assign","bind","arguments","length","apply","defaultLayout","x","y","width","height","KeyboardAvoidingView","forwardRef","behavior","children","contentContainerStyle","enabled","keyboardVerticalOffset","style","onLayout","onLayoutProps","props","ref","initialFrame","useSharedValue","frame","useDerivedValue","value","translate","padding","useTranslateAnimation","keyboard","useKeyboardAnimation","screenHeight","useWindowDimensions","relativeKeyboardHeight","useCallback","keyboardY","heightWhenOpened","Math","max","interpolateToRelativeKeyboardHeight","interpolate","onLayoutWorklet","layout","isClosed","runOnUI","nativeEvent","animatedStyle","useAnimatedStyle","bottom","progress","translateY","paddingBottom","bottomHeight","flex","paddingTop","transform","isPositionBehavior","containerStyle","combinedStyles","useMemo","createElement","View","_default","exports"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport Reanimated, {\n interpolate,\n runOnUI,\n useAnimatedStyle,\n useDerivedValue,\n useSharedValue,\n} from \"react-native-reanimated\";\n\nimport { useWindowDimensions } from \"../../hooks\";\n\nimport { useKeyboardAnimation, useTranslateAnimation } from \"./hooks\";\n\nimport type { LayoutRectangle, ViewProps } from \"react-native\";\n\nexport type KeyboardAvoidingViewBaseProps = {\n /**\n * Controls whether this `KeyboardAvoidingView` instance should take effect.\n * This is useful when more than one is on the screen. Defaults to true.\n */\n enabled?: boolean;\n\n /**\n * Distance between the top of the user screen and the React Native view. This\n * may be non-zero in some cases. Defaults to 0.\n */\n keyboardVerticalOffset?: number;\n} & ViewProps;\n\nexport type KeyboardAvoidingViewProps = KeyboardAvoidingViewBaseProps &\n (\n | {\n /**\n * Specify how to react to the presence of the keyboard.\n */\n behavior?: \"position\";\n\n /**\n * Style of the content container when `behavior` is 'position'.\n */\n contentContainerStyle?: ViewProps[\"style\"];\n }\n | {\n /**\n * Specify how to react to the presence of the keyboard.\n */\n behavior?: \"height\" | \"padding\" | \"translate-with-padding\";\n\n /**\n * `contentContainerStyle` is not allowed for these behaviors.\n */\n contentContainerStyle?: never;\n }\n );\n\nconst defaultLayout: LayoutRectangle = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n};\n\n/**\n * A View component that automatically adjusts its height, position, or bottom padding\n * when the keyboard appears to ensure that the content remains visible.\n *\n * @returns A View component that adjusts to keyboard visibility.\n * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view|Documentation} page for more details.\n * @example\n * ```tsx\n * <KeyboardAvoidingView behavior=\"padding\">\n * <TextInput />\n * </KeyboardAvoidingView>\n * ```\n */\nconst KeyboardAvoidingView = forwardRef<\n View,\n React.PropsWithChildren<KeyboardAvoidingViewProps>\n>(\n (\n {\n behavior,\n children,\n contentContainerStyle,\n enabled = true,\n keyboardVerticalOffset = 0,\n style,\n onLayout: onLayoutProps,\n ...props\n },\n ref,\n ) => {\n const initialFrame = useSharedValue<LayoutRectangle | null>(null);\n const frame = useDerivedValue(() => initialFrame.value || defaultLayout);\n\n const { translate, padding } = useTranslateAnimation();\n const keyboard = useKeyboardAnimation();\n const { height: screenHeight } = useWindowDimensions();\n\n const relativeKeyboardHeight = useCallback(() => {\n \"worklet\";\n\n const keyboardY =\n screenHeight - keyboard.heightWhenOpened.value - keyboardVerticalOffset;\n\n return Math.max(frame.value.y + frame.value.height - keyboardY, 0);\n }, [screenHeight, keyboardVerticalOffset]);\n const interpolateToRelativeKeyboardHeight = useCallback(\n (value: number) => {\n \"worklet\";\n\n return interpolate(value, [0, 1], [0, relativeKeyboardHeight()]);\n },\n [relativeKeyboardHeight],\n );\n\n const onLayoutWorklet = useCallback(\n (layout: LayoutRectangle) => {\n \"worklet\";\n\n if (\n keyboard.isClosed.value ||\n initialFrame.value === null ||\n behavior !== \"height\"\n ) {\n // eslint-disable-next-line react-compiler/react-compiler\n initialFrame.value = layout;\n }\n },\n [behavior],\n );\n const onLayout = useCallback<NonNullable<ViewProps[\"onLayout\"]>>(\n (e) => {\n runOnUI(onLayoutWorklet)(e.nativeEvent.layout);\n onLayoutProps?.(e);\n },\n [onLayoutProps],\n );\n\n const animatedStyle = useAnimatedStyle(() => {\n const bottom = interpolateToRelativeKeyboardHeight(\n keyboard.progress.value,\n );\n const translateY = interpolateToRelativeKeyboardHeight(translate.value);\n const paddingBottom = interpolateToRelativeKeyboardHeight(padding.value);\n const bottomHeight = enabled ? bottom : 0;\n\n switch (behavior) {\n case \"height\":\n if (!keyboard.isClosed.value) {\n return {\n height: frame.value.height - bottomHeight,\n flex: 0,\n };\n }\n\n return {};\n\n case \"position\":\n return { bottom: bottomHeight };\n\n case \"padding\":\n return { paddingBottom: bottomHeight };\n\n case \"translate-with-padding\":\n return {\n paddingTop: paddingBottom,\n transform: [{ translateY: -translateY }],\n };\n\n default:\n return {};\n }\n }, [behavior, enabled, interpolateToRelativeKeyboardHeight]);\n const isPositionBehavior = behavior === \"position\";\n const containerStyle = isPositionBehavior ? contentContainerStyle : style;\n const combinedStyles = useMemo(\n () => [containerStyle, animatedStyle],\n [containerStyle, animatedStyle],\n );\n\n if (isPositionBehavior) {\n return (\n <View ref={ref} style={style} onLayout={onLayout} {...props}>\n <Reanimated.View style={combinedStyles}>{children}</Reanimated.View>\n </View>\n );\n }\n\n return (\n <Reanimated.View\n ref={ref}\n style={combinedStyles}\n onLayout={onLayout}\n {...props}\n >\n {children}\n </Reanimated.View>\n );\n },\n);\n\nexport default KeyboardAvoidingView;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_hooks","_hooks2","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","_extends","assign","bind","arguments","length","apply","defaultLayout","x","y","width","height","KeyboardAvoidingView","forwardRef","behavior","children","contentContainerStyle","enabled","keyboardVerticalOffset","style","onLayout","onLayoutProps","props","ref","initialFrame","useSharedValue","frame","useDerivedValue","value","translate","padding","useTranslateAnimation","keyboard","useKeyboardAnimation","screenHeight","useWindowDimensions","relativeKeyboardHeight","useCallback","keyboardY","heightWhenOpened","Math","max","interpolateToRelativeKeyboardHeight","interpolate","onLayoutWorklet","layout","isClosed","runOnUI","nativeEvent","animatedStyle","useAnimatedStyle","bottom","progress","translateY","paddingBottom","bottomHeight","flex","paddingTop","transform","isPositionBehavior","containerStyle","combinedStyles","useMemo","createElement","View","_default","exports"],"sources":["index.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport Reanimated, {\n interpolate,\n runOnUI,\n useAnimatedStyle,\n useDerivedValue,\n useSharedValue,\n} from \"react-native-reanimated\";\n\nimport { useWindowDimensions } from \"../../hooks\";\n\nimport { useKeyboardAnimation, useTranslateAnimation } from \"./hooks\";\n\nimport type { LayoutRectangle, ViewProps } from \"react-native\";\n\nexport type KeyboardAvoidingViewBaseProps = {\n /**\n * Controls whether this `KeyboardAvoidingView` instance should take effect.\n * This is useful when more than one is on the screen. Defaults to true.\n */\n enabled?: boolean;\n\n /**\n * Distance between the top of the user screen and the React Native view. This\n * may be non-zero in some cases. Defaults to 0.\n */\n keyboardVerticalOffset?: number;\n} & ViewProps;\n\nexport type KeyboardAvoidingViewProps = KeyboardAvoidingViewBaseProps &\n (\n | {\n /**\n * Specify how to react to the presence of the keyboard.\n */\n behavior?: \"position\";\n\n /**\n * Style of the content container when `behavior` is 'position'.\n */\n contentContainerStyle?: ViewProps[\"style\"];\n }\n | {\n /**\n * Specify how to react to the presence of the keyboard.\n */\n behavior?: \"height\" | \"padding\" | \"translate-with-padding\";\n\n /**\n * `contentContainerStyle` is not allowed for these behaviors.\n */\n contentContainerStyle?: never;\n }\n );\n\nconst defaultLayout: LayoutRectangle = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n};\n\n/**\n * A View component that automatically adjusts its height, position, or bottom padding\n * when the keyboard appears to ensure that the content remains visible.\n *\n * @returns A View component that adjusts to keyboard visibility.\n * @see {@link https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-avoiding-view|Documentation} page for more details.\n * @example\n * ```tsx\n * <KeyboardAvoidingView behavior=\"padding\">\n * <TextInput />\n * </KeyboardAvoidingView>\n * ```\n */\nconst KeyboardAvoidingView = forwardRef<\n View,\n React.PropsWithChildren<KeyboardAvoidingViewProps>\n>(\n (\n {\n behavior,\n children,\n contentContainerStyle,\n enabled = true,\n keyboardVerticalOffset = 0,\n style,\n onLayout: onLayoutProps,\n ...props\n },\n ref,\n ) => {\n const initialFrame = useSharedValue<LayoutRectangle | null>(null);\n const frame = useDerivedValue(() => initialFrame.value || defaultLayout);\n\n const { translate, padding } = useTranslateAnimation();\n const keyboard = useKeyboardAnimation();\n const { height: screenHeight } = useWindowDimensions();\n\n const relativeKeyboardHeight = useCallback(() => {\n \"worklet\";\n\n const keyboardY =\n screenHeight - keyboard.heightWhenOpened.value - keyboardVerticalOffset;\n\n return Math.max(frame.value.y + frame.value.height - keyboardY, 0);\n }, [screenHeight, keyboardVerticalOffset]);\n const interpolateToRelativeKeyboardHeight = useCallback(\n (value: number) => {\n \"worklet\";\n\n return interpolate(value, [0, 1], [0, relativeKeyboardHeight()]);\n },\n [relativeKeyboardHeight],\n );\n\n const onLayoutWorklet = useCallback(\n (layout: LayoutRectangle) => {\n \"worklet\";\n\n if (\n keyboard.isClosed.value ||\n initialFrame.value === null ||\n behavior !== \"height\"\n ) {\n // eslint-disable-next-line react-compiler/react-compiler\n initialFrame.value = layout;\n }\n },\n [behavior],\n );\n const onLayout = useCallback<NonNullable<ViewProps[\"onLayout\"]>>(\n (e) => {\n runOnUI(onLayoutWorklet)(e.nativeEvent.layout);\n onLayoutProps?.(e);\n },\n [onLayoutProps],\n );\n\n const animatedStyle = useAnimatedStyle(() => {\n const bottom = interpolateToRelativeKeyboardHeight(\n keyboard.progress.value,\n );\n const translateY = interpolateToRelativeKeyboardHeight(translate.value);\n const paddingBottom = interpolateToRelativeKeyboardHeight(padding.value);\n const bottomHeight = enabled ? bottom : 0;\n const height = frame.value.height - bottomHeight;\n\n switch (behavior) {\n case \"height\":\n if (!keyboard.isClosed.value && height > 0) {\n return {\n height,\n flex: 0,\n };\n }\n\n return {};\n\n case \"position\":\n return { bottom: bottomHeight };\n\n case \"padding\":\n return { paddingBottom: bottomHeight };\n\n case \"translate-with-padding\":\n return {\n paddingTop: paddingBottom,\n transform: [{ translateY: -translateY }],\n };\n\n default:\n return {};\n }\n }, [behavior, enabled, interpolateToRelativeKeyboardHeight]);\n const isPositionBehavior = behavior === \"position\";\n const containerStyle = isPositionBehavior ? contentContainerStyle : style;\n const combinedStyles = useMemo(\n () => [containerStyle, animatedStyle],\n [containerStyle, animatedStyle],\n );\n\n if (isPositionBehavior) {\n return (\n <View ref={ref} style={style} onLayout={onLayout} {...props}>\n <Reanimated.View style={combinedStyles}>{children}</Reanimated.View>\n </View>\n );\n }\n\n return (\n <Reanimated.View\n ref={ref}\n style={combinedStyles}\n onLayout={onLayout}\n {...props}\n >\n {children}\n </Reanimated.View>\n );\n },\n);\n\nexport default KeyboardAvoidingView;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -249,6 +249,9 @@ const KeyboardAwareScrollView = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
249
249
|
syncKeyboardFrame(e);
|
|
250
250
|
}
|
|
251
251
|
}, [maybeScroll, disableScrollOnKeyboardHide, syncKeyboardFrame]);
|
|
252
|
+
(0, _react.useEffect)(() => {
|
|
253
|
+
(0, _reactNativeReanimated.runOnUI)(maybeScroll)(keyboardHeight.value, true);
|
|
254
|
+
}, [bottomOffset]);
|
|
252
255
|
(0, _reactNativeReanimated.useAnimatedReaction)(() => input.value, (current, previous) => {
|
|
253
256
|
if ((current === null || current === void 0 ? void 0 : current.target) === (previous === null || previous === void 0 ? void 0 : previous.target) && (current === null || current === void 0 ? void 0 : current.layout.height) !== (previous === null || previous === void 0 ? void 0 : previous.layout.height)) {
|
|
254
257
|
const prevLayout = layout.value;
|