Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified android/react_viro/react_viro-release.aar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@

package com.viromedia.bridge;

import android.util.Log;
import android.app.Activity;
import android.content.res.TypedArray;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
Expand Down Expand Up @@ -126,7 +128,7 @@ public ReactViroPackage(ViroPlatform platform) {

@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
Log.e("Manish", "createNativeModules");
installMaterial3AlertTheme(reactContext);
List<NativeModule> modules = new java.util.ArrayList<>(Arrays.<NativeModule>asList(
new MaterialManager(reactContext),
new AnimationManager(reactContext),
Expand All @@ -153,6 +155,46 @@ public List<NativeModule> createNativeModules(ReactApplicationContext reactConte
return modules;
}

// RN's Alert builds an AppCompat dialog styled by the host activity theme,
// where the RN/Expo template parent (Theme.AppCompat) means Material 2. Overlay
// just alertDialogTheme with viro's Material 3-styled dialog theme. Runs on
// every host resume: addLifecycleEventListener dispatches immediately when the
// host is already resumed, and re-applying covers activity recreation.
private void installMaterial3AlertTheme(final ReactApplicationContext reactContext) {
reactContext.addLifecycleEventListener(new LifecycleEventListener() {
@Override
public void onHostResume() {
Activity activity = reactContext.getCurrentActivity();
if (activity != null && isAppCompatTheme(activity)) {
activity.getTheme().applyStyle(R.style.ViroAlertDialogThemeOverride, true);
}
}

@Override
public void onHostPause() {
}

@Override
public void onHostDestroy() {
}
});
}

// The probe RN's AlertFragment uses to pick the AppCompat dialog path. In a
// brownfield host whose activity theme is not AppCompat-derived, RN shows a
// framework dialog instead, and the override must not reach it: the dialog
// background resolves ?attr/colorBackgroundFloating, which only AppCompat
// themes define — inflating it there crashes at alert-show time.
private static boolean isAppCompatTheme(Activity activity) {
TypedArray attributes =
activity.obtainStyledAttributes(androidx.appcompat.R.styleable.AppCompatTheme);
try {
return attributes.hasValue(androidx.appcompat.R.styleable.AppCompatTheme_windowActionBar);
} finally {
attributes.recycle();
}
}

@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- AppCompat's abc_dialog_material_background with its hardcoded white swapped for
colorBackgroundFloating, which AppCompat guarantees and already resolves per
light/dark, so this needs no values-night variant. Insets are 10dp to match
MaterialAlertDialog's background insets rather than AppCompat's 16dp. -->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="10dp"
android:insetTop="10dp"
android:insetRight="10dp"
android:insetBottom="10dp">
<shape android:shape="rectangle">
<corners android:radius="?attr/dialogCornerRadius" />
<solid android:color="?attr/colorBackgroundFloating" />
</shape>
</inset>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>

<!-- Night twin of ViroAlertDialogTheme (values/): identical except colorAccent is
left at AppCompat's night default (teal 200) — see the day version for why.
Keep the item lists in sync. -->
<style name="ViroAlertDialogTheme" parent="ThemeOverlay.AppCompat.Dialog.Alert">
<item name="dialogCornerRadius">28dp</item>
<item name="android:windowBackground">@drawable/viro_alert_dialog_background</item>
<item name="buttonBarButtonStyle">@style/ViroAlertDialogButton</item>
<item name="android:buttonBarButtonStyle">@style/ViroAlertDialogButton</item>
</style>

</resources>
41 changes: 41 additions & 0 deletions android/viro_bridge/src/main/res/values/viro_alert_dialog.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>

<!-- Applied onto the host activity theme at runtime (see ReactViroPackage);
overrides only the alert dialog theme, nothing else in the app. -->
<style name="ViroAlertDialogThemeOverride" parent="">
<item name="alertDialogTheme">@style/ViroAlertDialogTheme</item>
<item name="android:alertDialogTheme">@style/ViroAlertDialogTheme</item>
</style>

<!-- M3 shape and button treatment only; all colors stay inherited from the host
theme. Google's ThemeOverlay.Material3.Dialog.Alert is deliberately not the
parent: its whole chain supplies just buttonBarButtonStyle and windowElevation
(no shape, no dialogCornerRadius), so it would leave AppCompat's 2dp corners.
The M3 shape lives in ThemeOverlay.Material3.MaterialAlertDialog, which needs
both a Material3 host theme and the material library — and react_viro ships as
a bare AAR propagating no dependencies, so neither can be assumed. -->
<style name="ViroAlertDialogTheme" parent="ThemeOverlay.AppCompat.Dialog.Alert">
<item name="dialogCornerRadius">28dp</item>
<item name="android:windowBackground">@drawable/viro_alert_dialog_background</item>
<!-- Buttons read colorAccent, which templates rarely set (AppCompat teal by
default); follow the app's brand colorPrimary instead. Day only — the
values-night twin keeps AppCompat's night accent, because colorPrimary
rarely has a night variant and dark brand colors are unreadable on the
dark dialog surface. -->
<item name="colorAccent">?attr/colorPrimary</item>
<item name="buttonBarButtonStyle">@style/ViroAlertDialogButton</item>
<item name="android:buttonBarButtonStyle">@style/ViroAlertDialogButton</item>
</style>

<!-- M3 label-large. textAllCaps has to be a direct attribute here: it is forced
true by Base.TextAppearance.AppCompat.Button, which a textAppearance-level
override would not beat. Text color is left alone so it follows colorAccent. -->
<style name="ViroAlertDialogButton" parent="Widget.AppCompat.Button.Borderless.Colored">
<item name="android:textAllCaps">false</item>
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:letterSpacing">0.007</item>
</style>

</resources>