UNPKG

3.52 kBPlain TextView Raw
1/*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#import "RCTAppearance.h"
9
10#import <FBReactNativeSpec/FBReactNativeSpec.h>
11#import <React/RCTConstants.h>
12#import <React/RCTEventEmitter.h>
13
14#import "CoreModulesPlugins.h"
15
16using namespace facebook::react;
17
18NSString *const RCTAppearanceColorSchemeLight = @"light";
19NSString *const RCTAppearanceColorSchemeDark = @"dark";
20
21static BOOL sAppearancePreferenceEnabled = YES;
22void RCTEnableAppearancePreference(BOOL enabled) {
23 sAppearancePreferenceEnabled = enabled;
24}
25
26static NSString *RCTColorSchemePreference(UITraitCollection *traitCollection)
27{
28#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
29 if (@available(iOS 13.0, *)) {
30 static NSDictionary *appearances;
31 static dispatch_once_t onceToken;
32
33 dispatch_once(&onceToken, ^{
34 appearances = @{
35 @(UIUserInterfaceStyleLight): RCTAppearanceColorSchemeLight,
36 @(UIUserInterfaceStyleDark): RCTAppearanceColorSchemeDark
37 };
38 });
39
40 if (!sAppearancePreferenceEnabled) {
41 // Return the default if the app doesn't allow different color schemes.
42 return RCTAppearanceColorSchemeLight;
43 }
44
45 traitCollection = traitCollection ?: [UITraitCollection currentTraitCollection];
46 return appearances[@(traitCollection.userInterfaceStyle)] ?: RCTAppearanceColorSchemeLight;
47 }
48#endif
49
50 // Default to light on older OS version - same behavior as Android.
51 return RCTAppearanceColorSchemeLight;
52}
53
54@interface RCTAppearance () <NativeAppearanceSpec>
55@end
56
57@implementation RCTAppearance
58{
59 NSString *_currentColorScheme;
60}
61
62RCT_EXPORT_MODULE(Appearance)
63
64+ (BOOL)requiresMainQueueSetup
65{
66 return YES;
67}
68
69- (dispatch_queue_t)methodQueue
70{
71 return dispatch_get_main_queue();
72}
73
74- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker
75{
76 return std::make_shared<NativeAppearanceSpecJSI>(self, jsInvoker);
77}
78
79RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, getColorScheme)
80{
81 _currentColorScheme = RCTColorSchemePreference(nil);
82 return _currentColorScheme;
83}
84
85- (void)appearanceChanged:(NSNotification *)notification
86{
87 NSDictionary *userInfo = [notification userInfo];
88 UITraitCollection *traitCollection = nil;
89 if (userInfo) {
90 traitCollection = userInfo[RCTUserInterfaceStyleDidChangeNotificationTraitCollectionKey];
91 }
92 NSString *newColorScheme = RCTColorSchemePreference(traitCollection);
93 if (![_currentColorScheme isEqualToString:newColorScheme]) {
94 _currentColorScheme = newColorScheme;
95 [self sendEventWithName:@"appearanceChanged" body:@{@"colorScheme": newColorScheme}];
96 }
97}
98
99#pragma mark - RCTEventEmitter
100
101- (NSArray<NSString *> *)supportedEvents
102{
103 return @[@"appearanceChanged"];
104}
105
106- (void)startObserving
107{
108 if (@available(iOS 13.0, *)) {
109 [[NSNotificationCenter defaultCenter] addObserver:self
110 selector:@selector(appearanceChanged:)
111 name:RCTUserInterfaceStyleDidChangeNotification
112 object:nil];
113 }
114}
115
116- (void)stopObserving
117{
118 if (@available(iOS 13.0, *)) {
119 [[NSNotificationCenter defaultCenter] removeObserver:self];
120 }
121}
122
123@end
124
125Class RCTAppearanceCls(void) {
126 return RCTAppearance.class;
127}