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
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
*/
'use strict';

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

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

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

static getDimensions(): {[key:string]: Object} {
if (dimensionsInitialized) {
return dimensions;
}

// 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
// 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) {
// parse/stringify => Clone hack
dims = JSON.parse(JSON.stringify(dims));

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

/**
* 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];
return dimensions;
}

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

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

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

@implementation RCTDeviceInfo {
Expand Down Expand Up @@ -72,18 +73,18 @@ static BOOL RCTIsIPhoneX() {
{
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)
};
RCTDimensions dimensions = RCTGetDimensions(bridge.accessibilityManager.multiplier);
typeof (dimensions.window) window = dimensions.window; // Window and Screen are considered equal for iOS.
NSDictionary<NSString *, NSNumber *> *dims = @{
@"width": @(window.width),
@"height": @(window.height),
@"scale": @(window.scale),
@"fontScale": @(window.fontScale)
};
return @{
@"window": dims,
@"screen": dims
};
@"window": dims,
@"screen": dims
};
}

- (void)dealloc
Expand Down
14 changes: 14 additions & 0 deletions React/React.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,7 @@
EBF21BFE1FC499840052F4D5 /* InspectorInterfaces.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = EBF21BBA1FC498270052F4D5 /* InspectorInterfaces.h */; };
EBF21BFF1FC4998E0052F4D5 /* 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 */; };
FEFAAC9F1FDB89B50057BBE0 /* RCTRedBoxExtraDataViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFAAC9D1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.h */; };
/* 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>"; };
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; };
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>"; };
FEFAAC9D1FDB89B40057BBE0 /* RCTRedBoxExtraDataViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRedBoxExtraDataViewController.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -2888,6 +2891,7 @@
657734881EE8352500A0E9EA /* Inspector */,
13B07FE01A69315300A75B9A /* Modules */,
1450FF7F1BCFF28A00208362 /* Profiler */,
F1EFDA4D201F660F00EE6E4C /* UIUtils */,
13B07FF31A6947C200A75B9A /* Views */,
);
name = React;
Expand Down Expand Up @@ -3048,6 +3052,15 @@
path = jsinspector;
sourceTree = "<group>";
};
F1EFDA4D201F660F00EE6E4C /* UIUtils */ = {
isa = PBXGroup;
children = (
F1EFDA4F201F660F00EE6E4C /* RCTUIUtils.h */,
F1EFDA4E201F660F00EE6E4C /* RCTUIUtils.m */,
);
path = UIUtils;
sourceTree = "<group>";
};
/* End PBXGroup section */

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