-
Notifications
You must be signed in to change notification settings - Fork 24k
/
AppearanceModule.java
123 lines (99 loc) · 3.9 KB
/
AppearanceModule.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
* Copyright (c) Facebook, Inc. and its 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.modules.appearance;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import androidx.annotation.Nullable;
import com.facebook.fbreact.specs.NativeAppearanceSpec;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;
/** Module that exposes the user's preferred color scheme. */
@ReactModule(name = AppearanceModule.NAME)
public class AppearanceModule extends NativeAppearanceSpec {
public static final String NAME = "Appearance";
private static final String APPEARANCE_CHANGED_EVENT_NAME = "appearanceChanged";
private String mColorScheme = "light";
private final @Nullable OverrideColorScheme mOverrideColorScheme;
/** Optional override to the current color scheme */
public interface OverrideColorScheme {
/**
* Color scheme will use the return value instead of the current system configuration. Available
* scheme: {light, dark}
*/
public String getScheme();
}
public AppearanceModule(ReactApplicationContext reactContext) {
this(reactContext, null);
}
public AppearanceModule(
ReactApplicationContext reactContext, @Nullable OverrideColorScheme overrideColorScheme) {
super(reactContext);
mOverrideColorScheme = overrideColorScheme;
mColorScheme = colorSchemeForCurrentConfiguration(reactContext);
}
private String colorSchemeForCurrentConfiguration(Context context) {
if (mOverrideColorScheme != null) {
return mOverrideColorScheme.getScheme();
}
int currentNightMode =
context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
switch (currentNightMode) {
case Configuration.UI_MODE_NIGHT_NO:
return "light";
case Configuration.UI_MODE_NIGHT_YES:
return "dark";
}
return "light";
}
@Override
public String getName() {
return NAME;
}
@Override
public String getColorScheme() {
// Attempt to use the Activity context first in order to get the most up to date
// scheme. This covers the scenario when AppCompatDelegate.setDefaultNightMode()
// is called directly (which can occur in Brownfield apps for example).
Activity activity = getCurrentActivity();
mColorScheme =
colorSchemeForCurrentConfiguration(
activity != null ? activity : getReactApplicationContext());
return mColorScheme;
}
/** Stub */
@Override
public void addListener(String eventName) {}
/** Stub */
@Override
public void removeListeners(double count) {}
/*
* Call this from your root activity whenever configuration changes. If the
* color scheme has changed, an event will emitted.
*/
public void onConfigurationChanged(Context currentContext) {
String newColorScheme = colorSchemeForCurrentConfiguration(currentContext);
if (!mColorScheme.equals(newColorScheme)) {
mColorScheme = newColorScheme;
emitAppearanceChanged(mColorScheme);
}
}
/** Sends an event to the JS instance that the preferred color scheme has changed. */
public void emitAppearanceChanged(String colorScheme) {
WritableMap appearancePreferences = Arguments.createMap();
appearancePreferences.putString("colorScheme", colorScheme);
ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn();
if (reactApplicationContext != null) {
reactApplicationContext
.getJSModule(RCTDeviceEventEmitter.class)
.emit(APPEARANCE_CHANGED_EVENT_NAME, appearancePreferences);
}
}
}