Skip to content

Commit 3029563

Browse files
committed
fix: modal conflicts
1 parent a45270f commit 3029563

File tree

3 files changed

+24
-17
lines changed

3 files changed

+24
-17
lines changed

android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class KeyboardAnimationCallback(
5050
val view: View,
5151
val context: ThemedReactContext?,
5252
private val config: KeyboardAnimationCallbackConfig,
53+
private val source: KeyboardAnimationCallback? = null,
5354
) : WindowInsetsAnimationCompat.Callback(config.dispatchMode),
5455
OnApplyWindowInsetsListener,
5556
Suspendable {
@@ -67,6 +68,13 @@ class KeyboardAnimationCallback(
6768
get() = duration == -1
6869
override var isSuspended: Boolean = false
6970

71+
init {
72+
if (source != null) {
73+
this.persistentKeyboardHeight = source.persistentKeyboardHeight
74+
this.prevKeyboardHeight = source.prevKeyboardHeight
75+
}
76+
}
77+
7078
// listeners
7179
private val focusListener =
7280
OnGlobalFocusChangeListener { oldFocus, newFocus ->
@@ -165,13 +173,13 @@ class KeyboardAnimationCallback(
165173
return insets
166174
}
167175

168-
// always verify insets, because sometimes default lifecycles may not be invoked
169-
// (when we press "Share" on Android 16, for example)
176+
// always verify insets, because sometimes default lifecycle methods may not be invoked
177+
// (when we press "Share" on Android 16, when Modal closes keyboard, etc.)
170178
val newHeight = getCurrentKeyboardHeight(insets)
171-
if (prevKeyboardHeight != newHeight && !isTransitioning) {
179+
if (prevKeyboardHeight != newHeight && !isMoving && !isSuspended) {
172180
Logger.w(
173181
TAG,
174-
"detected desynchronized state - force updating it. $prevKeyboardHeight -> $newHeight"
182+
"detected desynchronized state - force updating it. $prevKeyboardHeight -> $newHeight. Modal ${this.source}",
175183
)
176184
this.syncKeyboardPosition(newHeight, newHeight > 0)
177185
}

android/src/main/java/com/reactnativekeyboardcontroller/modal/ModalAttachedWatcher.kt

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ModalAttachedWatcher(
3535
return
3636
}
3737

38+
val cb = this.callback()
3839
val modal =
3940
try {
4041
uiManager?.resolveView(event.viewTag) as? ReactModalHostView
@@ -46,6 +47,9 @@ class ModalAttachedWatcher(
4647
if (modal == null) {
4748
return
4849
}
50+
if (cb == null) {
51+
return
52+
}
4953

5054
val dialog = modal.dialog
5155
val window = dialog?.window
@@ -62,6 +66,7 @@ class ModalAttachedWatcher(
6266
eventPropagationView = view,
6367
context = reactContext,
6468
config = config,
69+
source = cb,
6570
)
6671

6772
rootView.addView(eventView)
@@ -70,28 +75,21 @@ class ModalAttachedWatcher(
7075
// on Android < 12 all events for `WindowInsetsAnimationCallback`
7176
// go through main `rootView`, so we don't need to stop main
7277
// callback - otherwise keyboard transitions will not be animated
73-
this.callback()?.suspend(true)
78+
cb.suspend(true)
7479
// attaching callback to Modal on Android < 12 can cause ghost animations, see: https://github.com/kirillzyusko/react-native-keyboard-controller/pull/718
7580
// and overall attaching additional callbacks (if animation events go through the main window) is not necessary
7681
ViewCompat.setWindowInsetsAnimationCallback(rootView, callback)
7782
ViewCompat.setOnApplyWindowInsetsListener(eventView, callback)
78-
79-
// when modal is shown then keyboard will be hidden by default
80-
//
81-
// - if events are coming from main window - then keyboard position
82-
// will be synchronized from main window callback
83-
// - if events are coming from modal window - then we need to update
84-
// position ourself, because callback can be attached after keyboard
85-
// auto-dismissal and we may miss some events and keyboard position
86-
// will be outdated
87-
callback.syncKeyboardPosition(0.0, false)
8883
}
8984

9085
dialog?.setOnDismissListener {
9186
callback.syncKeyboardPosition()
9287
callback.destroy()
9388
eventView.removeSelf()
94-
this.callback()?.suspend(false)
89+
// un-pause it in next frame because straight away `onApplyWindowInsets` will be called
90+
view.post {
91+
this.callback()?.suspend(false)
92+
}
9593
}
9694

9795
// imitating edge-to-edge mode behavior

cspell.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@
170170
"Pixelfed",
171171
"Kwai",
172172
"Kwibo",
173-
"revolut"
173+
"revolut",
174+
"desynchronized"
174175
],
175176
"ignorePaths": [
176177
"node_modules",

0 commit comments

Comments
 (0)