Introduce `DeviceInfo` as a new native module

Summary:
The `UIManager` already has a lot of responsibilities and is deeply
tied with React Native's view architecture. This diff separates out a
`DeviceInfo` native module to provide information about screen dimensions and
font scale, etc.

Reviewed By: fkgozali

Differential Revision: D4713834

fbshipit-source-id: f2ee93acf876a4221c29a8c731f5abeffbb97974
This commit is contained in:
Ashwin Bharambe 2017-03-17 16:47:51 -07:00 committed by Facebook Github Bot
parent 238fd4ad19
commit 95c1926193
25 changed files with 345 additions and 125 deletions

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule DeviceInfo
* @flow
*/
'use strict';
const DeviceInfo = require('NativeModules').DeviceInfo;
const invariant = require('invariant');
invariant(DeviceInfo, 'DeviceInfo native module is not installed correctly');
module.exports = DeviceInfo;

View File

@ -11,9 +11,9 @@
*/
'use strict';
var DeviceInfo = require('DeviceInfo');
var EventEmitter = require('EventEmitter');
var Platform = require('Platform');
var UIManager = require('UIManager');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var invariant = require('fbjs/lib/invariant');
@ -128,7 +128,7 @@ class Dimensions {
}
}
Dimensions.set(UIManager.Dimensions);
Dimensions.set(DeviceInfo.Dimensions);
RCTDeviceEventEmitter.addListener('didUpdateDimensions', function(update) {
Dimensions.set(update);
});

View File

@ -85,6 +85,7 @@ const ReactNative = {
get CameraRoll() { return require('CameraRoll'); },
get Clipboard() { return require('Clipboard'); },
get DatePickerAndroid() { return require('DatePickerAndroid'); },
get DeviceInfo() { return require('DeviceInfo'); },
get Dimensions() { return require('Dimensions'); },
get Easing() { return require('Easing'); },
get I18nManager() { return require('I18nManager'); },

View File

@ -0,0 +1,17 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import <React/RCTBridge.h>
#import <React/RCTBridgeModule.h>
@interface RCTDeviceInfo : NSObject <RCTBridgeModule, RCTInvalidating>
@end

View File

@ -0,0 +1,116 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "RCTDeviceInfo.h"
#import "RCTAccessibilityManager.h"
#import "RCTAssert.h"
#import "RCTEventDispatcher.h"
#import "RCTUtils.h"
@implementation RCTDeviceInfo {
#if !TARGET_OS_TV
UIInterfaceOrientation _currentInterfaceOrientation;
#endif
}
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE()
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
- (void)setBridge:(RCTBridge *)bridge
{
_bridge = bridge;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didReceiveNewContentSizeMultiplier)
name:RCTAccessibilityManagerDidUpdateMultiplierNotification
object:_bridge.accessibilityManager];
#if !TARGET_OS_TV
_currentInterfaceOrientation = [RCTSharedApplication() statusBarOrientation];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(interfaceOrientationDidChange)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
#endif
}
static NSDictionary *RCTExportedDimensions(RCTBridge *bridge)
{
RCTAssertMainQueue();
// Don't use RCTScreenSize since it the interface orientation doesn't apply to it
CGRect screenSize = [[UIScreen mainScreen] bounds];
NSDictionary *dims = @{
@"width": @(screenSize.size.width),
@"height": @(screenSize.size.height),
@"scale": @(RCTScreenScale()),
@"fontScale": @(bridge.accessibilityManager.multiplier)
};
return @{
@"window": dims,
@"screen": dims
};
}
- (void)invalidate
{
dispatch_async(dispatch_get_main_queue(), ^{
self->_bridge = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
});
}
- (NSDictionary<NSString *, id> *)constantsToExport
{
NSMutableDictionary<NSString *, NSDictionary *> *constants = [NSMutableDictionary new];
constants[@"Dimensions"] = RCTExportedDimensions(_bridge);
return constants;
}
- (void)didReceiveNewContentSizeMultiplier
{
// Report the event across the bridge.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions"
body:RCTExportedDimensions(_bridge)];
#pragma clang diagnostic pop
}
- (void)interfaceOrientationDidChange
{
#if !TARGET_OS_TV
UIInterfaceOrientation nextOrientation = [RCTSharedApplication() statusBarOrientation];
// Update when we go from portrait to landscape, or landscape to portrait
if ((UIInterfaceOrientationIsPortrait(_currentInterfaceOrientation) &&
!UIInterfaceOrientationIsPortrait(nextOrientation)) ||
(UIInterfaceOrientationIsLandscape(_currentInterfaceOrientation) &&
!UIInterfaceOrientationIsLandscape(nextOrientation))) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions"
body:RCTExportedDimensions(_bridge)];
#pragma clang diagnostic pop
}
_currentInterfaceOrientation = nextOrientation;
#endif
}
@end

View File

@ -225,9 +225,6 @@ static UIViewAnimationOptions UIViewAnimationOptionsFromRCTAnimationType(RCTAnim
NSDictionary *_componentDataByName;
NSMutableSet<id<RCTComponent>> *_bridgeTransactionListeners;
#if !TARGET_OS_TV
UIInterfaceOrientation _currentInterfaceOrientation;
#endif
}
@synthesize bridge = _bridge;
@ -239,8 +236,6 @@ RCT_EXPORT_MODULE()
// Report the event across the bridge.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions"
body:RCTExportedDimensions(_bridge)];
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateContentSizeMultiplier"
body:@([_bridge.accessibilityManager multiplier])];
#pragma clang diagnostic pop
@ -252,28 +247,6 @@ RCT_EXPORT_MODULE()
});
}
- (void)interfaceOrientationDidChange
{
#if !TARGET_OS_TV
UIInterfaceOrientation nextOrientation =
[RCTSharedApplication() statusBarOrientation];
// Update when we go from portrait to landscape, or landscape to portrait
if ((UIInterfaceOrientationIsPortrait(_currentInterfaceOrientation) &&
!UIInterfaceOrientationIsPortrait(nextOrientation)) ||
(UIInterfaceOrientationIsLandscape(_currentInterfaceOrientation) &&
!UIInterfaceOrientationIsLandscape(nextOrientation))) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions"
body:RCTExportedDimensions(_bridge)];
#pragma clang diagnostic pop
}
_currentInterfaceOrientation = nextOrientation;
#endif
}
- (void)invalidate
{
/**
@ -351,13 +324,6 @@ RCT_EXPORT_MODULE()
selector:@selector(didReceiveNewContentSizeMultiplier)
name:RCTAccessibilityManagerDidUpdateMultiplierNotification
object:_bridge.accessibilityManager];
#if !TARGET_OS_TV
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(interfaceOrientationDidChange)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
#endif
[RCTAnimation initializeStatics];
}
@ -1544,35 +1510,12 @@ RCT_EXPORT_METHOD(clearJSResponder)
constants[name] = moduleConstants;
}];
#if !TARGET_OS_TV
_currentInterfaceOrientation = [RCTSharedApplication() statusBarOrientation];
#endif
constants[@"customBubblingEventTypes"] = bubblingEvents;
constants[@"customDirectEventTypes"] = directEvents;
constants[@"Dimensions"] = RCTExportedDimensions(_bridge);
return constants;
}
static NSDictionary *RCTExportedDimensions(RCTBridge *bridge)
{
RCTAssertMainQueue();
// Don't use RCTScreenSize since it the interface orientation doesn't apply to it
CGRect screenSize = [[UIScreen mainScreen] bounds];
NSDictionary *dims = @{
@"width": @(screenSize.size.width),
@"height": @(screenSize.size.height),
@"scale": @(RCTScreenScale()),
@"fontScale": @(bridge.accessibilityManager.multiplier)
};
return @{
@"window": dims,
@"screen": dims
};
}
RCT_EXPORT_METHOD(configureNextLayoutAnimation:(NSDictionary *)config
withCallback:(RCTResponseSenderBlock)callback
errorCallback:(__unused RCTResponseSenderBlock)errorCallback)

View File

@ -738,6 +738,10 @@
B50558421E43E14000F71A00 /* RCTDevSettings.mm in Sources */ = {isa = PBXBuildFile; fileRef = B505583D1E43DFB900F71A00 /* RCTDevSettings.mm */; };
B50558431E43E64600F71A00 /* RCTDevSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = B505583C1E43DFB900F71A00 /* RCTDevSettings.h */; };
B95154321D1B34B200FE7B80 /* RCTActivityIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = B95154311D1B34B200FE7B80 /* RCTActivityIndicatorView.m */; };
CF85BC321E79EC6B00F1EF3B /* RCTDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = CF85BC301E79EC6B00F1EF3B /* RCTDeviceInfo.h */; };
CF85BC331E79EC6B00F1EF3B /* RCTDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = CF85BC311E79EC6B00F1EF3B /* RCTDeviceInfo.m */; };
CF85BC341E79EC7A00F1EF3B /* RCTDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = CF85BC301E79EC6B00F1EF3B /* RCTDeviceInfo.h */; };
CF85BC351E79EC7D00F1EF3B /* RCTDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = CF85BC311E79EC6B00F1EF3B /* RCTDeviceInfo.m */; };
E9B20B7B1B500126007A2DA7 /* RCTAccessibilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B20B7A1B500126007A2DA7 /* RCTAccessibilityManager.m */; };
/* End PBXBuildFile section */
@ -1381,6 +1385,8 @@
B505583D1E43DFB900F71A00 /* RCTDevSettings.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTDevSettings.mm; sourceTree = "<group>"; };
B95154301D1B34B200FE7B80 /* RCTActivityIndicatorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTActivityIndicatorView.h; sourceTree = "<group>"; };
B95154311D1B34B200FE7B80 /* RCTActivityIndicatorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTActivityIndicatorView.m; sourceTree = "<group>"; };
CF85BC301E79EC6B00F1EF3B /* RCTDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDeviceInfo.h; sourceTree = "<group>"; };
CF85BC311E79EC6B00F1EF3B /* RCTDeviceInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDeviceInfo.m; sourceTree = "<group>"; };
E3BBC8EB1ADE6F47001BBD81 /* RCTTextDecorationLineType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTTextDecorationLineType.h; sourceTree = "<group>"; };
E9B20B791B500126007A2DA7 /* RCTAccessibilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAccessibilityManager.h; sourceTree = "<group>"; };
E9B20B7A1B500126007A2DA7 /* RCTAccessibilityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAccessibilityManager.m; sourceTree = "<group>"; };
@ -1456,6 +1462,8 @@
B505583B1E43DFB900F71A00 /* RCTDevMenu.m */,
B505583C1E43DFB900F71A00 /* RCTDevSettings.h */,
B505583D1E43DFB900F71A00 /* RCTDevSettings.mm */,
CF85BC301E79EC6B00F1EF3B /* RCTDeviceInfo.h */,
CF85BC311E79EC6B00F1EF3B /* RCTDeviceInfo.m */,
13D9FEE91CDCCECF00158BD7 /* RCTEventEmitter.h */,
13D9FEEA1CDCCECF00158BD7 /* RCTEventEmitter.m */,
13B07FE91A69327A00A75B9A /* RCTExceptionsManager.h */,
@ -1869,6 +1877,7 @@
3D302F3E1DF828F800D6DDAE /* RCTKeyCommands.h in Headers */,
3D302F3F1DF828F800D6DDAE /* RCTLog.h in Headers */,
3D302F401DF828F800D6DDAE /* RCTModuleData.h in Headers */,
CF85BC341E79EC7A00F1EF3B /* RCTDeviceInfo.h in Headers */,
3D302F411DF828F800D6DDAE /* RCTModuleMethod.h in Headers */,
3D302F421DF828F800D6DDAE /* RCTMultipartDataTask.h in Headers */,
3D302F431DF828F800D6DDAE /* RCTMultipartStreamReader.h in Headers */,
@ -2055,6 +2064,7 @@
A12E9E2A1E5DEB860029001B /* RCTReconnectingWebSocket.h in Headers */,
3D80DA311DF820620028D040 /* RCTJavaScriptLoader.h in Headers */,
3D80DA321DF820620028D040 /* RCTJSStackFrame.h in Headers */,
CF85BC321E79EC6B00F1EF3B /* RCTDeviceInfo.h in Headers */,
3D80DA331DF820620028D040 /* RCTKeyCommands.h in Headers */,
3D80DA341DF820620028D040 /* RCTLog.h in Headers */,
3D80DA351DF820620028D040 /* RCTModuleData.h in Headers */,
@ -2465,6 +2475,7 @@
2D3B5EC21D9B093B00451313 /* RCTProfile.m in Sources */,
2D3B5ECB1D9B096200451313 /* RCTConvert+CoreLocation.m in Sources */,
A12E9E261E5DEB510029001B /* RCTPackagerClientResponder.m in Sources */,
CF85BC351E79EC7D00F1EF3B /* RCTDeviceInfo.m in Sources */,
2D3B5EEE1D9B09DA00451313 /* RCTView.m in Sources */,
594AD5D01E46D87500B07237 /* RCTScrollContentShadowView.m in Sources */,
2D3B5E981D9B089500451313 /* RCTConvert.m in Sources */,
@ -2675,6 +2686,7 @@
945929C41DD62ADD00653A7D /* RCTConvert+Transform.m in Sources */,
13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */,
13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */,
CF85BC331E79EC6B00F1EF3B /* RCTDeviceInfo.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -980,6 +980,10 @@
AC70D2E91DE489E4002E6351 /* RCTJavaScriptLoader.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC70D2E81DE489E4002E6351 /* RCTJavaScriptLoader.mm */; };
B233E6EA1D2D845D00BC68BA /* RCTI18nManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B233E6E91D2D845D00BC68BA /* RCTI18nManager.m */; };
B95154321D1B34B200FE7B80 /* RCTActivityIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = B95154311D1B34B200FE7B80 /* RCTActivityIndicatorView.m */; };
CF2731C01E7B8DE40044CA4F /* RCTDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = CF2731BE1E7B8DE40044CA4F /* RCTDeviceInfo.h */; };
CF2731C11E7B8DE40044CA4F /* RCTDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = CF2731BF1E7B8DE40044CA4F /* RCTDeviceInfo.m */; };
CF2731C21E7B8DEF0044CA4F /* RCTDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = CF2731BE1E7B8DE40044CA4F /* RCTDeviceInfo.h */; };
CF2731C31E7B8DF30044CA4F /* RCTDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = CF2731BF1E7B8DE40044CA4F /* RCTDeviceInfo.m */; };
E9B20B7B1B500126007A2DA7 /* RCTAccessibilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B20B7A1B500126007A2DA7 /* RCTAccessibilityManager.m */; };
/* End PBXBuildFile section */
@ -1828,6 +1832,8 @@
B233E6E91D2D845D00BC68BA /* RCTI18nManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTI18nManager.m; sourceTree = "<group>"; };
B95154301D1B34B200FE7B80 /* RCTActivityIndicatorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTActivityIndicatorView.h; sourceTree = "<group>"; };
B95154311D1B34B200FE7B80 /* RCTActivityIndicatorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTActivityIndicatorView.m; sourceTree = "<group>"; };
CF2731BE1E7B8DE40044CA4F /* RCTDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDeviceInfo.h; sourceTree = "<group>"; };
CF2731BF1E7B8DE40044CA4F /* RCTDeviceInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDeviceInfo.m; sourceTree = "<group>"; };
E3BBC8EB1ADE6F47001BBD81 /* RCTTextDecorationLineType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTTextDecorationLineType.h; sourceTree = "<group>"; };
E9B20B791B500126007A2DA7 /* RCTAccessibilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAccessibilityManager.h; sourceTree = "<group>"; };
E9B20B7A1B500126007A2DA7 /* RCTAccessibilityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAccessibilityManager.m; sourceTree = "<group>"; };
@ -2034,6 +2040,8 @@
13B07FE01A69315300A75B9A /* Modules */ = {
isa = PBXGroup;
children = (
CF2731BE1E7B8DE40044CA4F /* RCTDeviceInfo.h */,
CF2731BF1E7B8DE40044CA4F /* RCTDeviceInfo.m */,
130E3D861E6A082100ACE484 /* RCTDevSettings.h */,
130E3D871E6A082100ACE484 /* RCTDevSettings.mm */,
369123DF1DDC75850095B341 /* JSCSamplingProfiler.h */,
@ -2595,6 +2603,7 @@
3D302F881DF828F800D6DDAE /* RCTRootShadowView.h in Headers */,
3D302F891DF828F800D6DDAE /* RCTScrollableProtocol.h in Headers */,
3D302F8A1DF828F800D6DDAE /* RCTScrollView.h in Headers */,
CF2731C21E7B8DEF0044CA4F /* RCTDeviceInfo.h in Headers */,
3D302F8B1DF828F800D6DDAE /* RCTScrollViewManager.h in Headers */,
3D302F8C1DF828F800D6DDAE /* RCTSegmentedControl.h in Headers */,
3D302F8D1DF828F800D6DDAE /* RCTSegmentedControlManager.h in Headers */,
@ -2837,6 +2846,7 @@
3D80DA5E1DF820620028D040 /* RCTProfile.h in Headers */,
3D80DA5F1DF820620028D040 /* RCTActivityIndicatorView.h in Headers */,
3D80DA601DF820620028D040 /* RCTActivityIndicatorViewManager.h in Headers */,
CF2731C01E7B8DE40044CA4F /* RCTDeviceInfo.h in Headers */,
3D80DA611DF820620028D040 /* RCTAnimationType.h in Headers */,
3D80DA621DF820620028D040 /* RCTAutoInsetsProtocol.h in Headers */,
3D80DA631DF820620028D040 /* RCTBorderDrawing.h in Headers */,
@ -3314,6 +3324,7 @@
2D3B5EA51D9B08C700451313 /* RCTRootView.m in Sources */,
2D3B5EAC1D9B08EF00451313 /* RCTJSCExecutor.mm in Sources */,
13134C871E296B2A00B9F3CB /* RCTCxxBridge.mm in Sources */,
CF2731C31E7B8DF30044CA4F /* RCTDeviceInfo.m in Sources */,
2D3B5EB11D9B090100451313 /* RCTAppState.m in Sources */,
2D3B5EC21D9B093B00451313 /* RCTProfile.m in Sources */,
13134C931E296B2A00B9F3CB /* RCTNativeModule.mm in Sources */,
@ -3524,6 +3535,7 @@
14C2CA781B3ACB0400E6CBB2 /* RCTBatchedBridge.m in Sources */,
13E067591A70F44B002CDEE1 /* UIView+React.m in Sources */,
14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */,
CF2731C11E7B8DE40044CA4F /* RCTDeviceInfo.m in Sources */,
3D7AA9C41E548CD5001955CF /* NSDataBigString.mm in Sources */,
13D033631C1837FE0021DC29 /* RCTClipboard.m in Sources */,
14C2CA741B3AC64300E6CBB2 /* RCTModuleData.mm in Sources */,

View File

@ -15,6 +15,7 @@ deps = [
react_native_target("java/com/facebook/react/modules/datepicker:datepicker"),
react_native_target("java/com/facebook/react/modules/share:share"),
react_native_target("java/com/facebook/react/modules/systeminfo:systeminfo"),
react_native_target("java/com/facebook/react/modules/deviceinfo:deviceinfo"),
react_native_target("java/com/facebook/react/modules/timepicker:timepicker"),
react_native_target("java/com/facebook/react/touch:touch"),
react_native_target("java/com/facebook/react/uimanager:uimanager"),

View File

@ -31,6 +31,7 @@ import com.facebook.react.bridge.UnexpectedNativeTypeException;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.modules.appstate.AppStateModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.modules.systeminfo.AndroidInfoModule;
import com.facebook.react.testing.FakeWebSocketModule;
import com.facebook.react.testing.ReactIntegrationTestCase;
@ -101,6 +102,7 @@ public class CatalystNativeJSToJavaParametersTestCase extends ReactIntegrationTe
mCatalystInstance = ReactTestHelper.catalystInstanceBuilder(this)
.addNativeModule(mRecordingTestModule)
.addNativeModule(new AndroidInfoModule())
.addNativeModule(new DeviceInfoModule(getContext()))
.addNativeModule(new AppStateModule(getContext()))
.addNativeModule(new FakeWebSocketModule())
.addNativeModule(mUIManager)

View File

@ -20,6 +20,7 @@ import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.modules.appstate.AppStateModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.testing.AssertModule;
import com.facebook.react.testing.FakeWebSocketModule;
import com.facebook.react.testing.ReactIntegrationTestCase;
@ -78,6 +79,7 @@ public class CatalystNativeJavaToJSArgumentsTestCase extends ReactIntegrationTes
mInstance = ReactTestHelper.catalystInstanceBuilder(this)
.addNativeModule(mAssertModule)
.addNativeModule(new DeviceInfoModule(getContext()))
.addNativeModule(new AppStateModule(getContext()))
.addNativeModule(new FakeWebSocketModule())
.addJSModule(TestJavaToJSArgumentsModule.class)

View File

@ -19,6 +19,7 @@ import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.modules.appstate.AppStateModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.testing.AssertModule;
import com.facebook.react.testing.FakeWebSocketModule;
@ -119,6 +120,7 @@ public class CatalystNativeJavaToJSReturnValuesTestCase extends ReactIntegration
mInstance = ReactTestHelper.catalystInstanceBuilder(this)
.addNativeModule(mAssertModule)
.addNativeModule(new DeviceInfoModule(getContext()))
.addNativeModule(new AppStateModule(getContext()))
.addNativeModule(new FakeWebSocketModule())
.addJSModule(TestJavaToJSReturnValuesModule.class)

View File

@ -22,6 +22,7 @@ import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.modules.appstate.AppStateModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.modules.systeminfo.AndroidInfoModule;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.UIImplementation;
@ -96,6 +97,7 @@ public class CatalystUIManagerTestCase extends ReactIntegrationTestCase {
jsModule = ReactTestHelper.catalystInstanceBuilder(this)
.addNativeModule(uiManager)
.addNativeModule(new AndroidInfoModule())
.addNativeModule(new DeviceInfoModule(getContext()))
.addNativeModule(new AppStateModule(getContext()))
.addNativeModule(new FakeWebSocketModule())
.addJSModule(UIManagerTestModule.class)

View File

@ -19,6 +19,7 @@ import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.modules.appstate.AppStateModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.uimanager.UIImplementationProvider;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewManager;
@ -62,6 +63,7 @@ public class JSLocaleTest extends ReactIntegrationTestCase {
mInstance = ReactTestHelper.catalystInstanceBuilder(this)
.addNativeModule(mStringRecordingModule)
.addNativeModule(mUIManager)
.addNativeModule(new DeviceInfoModule(getContext()))
.addNativeModule(new AppStateModule(getContext()))
.addNativeModule(new FakeWebSocketModule())
.addJSModule(TestJSLocaleModule.class)

View File

@ -25,6 +25,7 @@ import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.modules.appstate.AppStateModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.modules.systeminfo.AndroidInfoModule;
import com.facebook.react.uimanager.UIImplementation;
import com.facebook.react.uimanager.UIImplementationProvider;
@ -87,6 +88,7 @@ public class ProgressBarTestCase extends ReactIntegrationTestCase {
mInstance = ReactTestHelper.catalystInstanceBuilder(this)
.addNativeModule(mUIManager)
.addNativeModule(new AndroidInfoModule())
.addNativeModule(new DeviceInfoModule(getContext()))
.addNativeModule(new AppStateModule(getContext()))
.addNativeModule(new FakeWebSocketModule())
.addJSModule(ProgressBarTestModule.class)

View File

@ -20,6 +20,7 @@ import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.modules.appstate.AppStateModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.modules.systeminfo.AndroidInfoModule;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.UIImplementation;
@ -68,6 +69,7 @@ public class ViewRenderingTestCase extends ReactIntegrationTestCase {
mCatalystInstance = ReactTestHelper.catalystInstanceBuilder(this)
.addNativeModule(uiManager)
.addNativeModule(new AndroidInfoModule())
.addNativeModule(new DeviceInfoModule(getContext()))
.addNativeModule(new AppStateModule(getContext()))
.addNativeModule(new FakeWebSocketModule())
.addJSModule(ViewRenderingTestModule.class)

View File

@ -19,6 +19,7 @@ DEPS = [
react_native_target("java/com/facebook/react/modules/core:core"),
react_native_target("java/com/facebook/react/modules/debug:debug"),
react_native_target("java/com/facebook/react/modules/debug:interfaces"),
react_native_target("java/com/facebook/react/modules/deviceinfo:deviceinfo"),
react_native_target("java/com/facebook/react/modules/systeminfo:systeminfo"),
react_native_target("java/com/facebook/react/modules/toast:toast"),
react_native_target("java/com/facebook/react/uimanager:uimanager"),

View File

@ -36,6 +36,7 @@ import com.facebook.react.modules.core.RCTNativeAppEventEmitter;
import com.facebook.react.modules.core.Timing;
import com.facebook.react.modules.debug.AnimationsDebugModule;
import com.facebook.react.modules.debug.SourceCodeModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.modules.systeminfo.AndroidInfoModule;
import com.facebook.react.modules.appregistry.AppRegistry;
import com.facebook.react.uimanager.UIImplementationProvider;
@ -65,6 +66,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_CORE_REACT_
SourceCodeModule.class,
Timing.class,
UIManagerModule.class,
DeviceInfoModule.class,
// Debug only
DebugComponentOwnershipModule.class,
JSCHeapCapture.class,
@ -151,6 +153,13 @@ import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_CORE_REACT_
return createUIManager(reactContext);
}
}));
moduleSpecList.add(
new ModuleSpec(DeviceInfoModule.class, new Provider<NativeModule>() {
@Override
public NativeModule get() {
return new DeviceInfoModule(reactContext);
}
}));
if (ReactBuildConfig.DEBUG) {
moduleSpecList.add(

View File

@ -15,7 +15,6 @@ import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
@ -32,6 +31,7 @@ import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.JSTouchDispatcher;
import com.facebook.react.uimanager.PixelUtil;
@ -396,7 +396,7 @@ public class ReactRootView extends SizeMonitoringFrameLayout implements RootView
private void emitUpdateDimensionsEvent() {
mReactInstanceManager
.getCurrentReactContext()
.getNativeModule(UIManagerModule.class)
.getNativeModule(DeviceInfoModule.class)
.emitUpdateDimensionsEvent();
}

View File

@ -0,0 +1,17 @@
include_defs("//ReactAndroid/DEFS")
android_library(
name = "deviceinfo",
srcs = glob(["**/*.java"]),
visibility = [
"PUBLIC",
],
deps = [
react_native_dep("third-party/java/jsr-305:jsr-305"),
react_native_target("java/com/facebook/react/bridge:bridge"),
react_native_target("java/com/facebook/react/common:common"),
react_native_target("java/com/facebook/react/module/annotations:annotations"),
react_native_target("java/com/facebook/react/modules/core:core"),
react_native_target("java/com/facebook/react/uimanager:uimanager"),
],
)

View File

@ -0,0 +1,105 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.modules.deviceinfo;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import android.util.DisplayMetrics;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.uimanager.DisplayMetricsHolder;
/**
* Module that exposes Android Constants to JS.
*/
@ReactModule(name = "DeviceInfo")
public class DeviceInfoModule extends ReactContextBaseJavaModule implements
LifecycleEventListener {
private float mFontScale;
public DeviceInfoModule(
ReactApplicationContext reactContext) {
super(reactContext);
mFontScale = getReactApplicationContext().getResources().getConfiguration().fontScale;
}
@Override
public String getName() {
return "DeviceInfo";
}
@Override
public @Nullable Map<String, Object> getConstants() {
HashMap<String, Object> constants = new HashMap<>();
constants.put(
"Dimensions",
getDimensionsConstants());
return constants;
}
@Override
public void onHostResume() {
float fontScale = getReactApplicationContext().getResources().getConfiguration().fontScale;
if (mFontScale != fontScale) {
mFontScale = fontScale;
emitUpdateDimensionsEvent();
}
}
@Override
public void onHostPause() {
}
@Override
public void onHostDestroy() {
}
public void emitUpdateDimensionsEvent() {
getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("didUpdateDimensions", getDimensionsConstants());
}
private WritableMap getDimensionsConstants() {
DisplayMetrics windowDisplayMetrics = DisplayMetricsHolder.getWindowDisplayMetrics();
DisplayMetrics screenDisplayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics();
WritableMap windowDisplayMetricsMap = Arguments.createMap();
windowDisplayMetricsMap.putInt("width", windowDisplayMetrics.widthPixels);
windowDisplayMetricsMap.putInt("height", windowDisplayMetrics.heightPixels);
windowDisplayMetricsMap.putDouble("scale", windowDisplayMetrics.density);
windowDisplayMetricsMap.putDouble("fontScale", mFontScale);
windowDisplayMetricsMap.putDouble("densityDpi", windowDisplayMetrics.densityDpi);
WritableMap screenDisplayMetricsMap = Arguments.createMap();
screenDisplayMetricsMap.putInt("width", screenDisplayMetrics.widthPixels);
screenDisplayMetricsMap.putInt("height", screenDisplayMetrics.heightPixels);
screenDisplayMetricsMap.putDouble("scale", screenDisplayMetrics.density);
screenDisplayMetricsMap.putDouble("fontScale", mFontScale);
screenDisplayMetricsMap.putDouble("densityDpi", screenDisplayMetrics.densityDpi);
WritableMap dimensionsMap = Arguments.createMap();
dimensionsMap.putMap("windowPhysicalPixels", windowDisplayMetricsMap);
dimensionsMap.putMap("screenPhysicalPixels", screenDisplayMetricsMap);
return dimensionsMap;
}
}

View File

@ -87,7 +87,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
private final Map<String, Object> mModuleConstants;
private final UIImplementation mUIImplementation;
private final MemoryTrimCallback mMemoryTrimCallback = new MemoryTrimCallback();
private float mFontScale;
private int mNextRootViewTag = 1;
private int mBatchId = 0;
@ -100,8 +99,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
super(reactContext);
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
mEventDispatcher = new EventDispatcher(reactContext);
mFontScale = getReactApplicationContext().getResources().getConfiguration().fontScale;
mModuleConstants = createConstants(viewManagerList, lazyViewManagersEnabled, mFontScale);
mModuleConstants = createConstants(viewManagerList, lazyViewManagersEnabled);
mUIImplementation = uiImplementationProvider
.createUIImplementation(reactContext, viewManagerList, mEventDispatcher);
@ -134,12 +132,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
@Override
public void onHostResume() {
mUIImplementation.onHostResume();
float fontScale = getReactApplicationContext().getResources().getConfiguration().fontScale;
if (mFontScale != fontScale) {
mFontScale = fontScale;
emitUpdateDimensionsEvent();
}
}
@Override
@ -163,15 +155,13 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
private static Map<String, Object> createConstants(
List<ViewManager> viewManagerList,
boolean lazyViewManagersEnabled,
float fontScale) {
boolean lazyViewManagersEnabled) {
ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_CONSTANTS_START);
Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "CreateUIManagerConstants");
try {
return UIManagerModuleConstantsHelper.createConstants(
viewManagerList,
lazyViewManagersEnabled,
fontScale);
lazyViewManagersEnabled);
} finally {
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_CONSTANTS_END);
@ -550,16 +540,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
mUIImplementation.sendAccessibilityEvent(tag, eventType);
}
public void emitUpdateDimensionsEvent() {
sendEvent("didUpdateDimensions", UIManagerModuleConstants.getDimensionsConstants(mFontScale));
}
private void sendEvent(String eventName, @Nullable WritableMap params) {
getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
/**
* Schedule a block to be executed on the UI thread. Useful if you need to execute
* view logic after all currently queued view updates have completed.

View File

@ -83,7 +83,7 @@ import com.facebook.react.uimanager.events.TouchEventType;
.build();
}
public static Map<String, Object> getConstants(float fontScale) {
public static Map<String, Object> getConstants() {
HashMap<String, Object> constants = new HashMap<String, Object>();
constants.put(
"UIView",
@ -97,10 +97,6 @@ import com.facebook.react.uimanager.events.TouchEventType;
"ScaleAspectCenter",
ImageView.ScaleType.CENTER_INSIDE.ordinal())));
constants.put(
"Dimensions",
getDimensionsConstants(fontScale));
constants.put(
"StyleConstants",
MapBuilder.of(
@ -133,29 +129,4 @@ import com.facebook.react.uimanager.events.TouchEventType;
return constants;
}
public static WritableMap getDimensionsConstants(float fontScale) {
DisplayMetrics windowDisplayMetrics = DisplayMetricsHolder.getWindowDisplayMetrics();
DisplayMetrics screenDisplayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics();
WritableMap windowDisplayMetricsMap = Arguments.createMap();
windowDisplayMetricsMap.putInt("width", windowDisplayMetrics.widthPixels);
windowDisplayMetricsMap.putInt("height", windowDisplayMetrics.heightPixels);
windowDisplayMetricsMap.putDouble("scale", windowDisplayMetrics.density);
windowDisplayMetricsMap.putDouble("fontScale", fontScale);
windowDisplayMetricsMap.putDouble("densityDpi", windowDisplayMetrics.densityDpi);
WritableMap screenDisplayMetricsMap = Arguments.createMap();
screenDisplayMetricsMap.putInt("width", screenDisplayMetrics.widthPixels);
screenDisplayMetricsMap.putInt("height", screenDisplayMetrics.heightPixels);
screenDisplayMetricsMap.putDouble("scale", screenDisplayMetrics.density);
screenDisplayMetricsMap.putDouble("fontScale", fontScale);
screenDisplayMetricsMap.putDouble("densityDpi", screenDisplayMetrics.densityDpi);
WritableMap dimensionsMap = Arguments.createMap();
dimensionsMap.putMap("windowPhysicalPixels", windowDisplayMetricsMap);
dimensionsMap.putMap("screenPhysicalPixels", screenDisplayMetricsMap);
return dimensionsMap;
}
}

View File

@ -43,9 +43,8 @@ import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
*/
/* package */ static Map<String, Object> createConstants(
List<ViewManager> viewManagers,
boolean lazyViewManagersEnabled,
float fontScale) {
Map<String, Object> constants = UIManagerModuleConstants.getConstants(fontScale);
boolean lazyViewManagersEnabled) {
Map<String, Object> constants = UIManagerModuleConstants.getConstants();
Map bubblingEventTypesConstants = UIManagerModuleConstants.getBubblingEventTypeConstants();
Map directEventTypesConstants = UIManagerModuleConstants.getDirectEventTypeConstants();

View File

@ -87,6 +87,16 @@ const mockNativeModules = {
DataManager: {
queryData: jest.fn(),
},
DeviceInfo: {
Dimensions: {
window: {
fontScale: 2,
height: 1334,
scale: 2,
width: 750,
},
},
},
FacebookSDK: {
login: jest.fn(),
logout: jest.fn(),
@ -150,14 +160,6 @@ const mockNativeModules = {
replaceExistingNonRootView: jest.fn(),
customBubblingEventTypes: {},
customDirectEventTypes: {},
Dimensions: {
window: {
fontScale: 2,
height: 1334,
scale: 2,
width: 750,
},
},
ModalFullscreenView: {
Constants: {},
},