From 389884606a6faf5827a2bad0daffc3bf643e87cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateo=20Guzm=C3=A1n?= Date: Sun, 15 Dec 2024 22:53:43 +0100 Subject: [PATCH 1/2] feat(modal): [android] setting resource-id from testID --- .../modal/ModalHostAccessibilityDelegate.kt | 25 +++++++++++++++++++ .../views/modal/ReactModalHostManager.kt | 6 +++++ .../react/views/modal/ReactModalHostView.kt | 11 ++++++++ 3 files changed, 42 insertions(+) create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostAccessibilityDelegate.kt diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostAccessibilityDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostAccessibilityDelegate.kt new file mode 100644 index 00000000000000..9a3079ad61db04 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostAccessibilityDelegate.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.views.modal + +import android.view.View +import androidx.core.view.AccessibilityDelegateCompat +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat +import com.facebook.react.R + +internal class ModalHostAccessibilityDelegate : AccessibilityDelegateCompat() { + override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) { + super.onInitializeAccessibilityNodeInfo(host, info) + + val testId = host.getTag(R.id.react_test_id) as String? + + if (testId != null) { + info.viewIdResourceName = testId + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.kt index 88157aea50294c..ca12140191e0d6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostManager.kt @@ -93,6 +93,12 @@ public class ReactModalHostManager : @ReactProp(name = "identifier") public override fun setIdentifier(view: ReactModalHostView, value: Int): Unit = Unit + @ReactProp(name = "testID") + public override fun setTestId(view: ReactModalHostView, value: String?) { + super.setTestId(view, value) + view.setDialogRootViewGroupTestId(value) + } + protected override fun addEventEmitters( reactContext: ThemedReactContext, view: ReactModalHostView diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt index 271e00f425fca2..b418f4afabc2c4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt @@ -26,6 +26,7 @@ import android.view.WindowManager import android.view.accessibility.AccessibilityEvent import android.widget.FrameLayout import androidx.annotation.UiThread +import androidx.core.view.ViewCompat import com.facebook.common.logging.FLog import com.facebook.react.R import com.facebook.react.bridge.GuardedRunnable @@ -386,6 +387,15 @@ public class ReactModalHostView(context: ThemedReactContext) : } } + /** + * Sets the testID on the DialogRootViewGroup. Since the accessibility delegate + * does not work when set on the ReactModalHostView, the testID is forwarded + * to the DialogRootViewGroup to set the resource-id. + */ + public fun setDialogRootViewGroupTestId(testId: String?) { + dialogRootViewGroup.setTag(R.id.react_test_id, testId) + } + // This listener is called when the user presses KeyEvent.KEYCODE_BACK // An event is then passed to JS which can either close or not close the Modal by setting the // visible property @@ -425,6 +435,7 @@ public class ReactModalHostView(context: ThemedReactContext) : if (ReactFeatureFlags.dispatchPointerEvents) { jSPointerDispatcher = JSPointerDispatcher(this) } + ViewCompat.setAccessibilityDelegate(this, ModalHostAccessibilityDelegate()) } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { From 2f677e201ce29caea72265e6e955aa8e64f22ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateo=20Guzm=C3=A1n?= Date: Mon, 16 Dec 2024 00:08:20 +0100 Subject: [PATCH 2/2] refactor(modal): [android] simplifying approach to call onInitializeAccessibilityNodeInfo --- .../modal/ModalHostAccessibilityDelegate.kt | 25 ------------------- .../react/views/modal/ReactModalHostView.kt | 16 +++++++++--- 2 files changed, 12 insertions(+), 29 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostAccessibilityDelegate.kt diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostAccessibilityDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostAccessibilityDelegate.kt deleted file mode 100644 index 9a3079ad61db04..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostAccessibilityDelegate.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.views.modal - -import android.view.View -import androidx.core.view.AccessibilityDelegateCompat -import androidx.core.view.accessibility.AccessibilityNodeInfoCompat -import com.facebook.react.R - -internal class ModalHostAccessibilityDelegate : AccessibilityDelegateCompat() { - override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) { - super.onInitializeAccessibilityNodeInfo(host, info) - - val testId = host.getTag(R.id.react_test_id) as String? - - if (testId != null) { - info.viewIdResourceName = testId - } - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt index b418f4afabc2c4..8d093ae7ea3488 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt @@ -24,9 +24,9 @@ import android.view.Window import android.view.WindowInsetsController import android.view.WindowManager import android.view.accessibility.AccessibilityEvent +import android.view.accessibility.AccessibilityNodeInfo import android.widget.FrameLayout import androidx.annotation.UiThread -import androidx.core.view.ViewCompat import com.facebook.common.logging.FLog import com.facebook.react.R import com.facebook.react.bridge.GuardedRunnable @@ -388,8 +388,8 @@ public class ReactModalHostView(context: ThemedReactContext) : } /** - * Sets the testID on the DialogRootViewGroup. Since the accessibility delegate - * does not work when set on the ReactModalHostView, the testID is forwarded + * Sets the testID on the DialogRootViewGroup. Since the accessibility events + * are not triggered on the on the ReactModalHostView, the testID is forwarded * to the DialogRootViewGroup to set the resource-id. */ public fun setDialogRootViewGroupTestId(testId: String?) { @@ -435,7 +435,15 @@ public class ReactModalHostView(context: ThemedReactContext) : if (ReactFeatureFlags.dispatchPointerEvents) { jSPointerDispatcher = JSPointerDispatcher(this) } - ViewCompat.setAccessibilityDelegate(this, ModalHostAccessibilityDelegate()) + } + + override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo) { + super.onInitializeAccessibilityNodeInfo(info) + + val testId = getTag(R.id.react_test_id) as String? + if (testId != null) { + info.viewIdResourceName = testId + } } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {