Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Appearance module does not behave correctly: addChangeListener does not react to changes, useColorScheme() does not react to changes. #28823

Closed
sannajammeh opened this issue May 4, 2020 · 32 comments
Labels
Platform: Android Android applications. Resolution: Locked This issue was locked by the bot. Resolution: PR Submitted A pull request with a fix has been provided.

Comments

@sannajammeh
Copy link

sannajammeh commented May 4, 2020

Description

The subscription of useColorScheme() and Appearance.addChangeListener() wont work. The hook returns an initial value only on component mount. Changes to the devices color scheme on Android does not provide the hook with a new value. I therefore tried to manually replicate this hook with useEffect and the Appearance module and found that Appearance.addChangeListener() when called returns "undefined", not type EventSubscription. The listener function provided to Appearance.addChangeListener() never gets called.

I have only tested this on Android so I am not aware if this is also an issue on iOS.

React Native version:

System:
    OS: Windows 10 10.0.17763
    CPU: (16) x64 Intel(R) Core(TM) i7-5960X CPU @ 3.00GHz
    Memory: 15.05 GB / 31.92 GB
  Binaries:
    Node: 10.16.2 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.19.2 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 6.14.4 - C:\Program Files\nodejs\npm.CMD
    Watchman: Not Found
  SDKs:
    Android SDK:
      API Levels: 28, 29
      Build Tools: 28.0.3, 29.0.2, 29.0.3
      System Images: android-28 | Intel x86 Atom_64, android-R | Google APIs Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: Version  3.6.0.0 AI-192.7142.36.36.6308749
  Languages:
    Java: 1.8.0_211 - C:\Program Files\Java\jdk1.8.0_211\bin\javac.EXE
    Python: 2.7.18 - C:\Python27\python.EXE
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.11.0 => 16.11.0
    react-native: 0.62.2 => 0.62.2
  npmGlobalPackages:
    *react-native*: Not Found

Steps To Reproduce

Provide a detailed list of steps that reproduce the issue.

  1. run npx react-native init TestDark --template react-native-template-typescript
  2. Import Appearance & useColorScheme from 'react-native'
  3. copy paste the code snippet below above the return in <App /> or use the useColorScheme hook and console.log its output.
  4. Change the color scheme of the Android device and check the console for the correct values.

Expected Results

The useColorScheme hook should return the correct colorScheme when the devices colorScheme changes.
The Appearance.addChangeListener() should return type EventSubscription not undefined.
The listener callback provided to Appearance.addChangeListener(cb) should be called.

Snack, code example, screenshot, or link to a repository:

const App = () => {
  const colorScheme = useColorScheme(); // Only gives initial colorScheme, does not return new colorScheme on change.
  const [mode1, setMode1] = useState('light');
  const mode = colorScheme || 'light';

  React.useEffect(() => {
    const initialColorScheme = Appearance.getColorScheme(); // Works as expected
    setMode1(initialColorScheme || 'light');

    const listener = () => {
      console.log('called'); // Never fires
      const colorScheme1 = Appearance.getColorScheme();
      setMode1(colorScheme1 || 'light');
    };

    const subscription = Appearance.addChangeListener(listener);
    console.log('App -> subscription', subscription); // logs as undefined
    return () => {
      Appearance.removeChangeListener(listener);
    };
  }, []);
  return (
   // jsx
  )
}

Here is a GIF of the app created with npx react-native init NAME --template react-native-template-typescript command. Look for Mode: dark (useColorScheme() and Mode_1 (useEffect & Appearance module). https://gyazo.com/d4ddb35bf689b3c8926be2f613714f73

@sannajammeh sannajammeh changed the title Appearance module does not behave correctly, addChangeListener does not behave correctly. Appearance module does not behave correctly, addChangeListener does not behave correctly. useColorScheme() does not behave correctly. May 4, 2020
@sannajammeh sannajammeh changed the title Appearance module does not behave correctly, addChangeListener does not behave correctly. useColorScheme() does not behave correctly. Appearance module does not behave correctly: addChangeListener does not react to changes, useColorScheme() does not react to changes.. May 4, 2020
@sannajammeh sannajammeh changed the title Appearance module does not behave correctly: addChangeListener does not react to changes, useColorScheme() does not react to changes.. Appearance module does not behave correctly: addChangeListener does not react to changes, useColorScheme() does not react to changes. May 4, 2020
@elkinjosetm
Copy link

elkinjosetm commented May 12, 2020

Having the same issue here, but it works fine on iOS. For some reason the changeListener never gets called on Android when changing the system color scheme

@josmithua
Copy link

josmithua commented May 12, 2020

Having issues with useColorScheme as well, same as described by the OP on Android. On iOS it always returns dark

@rarira
Copy link

rarira commented May 26, 2020

In my case, On iOS it always returns light.. and useColorScheme subscription doesn't work and Appearance.addChangeListener doesn't call its callback on both ios and android

@franciscocobas
Copy link

Having the same issue here, but it works fine on iOS. For some reason the changeListener never gets called on Android when changing the system color scheme

Same issue here, works well on iOS but not in Android, changeListener is never called.

@franciscocobas
Copy link

Oh finally I solved the issue for Android.

Based on the documentation of the react-native-appearance package I found a configuration for Android that solve this issue.

It has to modify the MainActivity.java with the following code

import android.content.Intent; // <--- import
import android.content.res.Configuration; // <--- import

public class MainActivity extends ReactActivity {
  ......

  // copy these lines
  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    Intent intent = new Intent("onConfigurationChanged");
    intent.putExtra("newConfig", newConfig);
    sendBroadcast(intent);
  }

  ......
}

@josmithua
Copy link

josmithua commented Jun 5, 2020

@franciscocobas that didn't work for me :/. I create a brand new project and added that method, but it still didn't work.

Also @rarira make sure that for iOS, you don't have UIUserInterfaceStyle set in your Info.plist file. That was my mistake (I had it set to Dark, hence why useColorScheme was always returning dark).

@sannajammeh
Copy link
Author

sannajammeh commented Jun 6, 2020

Oh finally I solved the issue for Android.

Based on the documentation of the react-native-appearance package I found a configuration for Android that solve this issue.

It has to modify the MainActivity.java with the following code

import android.content.Intent; // <--- import
import android.content.res.Configuration; // <--- import

public class MainActivity extends ReactActivity {
  ......

  // copy these lines
  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    Intent intent = new Intent("onConfigurationChanged");
    intent.putExtra("newConfig", newConfig);
    sendBroadcast(intent);
  }

  ......
}

This does seem to fix the issue, make sure uiMode is added in android:configChanges in AndroidManifest.xml also. Thank you for the quick solution :)

Edit: This only works when using react-native-appearance. The issue of react-native's Appearance API is still there.

@rarira
Copy link

rarira commented Jun 6, 2020

@franciscocobas that didn't work for me :/. I create a brand new project and added that method, but it still didn't work.

Also @rarira make sure that for iOS, you don't have UIUserInterfaceStyle set in your Info.plist file. That was my mistake (I had it set to Dark, hence why useColorScheme was always returning dark).

Thank you @josmithua ... I also have UIUserInterfaceStyle in my info.plist :)

@franciscocobas
Copy link

Oh finally I solved the issue for Android.
Based on the documentation of the react-native-appearance package I found a configuration for Android that solve this issue.
It has to modify the MainActivity.java with the following code

import android.content.Intent; // <--- import
import android.content.res.Configuration; // <--- import

public class MainActivity extends ReactActivity {
  ......

  // copy these lines
  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    Intent intent = new Intent("onConfigurationChanged");
    intent.putExtra("newConfig", newConfig);
    sendBroadcast(intent);
  }

  ......
}

This does seem to fix the issue, make sure uiMode is added in android:configChanges in AndroidManifest.xml also. Thank you for the quick solution :)

Edit: This only works when using react-native-appearance. The issue of react-native's Appearance API is still there.

Not really, I'm using the react-native's Appearance API.
I have a working implementation of that, check this repository https://github.com/franciscocobas/ReactNativeDarkMode

@mvrdrew
Copy link

mvrdrew commented Jun 8, 2020

I was having the same problem with the hook only returning 'light', no matter how much I'd toggle the appearance in the simulator.

After a lot of digging into code, it turned out the reason it was doing this was due to - the debugger! If you're using a Chrome-based debugger (either in browser or using the standalone RN debugger) the Appearance module will always return light, due to the debugger not being able to handle async functions (or something like that, it was a few days ago!).

I can't say I understand the idiosyncracies as to why it does this, but the upshot of it all is I stopped using the Chrome debugger and moved to flipper - and it worked! I'm now able to swap between dark and light mode using the useColorTheme hook as expected.

Hope this helps someone else, it was a head scratcher for me for quite a while!

@rarira
Copy link

rarira commented Jun 8, 2020

Oh finally I solved the issue for Android.
Based on the documentation of the react-native-appearance package I found a configuration for Android that solve this issue.
It has to modify the MainActivity.java with the following code

import android.content.Intent; // <--- import
import android.content.res.Configuration; // <--- import

public class MainActivity extends ReactActivity {
  ......

  // copy these lines
  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    Intent intent = new Intent("onConfigurationChanged");
    intent.putExtra("newConfig", newConfig);
    sendBroadcast(intent);
  }

  ......
}

This does seem to fix the issue, make sure uiMode is added in android:configChanges in AndroidManifest.xml also. Thank you for the quick solution :)
Edit: This only works when using react-native-appearance. The issue of react-native's Appearance API is still there.

Not really, I'm using the react-native's Appearance API.
I have a working implementation of that, check this repository https://github.com/franciscocobas/ReactNativeDarkMode

@mvrdrew I use flipper not chrome debugger, but it doesn't work either.

@franciscocobas I tried your repo and it works as you mentioned... and you only used react native's API in your code, But I found that in your package.json you have 'react-native-appear' in your dependancies which I don't have.
So I also tried it, I mean just 'yarn add react-native-appearance' .... and it works!!
Of course, I need those lines in MainActivity.java

@josmithua
Copy link

While that might be a work around, this issue is to do with React Native's own Appearance module not working correctly.

@mrbrentkelly
Copy link
Contributor

mrbrentkelly commented Jun 10, 2020

To add on to the list of issues. For iOS I've noticed some strange behavior when overriding the Window UserInterfaceStyle natively.

From the above gif you can see that setting the system theme works perfect, both the useColorScheme hook and change listener trigger.

But if you call window.overrideUserInterfaceStyle = .dark from native iOS only the change listener reacts and updates.

Then when you call window.overrideUserInterfaceStyle = .light neither the hook or change listener get called.

^^ this is using the Appearance API from React Native core.

If I use the react-native-appearance library this behavior works fine...

@mrbrentkelly
Copy link
Contributor

Also noticed an issue on the Android side (using react-native-appearance). If you try and override the system theme natively by calling AppCompatDelegate.setDefaultNightMode the useColorScheme hook or update listener aren't called.

e.g. Calling AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); from native android should trigger an update by the Appearance API on the JavaScript side.

I've raised a PR to address this in react-native-appearance but thought I should mention it here so that the same fix can be brought into React Native core if needed.

expo/react-native-appearance#50

@mrbrentkelly
Copy link
Contributor

In terms of getting Android to react to the system theme using the React Native core API, I've got it working by doing the following...

// in MainActivity.java
@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  getReactInstanceManager().onConfigurationChanged(this, newConfig);
}

It appears this is some missed implementation in ReactActivity.java and ReactActivityDelegate.java.

@josmithua
Copy link

Thanks @mrbrentkelly, I can confirm your Android fix works.

@hearingguo
Copy link

In my case, On iOS it always returns light.. and useColorScheme subscription doesn't work and Appearance.addChangeListener doesn't call its callback on both ios and android

i have same issue, have you solved the problem?

@dubiao
Copy link

dubiao commented Jun 20, 2020

Having issues with useColorScheme as well, same as described by the OP on Android. On iOS it always returns dark

On my iOS it always returnslight

vaagnavanesyan added a commit to vaagnavanesyan/piligrim that referenced this issue Jul 13, 2020
vaagnavanesyan added a commit to vaagnavanesyan/piligrim that referenced this issue Jul 13, 2020
vaagnavanesyan added a commit to vaagnavanesyan/piligrim that referenced this issue Jul 13, 2020
@alexandrughinea
Copy link

It doesn't subscribe to changes still.
I only get the initial value - and that is not always reported correctly.

@ndbeyer
Copy link

ndbeyer commented Aug 4, 2020

For me this works on an ios device with debug mode off. For all other cases (ios device debug mode on, ios simulator, android simulator, android device) this does not seem to work.

@efeliz
Copy link

efeliz commented Aug 13, 2020

Thanks, @mrbrentkelly! I've confirmed that this manual fix works for me while using the official Appearance API. 🥳

@mrbrentkelly
Copy link
Contributor

Feel free to submit a PR

I already did a few weeks back :) #29106

@ShivamJoker
Copy link

ShivamJoker commented Aug 14, 2020

MainActivity.java

import com.facebook.react.ReactActivity;
import android.content.Intent; 
import android.content.res.Configuration;
public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "SQL_PlayGround";
  }

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    getReactInstanceManager().onConfigurationChanged(this, newConfig);
  }
}

The whole code to fix this, hope this gets fixed ASAP

@safaiyeh safaiyeh added the Resolution: PR Submitted A pull request with a fix has been provided. label Aug 14, 2020
@safaiyeh safaiyeh added Platform: Android Android applications. and removed Needs: Issue Manager Attention labels Sep 2, 2020
@irekrog
Copy link

irekrog commented Sep 22, 2020

@mrbrentkelly

In terms of getting Android to react to the system theme using the React Native core API, I've got it working by doing the following...

// in MainActivity.java
@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  getReactInstanceManager().onConfigurationChanged(this, newConfig);
}

It appears this is some missed implementation in ReactActivity.java and ReactActivityDelegate.java.

Doesn't work for me... I'm using react-native-cli not expo and I have still 'dark' from useColorScheme (from react-native and also from react-native-appearance). Where should be call AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO)? In MainActivity or MainApplication? And before or after onCreate method?

@mrbrentkelly
Copy link
Contributor

@irekrog I've just created a repo that applies the workaround if you want to take a look https://github.com/mrbrentkelly/rn-appearance-workaround.

The only code change required to get useColorScheme to work correctly in fresh RN project is in MainActivity.java

package com.someproject;

import com.facebook.react.ReactActivity;
import android.content.res.Configuration; // <-- Add this import

public class MainActivity extends ReactActivity {

  @Override
  protected String getMainComponentName() {
    return "SomeProject";
  }

  // Add this code to get Appearance API to work in Android

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    getReactInstanceManager().onConfigurationChanged(this, newConfig);
  }
}

Also make sure you're using an android device or emulator that's running Android 10 or above.

Where should be call AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO)? In MainActivity or MainApplication? And before or after onCreate method?

This is more of a RN brownfield scenario so you probably don't need to call this at all.

@irekrog
Copy link

irekrog commented Sep 22, 2020

@mrbrentkelly

Ohh thank you for example repo! :)

But now I guess what is wrong because I have a slightly different case. In my app in Settings I have a switcher and I can set dark or light theme for app. For example on my device system theme is dark, but for app I want to change theme to light. Value of theme (dark/light) is saved in SharedPreferences with react-native-shared-preferences library. After restart app in onCreate method in Java I get value from SharedPreferences and if value is light then I call AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO) but unfortunately useColorScheme still returns 'dark'... :/

Also I have checked with int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK; what is value after call AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO) and value of currentNightMode is properly because returns Configuration.UI_MODE_NIGHT_NO

Additionaly I need to manipulate theme in Java with setDefaultNightMode because this is needed to change color in Splash Screen (also I created bug in react-native-bootsplash also related with setDefaultNightMode zoontek/react-native-bootsplash#157)

@mrbrentkelly
Copy link
Contributor

mrbrentkelly commented Sep 22, 2020

@irekrog there's a bug in the appearance API in RN core which will prevent calls to AppCompatDelegate.setDefaultNightMode() from being respected. I have fixed this bug (and the others mentioned in this issue) here but it hasn't been merged yet.

I also fixed the same bug in the react-native-appearance package. That PR was merged already expo/react-native-appearance#50 but I don't think its been published to NPM yet.

So you could ask them to publish the latest changes from their main branch or add react-native-appearance to your project using a github URL instead of through npm (which I wouldn't recommend).

e.g.

yarn add react-native-appearance@https://github.com/expo/react-native-appearance

Note react-native-appearance has a slightly difference setup configuration so check out their docs https://github.com/expo/react-native-appearance

I just tested this all out by creating a bridge module that calls AppCompatDelegate.setDefaultNightMode and it works for me:

https://github.com/mrbrentkelly/rn-appearance-workaround/compare/BK-WithRNA?expand=1

@irekrog
Copy link

irekrog commented Sep 22, 2020

@mrbrentkelly

Thank you very very much! :) Yeah, your fix is merged but still not publish to NPM so temporary I have used patch-package to patch react-native-appearance using your fix and it works fine 👍

rocknegi added a commit to rocknegi/hksj that referenced this issue Feb 1, 2021
Ciberusps added a commit to Ciberusps/expo that referenced this issue Jun 29, 2021
1) bare workflow recommendations for android dont work
```
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // dont work
    // Intent intent = new Intent("onConfigurationChanged");
    // intent.putExtra("newConfig", newConfig);
    // sendBroadcast(intent);
    
   // works ideally and already approved by many people in issue facebook/react-native#28823 (comment)
   getReactInstanceManager().onConfigurationChanged(this, newConfig);
}
```

2) Turned on debugger break `useColorScheme` and `Appearance.getColorScheme` they always return 'light'
facebook/react-native#28823 (comment)
@dmeyer-pfg
Copy link

In my case, On iOS it always returns light.. and useColorScheme subscription doesn't work and Appearance.addChangeListener doesn't call its callback on both ios and android

Assuming you aren't running into the debugger issue mentioned above, my issue was that the UIUserInterfaceStyle within the Info.plist was set to Light. Changing it to Automatic fixed my issue.

More info here.

@DiegoBM
Copy link

DiegoBM commented Sep 16, 2021

In terms of getting Android to react to the system theme using the React Native core API, I've got it working by doing the following...

// in MainActivity.java
@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  getReactInstanceManager().onConfigurationChanged(this, newConfig);
}

It appears this is some missed implementation in ReactActivity.java and ReactActivityDelegate.java.

How come more than one year later this hasn't made it into Android yet?

kanzitelli added a commit to starters-dev/rn-starter that referenced this issue Sep 23, 2021
@pke
Copy link

pke commented Oct 15, 2021

I was finally merged into main 9 days ago :) When can we expect this to hit the npm packaged release?

lunaleaps pushed a commit that referenced this issue Oct 15, 2021
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
lunaleaps pushed a commit that referenced this issue Nov 4, 2021
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
lunaleaps pushed a commit that referenced this issue Nov 4, 2021
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
brentvatne pushed a commit to expo/react-native that referenced this issue Nov 9, 2021
…acebook#29106)

Summary:
This PR fixes a few issues with the Appearance API (as noted here facebook#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

facebook#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: facebook#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
douglowder pushed a commit to react-native-tvos/react-native-tvos that referenced this issue Jan 9, 2022
Summary:
This PR fixes a few issues with the Appearance API (as noted here facebook/react-native#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

facebook/react-native#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: facebook/react-native#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
@facebook facebook locked as resolved and limited conversation to collaborators Oct 6, 2022
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Oct 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Platform: Android Android applications. Resolution: Locked This issue was locked by the bot. Resolution: PR Submitted A pull request with a fix has been provided.
Projects
None yet
Development

No branches or pull requests