Skip to content

Commit 25a2c60

Browse files
mrbrentkellyfacebook-github-bot
authored andcommitted
Addressing various issues with the Appearance API (#28823) (#29106)
Summary: This PR fixes a few issues with the Appearance API (as noted here #28823). 1. For the Appearance API to work correctly on Android you need to call `AppearanceModule.onConfigurationChanged` when the current Activity goes through a configuration change. This was being called in the RNTester app but not in `ReactActivity` so it meant the Appearance API wouldn't work for Android in newly generated RN projects (or ones upgraded to the latest version of RN). 2. The Appearance API wasn't working correctly for brownfield scenarios on Android. It's possible to force an app light or dark natively on Android by calling `AppCompatDelegate.setDefaultNightMode()`. The Appearance API wasn't picking up changes from this function because it was using the Application context instead of the current Activity context. 3. The Appearance API wasn't working correctly for brownfield scenarios on iOS. Just like on Android its possible to force an app light or dark natively by setting `window.overrideUserInterfaceStyle`. The Appearance API didn't work with this override because we were overwriting `_currentColorScheme` back to default as soon as we set it. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> ### Fixed #28823 * [Android] [Fixed] - Appearance API now works on Android * [Android] [Fixed] - Appearance API now works correctly when calling `AppCompatDelegate.setDefaultNightMode()` * [iOS] [Fixed] - Appearance API now works correctly when setting `window.overrideUserInterfaceStyle` Pull Request resolved: #29106 Test Plan: Ran RNTester on iOS and Android and verified the Appearance examples still worked [correctly.](url) Reviewed By: hramos Differential Revision: D31284331 Pulled By: sota000 fbshipit-source-id: 45bbe33983e506eb177d596d33ddf15f846708fd
1 parent 5280968 commit 25a2c60

File tree

5 files changed

+27
-14
lines changed

5 files changed

+27
-14
lines changed

React/CoreModules/RCTAppearance.mm

+3-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ - (dispatch_queue_t)methodQueue
8989

9090
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, getColorScheme)
9191
{
92-
_currentColorScheme = RCTColorSchemePreference(nil);
92+
if (_currentColorScheme == nil) {
93+
_currentColorScheme = RCTColorSchemePreference(nil);
94+
}
9395
return _currentColorScheme;
9496
}
9597

ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package com.facebook.react;
99

1010
import android.content.Intent;
11+
import android.content.res.Configuration;
1112
import android.os.Bundle;
1213
import android.view.KeyEvent;
1314
import androidx.annotation.Nullable;
@@ -121,6 +122,12 @@ public void onWindowFocusChanged(boolean hasFocus) {
121122
mDelegate.onWindowFocusChanged(hasFocus);
122123
}
123124

125+
@Override
126+
public void onConfigurationChanged(Configuration newConfig) {
127+
super.onConfigurationChanged(newConfig);
128+
mDelegate.onConfigurationChanged(newConfig);
129+
}
130+
124131
protected final ReactNativeHost getReactNativeHost() {
125132
return mDelegate.getReactNativeHost();
126133
}

ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java

+7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import android.app.Activity;
1212
import android.content.Context;
1313
import android.content.Intent;
14+
import android.content.res.Configuration;
1415
import android.os.Build;
1516
import android.os.Bundle;
1617
import android.view.KeyEvent;
@@ -154,6 +155,12 @@ public void onWindowFocusChanged(boolean hasFocus) {
154155
}
155156
}
156157

158+
public void onConfigurationChanged(Configuration newConfig) {
159+
if (getReactNativeHost().hasInstance()) {
160+
getReactInstanceManager().onConfigurationChanged(getContext(), newConfig);
161+
}
162+
}
163+
157164
@TargetApi(Build.VERSION_CODES.M)
158165
public void requestPermissions(
159166
String[] permissions, int requestCode, PermissionListener listener) {

ReactAndroid/src/main/java/com/facebook/react/modules/appearance/AppearanceModule.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
package com.facebook.react.modules.appearance;
99

10+
import android.app.Activity;
1011
import android.content.Context;
1112
import android.content.res.Configuration;
1213
import androidx.annotation.Nullable;
@@ -74,7 +75,15 @@ public String getName() {
7475

7576
@Override
7677
public String getColorScheme() {
77-
mColorScheme = colorSchemeForCurrentConfiguration(getReactApplicationContext());
78+
// Attempt to use the Activity context first in order to get the most up to date
79+
// scheme. This covers the scenario when AppCompatDelegate.setDefaultNightMode()
80+
// is called directly (which can occur in Brownfield apps for example).
81+
Activity activity = getCurrentActivity();
82+
83+
mColorScheme =
84+
colorSchemeForCurrentConfiguration(
85+
activity != null ? activity : getReactApplicationContext());
86+
7887
return mColorScheme;
7988
}
8089

packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterActivity.java

-12
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@
77

88
package com.facebook.react.uiapp;
99

10-
import android.content.res.Configuration;
1110
import android.os.Bundle;
1211
import androidx.annotation.Nullable;
1312
import com.facebook.react.ReactActivity;
1413
import com.facebook.react.ReactActivityDelegate;
15-
import com.facebook.react.ReactInstanceManager;
1614
import com.facebook.react.ReactRootView;
1715

1816
public class RNTesterActivity extends ReactActivity {
@@ -64,14 +62,4 @@ protected ReactActivityDelegate createReactActivityDelegate() {
6462
protected String getMainComponentName() {
6563
return "RNTesterApp";
6664
}
67-
68-
@Override
69-
public void onConfigurationChanged(Configuration newConfig) {
70-
super.onConfigurationChanged(newConfig);
71-
ReactInstanceManager instanceManager = getReactInstanceManager();
72-
73-
if (instanceManager != null) {
74-
instanceManager.onConfigurationChanged(this, newConfig);
75-
}
76-
}
7765
}

0 commit comments

Comments
 (0)