From 323971e397ed08a34e18bfce0ba52294137d7b8b Mon Sep 17 00:00:00 2001 From: Peter Abbondanzo Date: Thu, 23 May 2024 06:11:03 -0700 Subject: [PATCH] [skip ci] Migration RN Alert Dialog to androidx (#44494) Summary: Migrates the `AlertFragment` from `android.app.AlertDialog` to `androidx.appcompat.app.AlertDialog`. This backports tons of fixes that have gone into the AlertDialog component over the years, including proper line wrapping of button text, alignment of buttons, etc. ## For consideration - Alert dialog themes may no longer need the `android` namespace, meaning themes can now be specified as `alertDialogTheme` rather than `android:alertDialogTheme`. - This change requires all implementing activities to have a theme that inherits from `Theme.AppCompat`. Creation of any activities which do not have a descendant of this style will result in an `IllegalStateException`: https://www.internalfb.com/intern/signalinfra/exception_owners/?mid=5ee93f6ecd59f3d8ad82a78c213ea016&result_id=16044073705339118.281475102518721.1715097866 ## Changelog: [Android] [Changed] - Migrated `AlertFragment` dialog builder to use `androidx.appcompat` Reviewed By: zeyap Differential Revision: D57019423 --- .../react/modules/dialog/AlertFragment.java | 2 +- .../react/modules/dialog/DialogModuleTest.kt | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/AlertFragment.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/AlertFragment.java index 8bc0481f686946..4e81931ccabaf7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/AlertFragment.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/AlertFragment.java @@ -8,12 +8,12 @@ package com.facebook.react.modules.dialog; import android.annotation.SuppressLint; -import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; /** A fragment used to display the dialog. */ diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/dialog/DialogModuleTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/dialog/DialogModuleTest.kt index dda9e82c14b2b7..1a1c90fe82a961 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/dialog/DialogModuleTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/dialog/DialogModuleTest.kt @@ -7,10 +7,11 @@ package com.facebook.react.modules.dialog -import android.app.AlertDialog import android.content.DialogInterface import android.os.Looper.getMainLooper +import androidx.appcompat.app.AlertDialog import androidx.fragment.app.FragmentActivity +import com.facebook.react.R import com.facebook.react.bridge.Callback import com.facebook.react.bridge.JavaOnlyMap import com.facebook.react.bridge.ReactApplicationContext @@ -48,6 +49,9 @@ class DialogModuleTest { fun setUp() { activityController = Robolectric.buildActivity(FragmentActivity::class.java) activity = activityController.create().start().resume().get() + // We must set the theme to a descendant of AppCompat for the AlertDialog to show without + // raising an exception + activity.setTheme(APP_COMPAT_THEME) val context: ReactApplicationContext = mock(ReactApplicationContext::class.java) whenever(context.hasActiveReactInstance()).thenReturn(true) @@ -62,6 +66,16 @@ class DialogModuleTest { activityController.pause().stop().destroy() } + @Test + fun testIllegalActivityTheme() { + val options = JavaOnlyMap() + activity.setTheme(NON_APP_COMPAT_THEME) + + assertThrows(NullPointerException::class.java) { dialogModule.showAlert(options, null, null) } + + activity.setTheme(APP_COMPAT_THEME) + } + @Test fun testAllOptions() { val options = @@ -158,4 +172,9 @@ class DialogModuleTest { return activity.supportFragmentManager.findFragmentByTag(DialogModule.FRAGMENT_TAG) as? AlertFragment } + + companion object { + private val APP_COMPAT_THEME: Int = R.style.Theme_ReactNative_AppCompat_Light + private val NON_APP_COMPAT_THEME: Int = android.R.style.Theme_DeviceDefault_Light + } }