Skip to content

Commit

Permalink
Migrate DeviceInfoModule from RN Module to Native Function.
Browse files Browse the repository at this point in the history
Reviewed By: danzimm

Differential Revision: D6750934

fbshipit-source-id: f453801737e41632c6b84ff894e7f0eb66b575dc
  • Loading branch information
Dmitry Zakharov authored and facebook-github-bot committed Jan 29, 2018
1 parent 6224ef5 commit 429fcc8
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 45 deletions.
84 changes: 50 additions & 34 deletions Libraries/Utilities/Dimensions.js
Expand Up @@ -11,7 +11,6 @@
*/ */
'use strict'; 'use strict';


var DeviceInfo = require('DeviceInfo');
var EventEmitter = require('EventEmitter'); var EventEmitter = require('EventEmitter');
var Platform = require('Platform'); var Platform = require('Platform');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
Expand All @@ -21,22 +20,59 @@ var invariant = require('fbjs/lib/invariant');
var eventEmitter = new EventEmitter(); var eventEmitter = new EventEmitter();
var dimensionsInitialized = false; var dimensionsInitialized = false;
var dimensions = {}; var dimensions = {};

var dimensionsProvider: ?(() => {[key:string]: Object});

class Dimensions { class Dimensions {
/** static setProvider(value: () => {[key:string]: Object}): void {
* This should only be called from native code by sending the dimensionsProvider = value;
* didUpdateDimensions event. dimensionsInitialized = false;
* dimensions = {};
* @param {object} dims Simple string-keyed object of dimensions to set }
*/
static set(dims: {[key:string]: any}): void { static getDimensions(): {[key:string]: Object} {
if (dimensionsInitialized) {
return dimensions;
}

// We calculate the window dimensions in JS so that we don't encounter loss of // We calculate the window dimensions in JS so that we don't encounter loss of
// precision in transferring the dimensions (which could be non-integers) over // precision in transferring the dimensions (which could be non-integers) over
// the bridge. // the bridge.
const dims = (dimensionsProvider || defaultDimProvider)();
const result = Dimensions.updateDimensions(dims);
RCTDeviceEventEmitter.addListener('didUpdateDimensions', function(update) {
Dimensions.updateDimensions(update);
});
return result;
}

/**
* Initial dimensions are set before `runApplication` is called so they should
* be available before any other require's are run, but may be updated later.
*
* Note: Although dimensions are available immediately, they may change (e.g
* due to device rotation) so any rendering logic or styles that depend on
* these constants should try to call this function on every render, rather
* than caching the value (for example, using inline styles rather than
* setting a value in a `StyleSheet`).
*
* Example: `var {height, width} = Dimensions.get('window');`
*
* @param {string} dim Name of dimension as defined when calling `set`.
* @returns {Object?} Value for the dimension.
*/
static get(dim: string): Object {
const dims = Dimensions.getDimensions();
invariant(dims[dim], 'No dimension set for key ' + dim);
return dims[dim];
}

static updateDimensions(dims: ?{[key:string]: Object}): {[key:string]: Object} {
if (dims && dims.windowPhysicalPixels) { if (dims && dims.windowPhysicalPixels) {
// parse/stringify => Clone hack // parse/stringify => Clone hack
dims = JSON.parse(JSON.stringify(dims)); dims = JSON.parse(JSON.stringify(dims));


var windowPhysicalPixels = dims.windowPhysicalPixels; const windowPhysicalPixels = dims.windowPhysicalPixels;
dims.window = { dims.window = {
width: windowPhysicalPixels.width / windowPhysicalPixels.scale, width: windowPhysicalPixels.width / windowPhysicalPixels.scale,
height: windowPhysicalPixels.height / windowPhysicalPixels.scale, height: windowPhysicalPixels.height / windowPhysicalPixels.scale,
Expand All @@ -45,7 +81,7 @@ class Dimensions {
}; };
if (Platform.OS === 'android') { if (Platform.OS === 'android') {
// Screen and window dimensions are different on android // Screen and window dimensions are different on android
var screenPhysicalPixels = dims.screenPhysicalPixels; const screenPhysicalPixels = dims.screenPhysicalPixels;
dims.screen = { dims.screen = {
width: screenPhysicalPixels.width / screenPhysicalPixels.scale, width: screenPhysicalPixels.width / screenPhysicalPixels.scale,
height: screenPhysicalPixels.height / screenPhysicalPixels.scale, height: screenPhysicalPixels.height / screenPhysicalPixels.scale,
Expand All @@ -72,26 +108,7 @@ class Dimensions {
} else { } else {
dimensionsInitialized = true; dimensionsInitialized = true;
} }
} return dimensions;

/**
* Initial dimensions are set before `runApplication` is called so they should
* be available before any other require's are run, but may be updated later.
*
* Note: Although dimensions are available immediately, they may change (e.g
* due to device rotation) so any rendering logic or styles that depend on
* these constants should try to call this function on every render, rather
* than caching the value (for example, using inline styles rather than
* setting a value in a `StyleSheet`).
*
* Example: `var {height, width} = Dimensions.get('window');`
*
* @param {string} dim Name of dimension as defined when calling `set`.
* @returns {Object?} Value for the dimension.
*/
static get(dim: string): Object {
invariant(dimensions[dim], 'No dimension set for key ' + dim);
return dimensions[dim];
} }


/** /**
Expand Down Expand Up @@ -128,9 +145,8 @@ class Dimensions {
} }
} }


Dimensions.set(DeviceInfo.Dimensions); function defaultDimProvider(): {[key:string]: Object} {
RCTDeviceEventEmitter.addListener('didUpdateDimensions', function(update) { return require('DeviceInfo').Dimensions;
Dimensions.set(update); }
});


module.exports = Dimensions; module.exports = Dimensions;
23 changes: 12 additions & 11 deletions React/Modules/RCTDeviceInfo.m
Expand Up @@ -12,6 +12,7 @@
#import "RCTAccessibilityManager.h" #import "RCTAccessibilityManager.h"
#import "RCTAssert.h" #import "RCTAssert.h"
#import "RCTEventDispatcher.h" #import "RCTEventDispatcher.h"
#import "RCTUIUtils.h"
#import "RCTUtils.h" #import "RCTUtils.h"


@implementation RCTDeviceInfo { @implementation RCTDeviceInfo {
Expand Down Expand Up @@ -72,18 +73,18 @@ static BOOL RCTIsIPhoneX() {
{ {
RCTAssertMainQueue(); RCTAssertMainQueue();


// Don't use RCTScreenSize since it the interface orientation doesn't apply to it RCTDimensions dimensions = RCTGetDimensions(bridge.accessibilityManager.multiplier);
CGRect screenSize = [[UIScreen mainScreen] bounds]; typeof (dimensions.window) window = dimensions.window; // Window and Screen are considered equal for iOS.
NSDictionary *dims = @{ NSDictionary<NSString *, NSNumber *> *dims = @{
@"width": @(screenSize.size.width), @"width": @(window.width),
@"height": @(screenSize.size.height), @"height": @(window.height),
@"scale": @(RCTScreenScale()), @"scale": @(window.scale),
@"fontScale": @(bridge.accessibilityManager.multiplier) @"fontScale": @(window.fontScale)
}; };
return @{ return @{
@"window": dims, @"window": dims,
@"screen": dims @"screen": dims
}; };
} }


- (void)dealloc - (void)dealloc
Expand Down
14 changes: 14 additions & 0 deletions React/React.xcodeproj/project.pbxproj
Expand Up @@ -1203,6 +1203,7 @@
EBF21BFE1FC499840052F4D5 /* InspectorInterfaces.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = EBF21BBA1FC498270052F4D5 /* InspectorInterfaces.h */; }; EBF21BFE1FC499840052F4D5 /* InspectorInterfaces.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = EBF21BBA1FC498270052F4D5 /* InspectorInterfaces.h */; };
EBF21BFF1FC4998E0052F4D5 /* InspectorInterfaces.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBF21BBB1FC498270052F4D5 /* InspectorInterfaces.cpp */; }; EBF21BFF1FC4998E0052F4D5 /* InspectorInterfaces.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBF21BBB1FC498270052F4D5 /* InspectorInterfaces.cpp */; };
EBF21C001FC499A80052F4D5 /* InspectorInterfaces.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBF21BBB1FC498270052F4D5 /* InspectorInterfaces.cpp */; }; EBF21C001FC499A80052F4D5 /* InspectorInterfaces.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBF21BBB1FC498270052F4D5 /* InspectorInterfaces.cpp */; };
F1EFDA50201F661000EE6E4C /* RCTUIUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EFDA4E201F660F00EE6E4C /* RCTUIUtils.m */; };
FEFAAC9E1FDB89B50057BBE0 /* RCTRedBoxExtraDataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FEFAAC9C1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.m */; }; FEFAAC9E1FDB89B50057BBE0 /* RCTRedBoxExtraDataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FEFAAC9C1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.m */; };
FEFAAC9F1FDB89B50057BBE0 /* RCTRedBoxExtraDataViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFAAC9D1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.h */; }; FEFAAC9F1FDB89B50057BBE0 /* RCTRedBoxExtraDataViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFAAC9D1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.h */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
Expand Down Expand Up @@ -2279,6 +2280,8 @@
EBF21BBB1FC498270052F4D5 /* InspectorInterfaces.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorInterfaces.cpp; sourceTree = "<group>"; }; EBF21BBB1FC498270052F4D5 /* InspectorInterfaces.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorInterfaces.cpp; sourceTree = "<group>"; };
EBF21BDC1FC498900052F4D5 /* libjsinspector.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjsinspector.a; sourceTree = BUILT_PRODUCTS_DIR; }; EBF21BDC1FC498900052F4D5 /* libjsinspector.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjsinspector.a; sourceTree = BUILT_PRODUCTS_DIR; };
EBF21BFA1FC4989A0052F4D5 /* libjsinspector-tvOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libjsinspector-tvOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; EBF21BFA1FC4989A0052F4D5 /* libjsinspector-tvOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libjsinspector-tvOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
F1EFDA4E201F660F00EE6E4C /* RCTUIUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIUtils.m; sourceTree = "<group>"; };
F1EFDA4F201F660F00EE6E4C /* RCTUIUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTUIUtils.h; sourceTree = "<group>"; };
FEFAAC9C1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRedBoxExtraDataViewController.m; sourceTree = "<group>"; }; FEFAAC9C1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRedBoxExtraDataViewController.m; sourceTree = "<group>"; };
FEFAAC9D1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRedBoxExtraDataViewController.h; sourceTree = "<group>"; }; FEFAAC9D1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRedBoxExtraDataViewController.h; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
Expand Down Expand Up @@ -2888,6 +2891,7 @@
657734881EE8352500A0E9EA /* Inspector */, 657734881EE8352500A0E9EA /* Inspector */,
13B07FE01A69315300A75B9A /* Modules */, 13B07FE01A69315300A75B9A /* Modules */,
1450FF7F1BCFF28A00208362 /* Profiler */, 1450FF7F1BCFF28A00208362 /* Profiler */,
F1EFDA4D201F660F00EE6E4C /* UIUtils */,
13B07FF31A6947C200A75B9A /* Views */, 13B07FF31A6947C200A75B9A /* Views */,
); );
name = React; name = React;
Expand Down Expand Up @@ -3048,6 +3052,15 @@
path = jsinspector; path = jsinspector;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
F1EFDA4D201F660F00EE6E4C /* UIUtils */ = {
isa = PBXGroup;
children = (
F1EFDA4F201F660F00EE6E4C /* RCTUIUtils.h */,
F1EFDA4E201F660F00EE6E4C /* RCTUIUtils.m */,
);
path = UIUtils;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */


/* Begin PBXHeadersBuildPhase section */ /* Begin PBXHeadersBuildPhase section */
Expand Down Expand Up @@ -4508,6 +4521,7 @@
13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */, 13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */,
13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */, 13B0801B1A69489C00A75B9A /* RCTNavigatorManager.m in Sources */,
916F9C2D1F743F57002E5920 /* RCTModalManager.m in Sources */, 916F9C2D1F743F57002E5920 /* RCTModalManager.m in Sources */,
F1EFDA50201F661000EE6E4C /* RCTUIUtils.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
Expand Down
37 changes: 37 additions & 0 deletions React/UIUtils/RCTUIUtils.h
@@ -0,0 +1,37 @@
/**
* 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 <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

#ifdef __cplusplus
extern "C" {
#endif

// Get window and screen dimensions
typedef struct {
struct {
CGFloat width, height, scale, fontScale;
} window, screen;
} RCTDimensions;
extern __attribute__((visibility("default")))
RCTDimensions RCTGetDimensions(CGFloat fontScale);

// Get font size multiplier for font base size (Large) by content size category
extern __attribute__((visibility("default")))
CGFloat RCTGetMultiplierForContentSizeCategory(UIContentSizeCategory category);

#ifdef __cplusplus
}
#endif

NS_ASSUME_NONNULL_END
52 changes: 52 additions & 0 deletions React/UIUtils/RCTUIUtils.m
@@ -0,0 +1,52 @@
/**
* 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 "RCTUIUtils.h"

RCTDimensions RCTGetDimensions(CGFloat fontScale)
{
UIScreen *mainScreen = UIScreen.mainScreen;
CGSize screenSize = mainScreen.bounds.size;
RCTDimensions result;
typeof (result.window) dims = {
.width = screenSize.width,
.height = screenSize.height,
.scale = mainScreen.scale,
.fontScale = fontScale
};
result.window = dims;
result.screen = dims;

return result;
}

CGFloat RCTGetMultiplierForContentSizeCategory(UIContentSizeCategory category)
{
static NSDictionary<NSString *, NSNumber *> *multipliers = nil;
static dispatch_once_t token;
dispatch_once(&token, ^{
multipliers = @{
UIContentSizeCategoryExtraSmall: @0.823,
UIContentSizeCategorySmall: @0.882,
UIContentSizeCategoryMedium: @0.941,
UIContentSizeCategoryLarge: @1.0,
UIContentSizeCategoryExtraLarge: @1.118,
UIContentSizeCategoryExtraExtraLarge: @1.235,
UIContentSizeCategoryExtraExtraExtraLarge: @1.353,
UIContentSizeCategoryAccessibilityMedium: @1.786,
UIContentSizeCategoryAccessibilityLarge: @2.143,
UIContentSizeCategoryAccessibilityExtraLarge: @2.643,
UIContentSizeCategoryAccessibilityExtraExtraLarge: @3.143,
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @3.571
};
});

double value = multipliers[category].doubleValue;
return value > 0.0 ? value : 1.0;
}

0 comments on commit 429fcc8

Please sign in to comment.