diff --git a/Examples/Movies/Info.plist b/Examples/Movies/Info.plist
index 1c298405a..3c7e8c72e 100644
--- a/Examples/Movies/Info.plist
+++ b/Examples/Movies/Info.plist
@@ -28,6 +28,8 @@
armv7
+ UIViewControllerBasedStatusBarAppearance
+
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
diff --git a/Examples/TicTacToe/Info.plist b/Examples/TicTacToe/Info.plist
index 1c298405a..9a7ca7e3c 100644
--- a/Examples/TicTacToe/Info.plist
+++ b/Examples/TicTacToe/Info.plist
@@ -34,5 +34,7 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UIViewControllerBasedStatusBarAppearance
+
diff --git a/Examples/UIExplorer/Info.plist b/Examples/UIExplorer/Info.plist
index 1c298405a..9a7ca7e3c 100644
--- a/Examples/UIExplorer/Info.plist
+++ b/Examples/UIExplorer/Info.plist
@@ -34,5 +34,7 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UIViewControllerBasedStatusBarAppearance
+
diff --git a/Examples/UIExplorer/StatusBarIOSExample.js b/Examples/UIExplorer/StatusBarIOSExample.js
new file mode 100644
index 000000000..1ee83419a
--- /dev/null
+++ b/Examples/UIExplorer/StatusBarIOSExample.js
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2004-present Facebook. All Rights Reserved.
+ *
+ * @providesModule StatusBarIOSExample
+ */
+'use strict';
+
+var React = require('react-native');
+var {
+ StyleSheet,
+ View,
+ Text,
+ TouchableHighlight,
+ StatusBarIOS,
+} = React;
+
+exports.framework = 'React';
+exports.title = 'StatusBarIOS';
+exports.description = 'Module for controlling iOS status bar';
+exports.examples = [{
+ title: 'Status Bar Style',
+ render() {
+ return (
+
+ {Object.keys(StatusBarIOS.Style).map((key) =>
+ StatusBarIOS.setStyle(StatusBarIOS.Style[key])}>
+
+ setStyle(StatusBarIOS.Style.{key})
+
+
+ )}
+
+ );
+ },
+}, {
+ title: 'Status Bar Style Animated',
+ render() {
+ return (
+
+ {Object.keys(StatusBarIOS.Style).map((key) =>
+ StatusBarIOS.setStyle(StatusBarIOS.Style[key], true)}>
+
+ setStyle(StatusBarIOS.Style.{key}, true)
+
+
+ )}
+
+ );
+ },
+}, {
+ title: 'Status Bar Hidden',
+ render() {
+ return (
+
+ {Object.keys(StatusBarIOS.Animation).map((key) =>
+
+ StatusBarIOS.setHidden(true, StatusBarIOS.Animation[key])}>
+
+ setHidden(true, StatusBarIOS.Animation.{key})
+
+
+ StatusBarIOS.setHidden(false, StatusBarIOS.Animation[key])}>
+
+ setHidden(false, StatusBarIOS.Animation.{key})
+
+
+
+ )}
+
+ );
+ },
+}];
+
+var styles = StyleSheet.create({
+ wrapper: {
+ borderRadius: 5,
+ marginBottom: 5,
+ },
+ button: {
+ backgroundColor: '#eeeeee',
+ padding: 10,
+ },
+});
diff --git a/Examples/UIExplorer/UIExplorerList.js b/Examples/UIExplorer/UIExplorerList.js
index 207ad2d66..9effbf8e4 100644
--- a/Examples/UIExplorer/UIExplorerList.js
+++ b/Examples/UIExplorer/UIExplorerList.js
@@ -25,6 +25,7 @@ var EXAMPLES = [
require('./ImageExample'),
require('./ListViewSimpleExample'),
require('./NavigatorIOSExample'),
+ require('./StatusBarIOSExample'),
require('./PointerEventsExample'),
require('./TouchableExample'),
require('./SpinnerExample'),
diff --git a/Libraries/Components/StatusBar/StatusBarIOS.js b/Libraries/Components/StatusBar/StatusBarIOS.js
new file mode 100644
index 000000000..eaea1cc7a
--- /dev/null
+++ b/Libraries/Components/StatusBar/StatusBarIOS.js
@@ -0,0 +1,35 @@
+/**
+ * Copyright 2004-present Facebook. All Rights Reserved.
+ *
+ * @providesModule StatusBarIOS
+ * @flow
+ */
+'use strict';
+
+var { RKStatusBarManager } = require('NativeModules');
+
+var StatusBarIOS = {
+
+ Style: {
+ default: RKStatusBarManager.Style.default,
+ lightContent: RKStatusBarManager.Style.lightContent
+ },
+
+ Animation: {
+ none: RKStatusBarManager.Animation.none,
+ fade: RKStatusBarManager.Animation.fade,
+ slide: RKStatusBarManager.Animation.slide,
+ },
+
+ setStyle(style: number, animated: boolean) {
+ animated = animated || false;
+ RKStatusBarManager.setStyle(style, animated);
+ },
+
+ setHidden(hidden: boolean, animation: number) {
+ animation = animation || StatusBarIOS.Animation.none;
+ RKStatusBarManager.setHidden(hidden, animation);
+ },
+};
+
+module.exports = StatusBarIOS;
diff --git a/Libraries/react-native/react-native.js b/Libraries/react-native/react-native.js
index 12a82fefa..b483534e1 100644
--- a/Libraries/react-native/react-native.js
+++ b/Libraries/react-native/react-native.js
@@ -11,6 +11,7 @@ var Image = require('Image');
var ListView = require('ListView');
var ListViewDataSource = require('ListViewDataSource');
var NavigatorIOS = require('NavigatorIOS');
+var StatusBarIOS = require('StatusBarIOS');
var PixelRatio = require('PixelRatio');
var React = require('React');
var ScrollView = require('ScrollView');
@@ -34,6 +35,7 @@ var ReactNative = {
ListView,
ListViewDataSource,
NavigatorIOS,
+ StatusBarIOS,
PixelRatio,
ScrollView,
SpinnerIOS,
diff --git a/ReactKit/Modules/RCTStatusBarManager.h b/ReactKit/Modules/RCTStatusBarManager.h
new file mode 100644
index 000000000..830393521
--- /dev/null
+++ b/ReactKit/Modules/RCTStatusBarManager.h
@@ -0,0 +1,9 @@
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#import
+
+#import "RCTBridgeModule.h"
+
+@interface RCTStatusBarManager : NSObject
+
+@end
diff --git a/ReactKit/Modules/RCTStatusBarManager.m b/ReactKit/Modules/RCTStatusBarManager.m
new file mode 100644
index 000000000..9a49cdd62
--- /dev/null
+++ b/ReactKit/Modules/RCTStatusBarManager.m
@@ -0,0 +1,67 @@
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#import "RCTStatusBarManager.h"
+
+#import "RCTLog.h"
+
+@implementation RCTStatusBarManager
+
+static BOOL RCTViewControllerBasedStatusBarAppearance()
+{
+ static BOOL value;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ value = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"] boolValue];
+ });
+
+ return value;
+}
+
+- (void)setStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated
+{
+ RCT_EXPORT();
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+
+ if (RCTViewControllerBasedStatusBarAppearance()) {
+ RCTLogError(@"RCTStatusBarManager module requires that the \
+ UIViewControllerBasedStatusBarAppearance key in the Info.plist is set to NO");
+ } else {
+ [[UIApplication sharedApplication] setStatusBarStyle:statusBarStyle
+ animated:animated];
+ }
+ });
+}
+
+- (void)setHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation
+{
+ RCT_EXPORT();
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+
+ if (RCTViewControllerBasedStatusBarAppearance()) {
+ RCTLogError(@"RCTStatusBarManager module requires that the \
+ UIViewControllerBasedStatusBarAppearance key in the Info.plist is set to NO");
+ } else {
+ [[UIApplication sharedApplication] setStatusBarHidden:hidden
+ withAnimation:animation];
+ }
+ });
+}
+
++ (NSDictionary *)constantsToExport
+{
+ return @{
+ @"Style": @{
+ @"default": @(UIStatusBarStyleDefault),
+ @"lightContent": @(UIStatusBarStyleLightContent),
+ },
+ @"Animation": @{
+ @"none": @(UIStatusBarAnimationNone),
+ @"fade": @(UIStatusBarAnimationFade),
+ @"slide": @(UIStatusBarAnimationSlide),
+ },
+ };
+}
+
+@end
diff --git a/ReactKit/ReactKit.xcodeproj/project.pbxproj b/ReactKit/ReactKit.xcodeproj/project.pbxproj
index 4610f9f75..483e4bc55 100644
--- a/ReactKit/ReactKit.xcodeproj/project.pbxproj
+++ b/ReactKit/ReactKit.xcodeproj/project.pbxproj
@@ -16,6 +16,7 @@
137029491A698FF000575408 /* RCTNetworkImageViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 137029401A698FF000575408 /* RCTNetworkImageViewManager.m */; };
137029501A6990A100575408 /* RCTNetworkImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1370294F1A6990A100575408 /* RCTNetworkImageView.m */; };
137029531A69923600575408 /* RCTImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 137029521A69923600575408 /* RCTImageDownloader.m */; };
+ 13723B501A82FD3C00F88898 /* RCTStatusBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */; };
13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */; };
13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FE81A69327A00A75B9A /* RCTAlertManager.m */; };
13B07FF01A69327A00A75B9A /* RCTExceptionsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FEA1A69327A00A75B9A /* RCTExceptionsManager.m */; };
@@ -82,6 +83,8 @@
137029521A69923600575408 /* RCTImageDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageDownloader.m; sourceTree = ""; };
137029571A6C197000575408 /* RCTRawTextManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRawTextManager.h; sourceTree = ""; };
137029581A6C197000575408 /* RCTRawTextManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRawTextManager.m; sourceTree = ""; };
+ 13723B4E1A82FD3C00F88898 /* RCTStatusBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTStatusBarManager.h; sourceTree = ""; };
+ 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTStatusBarManager.m; sourceTree = ""; };
13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTKeyCommands.h; sourceTree = ""; };
13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTKeyCommands.m; sourceTree = ""; };
13B07FC71A68125100A75B9A /* Layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Layout.c; sourceTree = ""; };
@@ -206,6 +209,8 @@
13B07FEE1A69327A00A75B9A /* RCTTiming.m */,
13E067481A70F434002CDEE1 /* RCTUIManager.h */,
13E067491A70F434002CDEE1 /* RCTUIManager.m */,
+ 13723B4E1A82FD3C00F88898 /* RCTStatusBarManager.h */,
+ 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */,
);
path = Modules;
sourceTree = "";
@@ -403,6 +408,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 13723B501A82FD3C00F88898 /* RCTStatusBarManager.m in Sources */,
13B0801E1A69489C00A75B9A /* RCTTextField.m in Sources */,
13B07FEF1A69327A00A75B9A /* RCTAlertManager.m in Sources */,
83CBBACC1A6023D300E9B192 /* RCTConvert.m in Sources */,
diff --git a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js
index d255a3c3c..f80bd0b3b 100644
--- a/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js
+++ b/packager/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js
@@ -325,10 +325,26 @@ DependecyGraph.prototype._lookupName = function(modulePath) {
}
};
+DependecyGraph.prototype._deleteModule = function(module) {
+ delete this._graph[module.path];
+
+ // Others may keep a reference so we mark it as deleted.
+ module.deleted = true;
+
+ // Haste allows different module to have the same id.
+ if (this._moduleById[module.id] === module) {
+ delete this._moduleById[module.id];
+ }
+};
+
/**
- * Update the graph and idices with the module.
+ * Update the graph and indices with the module.
*/
DependecyGraph.prototype._updateGraphWithModule = function(module) {
+ if (this._graph[module.path]) {
+ this._deleteModule(this._graph[module.path]);
+ }
+
this._graph[module.path] = module;
if (this._moduleById[module.id]) {
@@ -389,15 +405,7 @@ DependecyGraph.prototype._processFileChange = function(eventType, filePath, root
return;
}
- delete this._graph[module];
-
- // Others may keep a reference so we mark it as deleted.
- module.deleted = true;
-
- // Modules may have same id.
- if (this._moduleById[module.id] === module) {
- delete this._moduleById[module.id];
- }
+ this._deleteModule(module);
} else if (!(stat && stat.isDirectory())) {
var self = this;
this._loading = this._loading.then(function() {