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 17:01:57 -07:00
committed by Facebook Github Bot
parent 238fd4ad19
commit 95c1926193
25 changed files with 345 additions and 125 deletions
+17
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
+116
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
-57
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)