Browse Source

copy controllers code to here - a start of something beautiful

Daniel Zlotin 7 years ago
parent
commit
18b1e8f59b
60 changed files with 8853 additions and 0 deletions
  1. 10
    0
      controllers/Constants.js
  2. 309
    0
      controllers/index.js
  3. 81
    0
      controllers/utils.js
  4. 22
    0
      ios/Helpers/RCCTitleViewHelper.h
  5. 217
    0
      ios/Helpers/RCCTitleViewHelper.m
  6. 14
    0
      ios/Helpers/RCTHelpers.h
  7. 78
    0
      ios/Helpers/RCTHelpers.m
  8. 77
    0
      ios/RCCDrawerController/MMDrawerController/MMDrawerBarButtonItem.h
  9. 302
    0
      ios/RCCDrawerController/MMDrawerController/MMDrawerBarButtonItem.m
  10. 111
    0
      ios/RCCDrawerController/MMDrawerController/MMDrawerController+Subclass.h
  11. 480
    0
      ios/RCCDrawerController/MMDrawerController/MMDrawerController.h
  12. 1529
    0
      ios/RCCDrawerController/MMDrawerController/MMDrawerController.m
  13. 61
    0
      ios/RCCDrawerController/MMDrawerController/MMDrawerVisualState.h
  14. 150
    0
      ios/RCCDrawerController/MMDrawerController/MMDrawerVisualState.m
  15. 42
    0
      ios/RCCDrawerController/MMDrawerController/MMExampleDrawerVisualStateManager.h
  16. 97
    0
      ios/RCCDrawerController/MMDrawerController/MMExampleDrawerVisualStateManager.m
  17. 45
    0
      ios/RCCDrawerController/MMDrawerController/UIViewController+MMDrawerController.h
  18. 64
    0
      ios/RCCDrawerController/MMDrawerController/UIViewController+MMDrawerController.m
  19. 10
    0
      ios/RCCDrawerController/RCCDrawerController.h
  20. 154
    0
      ios/RCCDrawerController/RCCDrawerController.m
  21. 35
    0
      ios/RCCDrawerController/RCCDrawerHelper.h
  22. 96
    0
      ios/RCCDrawerController/RCCDrawerHelper.m
  23. 24
    0
      ios/RCCDrawerController/RCCDrawerProtocol.h
  24. 22
    0
      ios/RCCDrawerController/RCCTheSideBarManagerViewController.h
  25. 258
    0
      ios/RCCDrawerController/RCCTheSideBarManagerViewController.m
  26. 28
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarAirbnbAnimation.h
  27. 135
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarAirbnbAnimation.m
  28. 80
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarAnimation.h
  29. 101
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarAnimation.m
  30. 28
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarFacebookAnimation.h
  31. 83
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarFacebookAnimation.m
  32. 28
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarFeedlyAnimation.h
  33. 89
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarFeedlyAnimation.m
  34. 28
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarFlipboardAnimation.h
  35. 99
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarFlipboardAnimation.m
  36. 28
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarLuvocracyAnimation.h
  37. 111
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarLuvocracyAnimation.m
  38. 28
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarWunderlistAnimation.h
  39. 103
    0
      ios/RCCDrawerController/TheSidebarController/Animations/SidebarWunderlistAnimation.m
  40. 91
    0
      ios/RCCDrawerController/TheSidebarController/TheSidebarController.h
  41. 414
    0
      ios/RCCDrawerController/TheSidebarController/TheSidebarController.m
  42. 18
    0
      ios/RCCExternalViewControllerProtocol.h
  43. 7
    0
      ios/RCCLightBox.h
  44. 235
    0
      ios/RCCLightBox.m
  45. 21
    0
      ios/RCCManager.h
  46. 221
    0
      ios/RCCManager.m
  47. 8
    0
      ios/RCCManagerModule.h
  48. 378
    0
      ios/RCCManagerModule.m
  49. 9
    0
      ios/RCCNavigationController.h
  50. 298
    0
      ios/RCCNavigationController.m
  51. 8
    0
      ios/RCCNotification.h
  52. 462
    0
      ios/RCCNotification.m
  53. 9
    0
      ios/RCCTabBarController.h
  54. 220
    0
      ios/RCCTabBarController.m
  55. 14
    0
      ios/RCCToolBar/RCCToolBar.h
  56. 57
    0
      ios/RCCToolBar/RCCToolBar.m
  57. 23
    0
      ios/RCCViewController.h
  58. 559
    0
      ios/RCCViewController.m
  59. 464
    0
      ios/ReactNativeControllers.xcodeproj/project.pbxproj
  60. 80
    0
      ios/ReactNativeControllers.xcodeproj/xcshareddata/xcschemes/ReactNativeControllers.xcscheme

+ 10
- 0
controllers/Constants.js View File

@@ -0,0 +1,10 @@
1
+
2
+export const MMDRAWER_DOOR = 'door';
3
+export const MMDRAWER_PARALLAX = 'parallax';
4
+export const MMDRAWER_SLIDE = 'slide';
5
+export const MMDRAWER_SLIDE_AND_SCALE = 'slide-and-scale';
6
+
7
+export const THE_SIDEBAR_AIRBNB = 'airbnb';
8
+export const THE_SIDEBAR_FACEBOOK = 'facebook';
9
+export const THE_SIDEBAR_LUVOCRACY = 'luvocracy';
10
+export const THE_SIDEBAR_WUNDER_LIST = 'wunder-list';

+ 309
- 0
controllers/index.js View File

@@ -0,0 +1,309 @@
1
+var OriginalReactNative = require('react-native');
2
+var RCCManager = OriginalReactNative.NativeModules.RCCManager;
3
+var NativeAppEventEmitter = OriginalReactNative.NativeAppEventEmitter;
4
+var utils = require('./utils');
5
+var Constants = require('./Constants');
6
+var resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource');
7
+var processColor = OriginalReactNative.processColor;
8
+
9
+var _controllerRegistry = {};
10
+
11
+function _getRandomId() {
12
+  return (Math.random()*1e20).toString(36);
13
+}
14
+
15
+function _processProperties(properties) {
16
+  for (var property in properties) {
17
+    if (properties.hasOwnProperty(property)) {
18
+      if (property === 'icon' || property.endsWith('Icon') || property.endsWith('Image')) {
19
+        properties[property] = resolveAssetSource(properties[property]);
20
+      }
21
+      if (property === 'color' || property.endsWith('Color')) {
22
+        properties[property] = processColor(properties[property]);
23
+      }
24
+      if (property === 'buttons' || property.endsWith('Buttons')) {
25
+        _processButtons(properties[property]);
26
+      }
27
+    }
28
+  }
29
+}
30
+
31
+function _setListener(callbackId, func) {
32
+  return NativeAppEventEmitter.addListener(callbackId, (...args) => func(...args));
33
+}
34
+
35
+function _processButtons(buttons) {
36
+  if (!buttons) return;
37
+  var unsubscribes = [];
38
+  for (var i = 0 ; i < buttons.length ; i++) {
39
+    buttons[i] = Object.assign({}, buttons[i]);
40
+    var button = buttons[i];
41
+    _processProperties(button);
42
+    if (typeof button.onPress === "function") {
43
+      var onPressId = _getRandomId();
44
+      var onPressFunc = button.onPress;
45
+      button.onPress = onPressId;
46
+      var unsubscribe = _setListener(onPressId, onPressFunc);
47
+      unsubscribes.push(unsubscribe);
48
+    }
49
+  }
50
+  return function () {
51
+    for (var i = 0 ; i < unsubscribes.length ; i++) {
52
+      if (unsubscribes[i]) { unsubscribes[i](); }
53
+    }
54
+  };
55
+}
56
+
57
+function _validateDrawerProps(layout) {
58
+  if (layout.type === "DrawerControllerIOS") {
59
+    let shouldSetToDefault = true;
60
+
61
+    const drawerProps = layout.props;
62
+    if (drawerProps.type === "MMDrawer") {
63
+      [ Constants.MMDRAWER_DOOR, Constants.MMDRAWER_PARALLAX, Constants.MMDRAWER_SLIDE, Constants.MMDRAWER_SLIDE_AND_SCALE].forEach(function(type) {
64
+        if (type === drawerProps.animationType){
65
+          shouldSetToDefault = false;
66
+        }
67
+      })
68
+    }
69
+    else if (drawerProps.type === "TheSideBar") {
70
+      [Constants.THE_SIDEBAR_AIRBNB, Constants.THE_SIDEBAR_FACEBOOK, Constants.THE_SIDEBAR_LUVOCRACY, Constants.THE_SIDEBAR_WUNDER_LIST].forEach(function(type) {
71
+        if (type === drawerProps.animationType){
72
+          shouldSetToDefault = false;
73
+        }
74
+      })
75
+    }
76
+
77
+    if (shouldSetToDefault) {
78
+      console.warn("Set to default type=MMDrawer animationType=slide");
79
+      drawerProps.type = "MMDrawer";
80
+      drawerProps.animationType = "slide";
81
+    }
82
+  }
83
+}
84
+
85
+
86
+var Controllers = {
87
+
88
+  createClass: function (app) {
89
+    return app;
90
+  },
91
+
92
+  hijackReact: function () {
93
+    return {
94
+      createElement: function(type, props) {
95
+        var children = Array.prototype.slice.call(arguments, 2);
96
+        var flatChildren = utils.flattenDeep(children);
97
+        props = Object.assign({}, props);
98
+        _processProperties(props);
99
+        if (props['style']) {
100
+          props['style'] = Object.assign({}, props['style']);
101
+          _processProperties(props['style']);
102
+        }
103
+        return {
104
+          'type': type.name,
105
+          'props': props,
106
+          'children': flatChildren
107
+        };
108
+      },
109
+
110
+      ControllerRegistry: Controllers.ControllerRegistry,
111
+      TabBarControllerIOS: {name: 'TabBarControllerIOS', Item: {name: 'TabBarControllerIOS.Item'}},
112
+      NavigationControllerIOS: {name: 'NavigationControllerIOS'},
113
+      ViewControllerIOS: {name: 'ViewControllerIOS'},
114
+      DrawerControllerIOS: {name: 'DrawerControllerIOS'},
115
+    };
116
+  },
117
+
118
+  ControllerRegistry: {
119
+    registerController: function (appKey, getControllerFunc) {
120
+      _controllerRegistry[appKey] = getControllerFunc();
121
+    },
122
+    setRootController: function (appKey, animationType = 'none', passProps = {}) {
123
+      var controller = _controllerRegistry[appKey];
124
+      if (controller === undefined) return;
125
+      var layout = controller.render();
126
+      _validateDrawerProps(layout);
127
+      RCCManager.setRootController(layout, animationType, passProps);
128
+    }
129
+  },
130
+
131
+  NavigationControllerIOS: function (id) {
132
+    return {
133
+      push: function (params) {
134
+        var unsubscribes = [];
135
+        if (params['style']) {
136
+          params['style'] = Object.assign({}, params['style']);
137
+          _processProperties(params['style']);
138
+        }
139
+        if (params['titleImage']) {
140
+          params['titleImage'] = resolveAssetSource(params['titleImage']);
141
+        }
142
+        if (params['leftButtons']) {
143
+          var unsubscribe = _processButtons(params['leftButtons']);
144
+          unsubscribes.push(unsubscribe);
145
+        }
146
+        if (params['rightButtons']) {
147
+          var unsubscribe = _processButtons(params['rightButtons']);
148
+          unsubscribes.push(unsubscribe);
149
+        }
150
+        RCCManager.NavigationControllerIOS(id, "push", params);
151
+        return function() {
152
+          for (var i = 0 ; i < unsubscribes.length ; i++) {
153
+            if (unsubscribes[i]) { unsubscribes[i](); }
154
+          }
155
+        };
156
+      },
157
+      pop: function (params) {
158
+        RCCManager.NavigationControllerIOS(id, "pop", params);
159
+      },
160
+      popToRoot: function (params) {
161
+        RCCManager.NavigationControllerIOS(id, "popToRoot", params);
162
+      },
163
+      setTitle: function (params) {
164
+        if (params['style']) {
165
+          params['style'] = Object.assign({}, params['style']);
166
+          _processProperties(params['style']);
167
+        }
168
+        if (params['titleImage']) {
169
+          params['titleImage'] = resolveAssetSource(params['titleImage']);
170
+        }
171
+        RCCManager.NavigationControllerIOS(id, "setTitle", params);
172
+      },
173
+      resetTo: function (params) {
174
+        var unsubscribes = [];
175
+        if (params['style']) {
176
+          params['style'] = Object.assign({}, params['style']);
177
+          _processProperties(params['style']);
178
+        }
179
+        if (params['leftButtons']) {
180
+          var unsubscribe = _processButtons(params['leftButtons']);
181
+          unsubscribes.push(unsubscribe);
182
+        }
183
+        if (params['rightButtons']) {
184
+          var unsubscribe = _processButtons(params['rightButtons']);
185
+          unsubscribes.push(unsubscribe);
186
+        }
187
+        RCCManager.NavigationControllerIOS(id, "resetTo", params);
188
+        return function() {
189
+          for (var i = 0 ; i < unsubscribes.length ; i++) {
190
+            if (unsubscribes[i]) { unsubscribes[i](); }
191
+          }
192
+        };
193
+      },
194
+      setLeftButton: function () {
195
+        console.error('setLeftButton is deprecated, see setLeftButtons');
196
+      },
197
+      setLeftButtons: function (buttons, animated = false) {
198
+        var unsubscribe = _processButtons(buttons);
199
+        RCCManager.NavigationControllerIOS(id, "setButtons", {buttons: buttons, side: "left", animated: animated});
200
+        return unsubscribe;
201
+      },
202
+      setRightButtons: function (buttons, animated = false) {
203
+        var unsubscribe = _processButtons(buttons);
204
+        RCCManager.NavigationControllerIOS(id, "setButtons", {buttons: buttons, side: "right", animated: animated});
205
+        return unsubscribe;
206
+      },
207
+      setHidden: function(params = {}) {
208
+        RCCManager.NavigationControllerIOS(id, "setHidden", params);
209
+      }
210
+    };
211
+  },
212
+
213
+  DrawerControllerIOS: function (id) {
214
+    return {
215
+      open: function (params) {
216
+        return RCCManager.DrawerControllerIOS(id, "open", params);
217
+      },
218
+      close: function (params) {
219
+        return RCCManager.DrawerControllerIOS(id, "close", params);
220
+      },
221
+      toggle: function (params) {
222
+        return RCCManager.DrawerControllerIOS(id, "toggle", params);
223
+      },
224
+      setStyle: function (params) {
225
+        return RCCManager.DrawerControllerIOS(id, "setStyle", params);
226
+      }
227
+    };
228
+  },
229
+
230
+  TabBarControllerIOS: function (id) {
231
+    return {
232
+      setHidden: function (params) {
233
+        return RCCManager.TabBarControllerIOS(id, "setTabBarHidden", params);
234
+      },
235
+      setBadge: function (params) {
236
+        return RCCManager.TabBarControllerIOS(id, "setBadge", params);
237
+      },
238
+      switchTo: function (params) {
239
+        return RCCManager.TabBarControllerIOS(id, "switchTo", params);
240
+      }
241
+    };
242
+  },
243
+
244
+  Modal: {
245
+    showLightBox: function(params) {
246
+      params['style'] = Object.assign({}, params['style']);
247
+      _processProperties(params['style']);
248
+      RCCManager.modalShowLightBox(params);
249
+    },
250
+    dismissLightBox: function() {
251
+      RCCManager.modalDismissLightBox();
252
+    },
253
+    showController: function(appKey, animationType = 'slide-up', passProps = {}) {
254
+      var controller = _controllerRegistry[appKey];
255
+      if (controller === undefined) return;
256
+      var layout = controller.render();
257
+      _validateDrawerProps(layout);
258
+      RCCManager.showController(layout, animationType, passProps);
259
+    },
260
+    dismissController: function(animationType = 'slide-down') {
261
+      RCCManager.dismissController(animationType);
262
+    },
263
+    dismissAllControllers: function(animationType = 'slide-down') {
264
+      RCCManager.dismissAllControllers(animationType);
265
+    }
266
+  },
267
+
268
+  Notification: {
269
+    show: async function(params = {}) {
270
+      await RCCManager.showNotification(params);
271
+    },
272
+    dismiss: async function(params = {}) {
273
+      await RCCManager.dismissNotification(params);
274
+    },
275
+    AnimationPresets: {
276
+      default: {
277
+        animated: true,
278
+        duration: 0.5,
279
+        damping: 0.65,
280
+        type: 'slide-down',
281
+        fade: true
282
+      },
283
+      simple: {
284
+        animated: true,
285
+        duration: 0.3,
286
+        type: 'slide-down',
287
+        fade: true
288
+      },
289
+      swing: {
290
+        animated: true,
291
+        duration: 0.65,
292
+        damping: 0.6,
293
+        type: 'swing'
294
+      },
295
+      fade: {
296
+        animated: true,
297
+        duration: 0.3,
298
+        fade: true
299
+      }
300
+    }
301
+  },
302
+
303
+  NavigationToolBarIOS: OriginalReactNative.requireNativeComponent('RCCToolBar', null),
304
+
305
+  Constants: Constants
306
+};
307
+
308
+module.exports = Controllers;
309
+

+ 81
- 0
controllers/utils.js View File

@@ -0,0 +1,81 @@
1
+var INFINITY = 1 / 0;
2
+var MAX_SAFE_INTEGER = 9007199254740991;
3
+
4
+function flattenDeep(array) {
5
+  var length = array ? array.length : 0;
6
+  return length ? baseFlatten(array, INFINITY) : [];
7
+}
8
+
9
+function baseFlatten(array, depth, isStrict, result) {
10
+  result || (result = []);
11
+  var index = -1, length = array.length;
12
+  while (++index < length) {
13
+    var value = array[index];
14
+    if (depth > 0 && isArrayLikeObject(value) &&
15
+        (isStrict || isArray(value) || isArguments(value))) {
16
+      if (depth > 1) {
17
+        // Recursively flatten arrays (susceptible to call stack limits).
18
+        baseFlatten(value, depth - 1, isStrict, result);
19
+      } else {
20
+        arrayPush(result, value);
21
+      }
22
+    } else if (!isStrict) {
23
+      result[result.length] = value;
24
+    }
25
+  }
26
+  return result;
27
+}
28
+
29
+function isArguments(value) {
30
+  // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode.
31
+  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
32
+    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
33
+}
34
+
35
+var isArray = Array.isArray;
36
+
37
+function isArrayLikeObject(value) {
38
+  return isObjectLike(value) && isArrayLike(value);
39
+}
40
+
41
+function isObjectLike(value) {
42
+  return !!value && typeof value == 'object';
43
+}
44
+
45
+function isArrayLike(value) {
46
+  return value != null &&
47
+    !(typeof value == 'function' && isFunction(value)) && isLength(getLength(value));
48
+}
49
+
50
+function isFunction(value) {
51
+  // The use of `Object#toString` avoids issues with the `typeof` operator
52
+  // in Safari 8 which returns 'object' for typed array constructors, and
53
+  // PhantomJS 1.9 which returns 'function' for `NodeList` instances.
54
+  var tag = isObject(value) ? objectToString.call(value) : '';
55
+  return tag == funcTag || tag == genTag;
56
+}
57
+
58
+function isLength(value) {
59
+  return typeof value == 'number' &&
60
+    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
61
+}
62
+
63
+var getLength = baseProperty('length');
64
+
65
+function baseProperty(key) {
66
+  return function(object) {
67
+    return object == null ? undefined : object[key];
68
+  };
69
+}
70
+
71
+function arrayPush(array, values) {
72
+  var index = -1, length = values.length, offset = array.length;
73
+  while (++index < length) {
74
+    array[offset + index] = values[index];
75
+  }
76
+  return array;
77
+}
78
+
79
+module.exports = {
80
+  flattenDeep: flattenDeep
81
+};

+ 22
- 0
ios/Helpers/RCCTitleViewHelper.h View File

@@ -0,0 +1,22 @@
1
+//
2
+//  RCCTitleViewHelper.h
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Ran Greenberg on 06/09/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import <UIKit/UIKit.h>
11
+
12
+@interface RCCTitleViewHelper : NSObject
13
+
14
+
15
+- (instancetype)init:(UIViewController*)viewController
16
+navigationController:(UINavigationController*)navigationController
17
+               title:(NSString*)title subtitle:(NSString*)subtitle
18
+      titleImageData:(id)titleImageData;
19
+
20
+-(void)setup:(NSDictionary*)style;
21
+
22
+@end

+ 217
- 0
ios/Helpers/RCCTitleViewHelper.m View File

@@ -0,0 +1,217 @@
1
+//
2
+//  RCCTitleViewHelper.m
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Ran Greenberg on 06/09/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import "RCCTitleViewHelper.h"
10
+#import "RCTConvert.h"
11
+
12
+@interface RCCTitleViewHelper ()
13
+
14
+@property (nonatomic, weak) UIViewController *viewController;
15
+@property (nonatomic, weak) UINavigationController *navigationController;
16
+
17
+@property (nonatomic, strong) NSString *title;
18
+@property (nonatomic, strong) NSString *subtitle;
19
+@property (nonatomic, strong) id titleImageData;
20
+
21
+@property (nonatomic, strong) UIView *titleView;
22
+
23
+@end
24
+
25
+
26
+@implementation RCCTitleViewHelper
27
+
28
+- (instancetype)init:(UIViewController*)viewController
29
+navigationController:(UINavigationController*)navigationController
30
+               title:(NSString*)title subtitle:(NSString*)subtitle
31
+      titleImageData:(id)titleImageData
32
+{
33
+    self = [super init];
34
+    if (self) {
35
+        self.viewController = viewController;
36
+        self.navigationController = navigationController;
37
+        self.title = title;
38
+        self.subtitle = subtitle;
39
+        self.titleImageData = titleImageData;
40
+    }
41
+    return self;
42
+}
43
+
44
+-(void)setup:(NSDictionary*)style
45
+{
46
+    if (!self.navigationController)
47
+    {
48
+        return;
49
+    }
50
+    
51
+    CGRect navigationBarBounds = self.navigationController.navigationBar.bounds;
52
+    
53
+    UILabel *titleLabel;
54
+    UILabel *subtitleLabel;
55
+    
56
+    self.titleView = [[UIView alloc] initWithFrame:navigationBarBounds];
57
+    self.titleView.backgroundColor = [UIColor clearColor];
58
+    self.titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
59
+    self.titleView.clipsToBounds = YES;
60
+    
61
+    
62
+    self.viewController.title = self.title;
63
+    
64
+    if ([self isTitleOnly]) {
65
+        self.viewController.navigationItem.titleView = nil;
66
+        return;
67
+    }
68
+    
69
+    if ([self isTitleImage])
70
+    {
71
+        [self setupTitleImage];
72
+        return;
73
+    }
74
+    
75
+    if (self.subtitle)
76
+    {
77
+        subtitleLabel = [self setupSubtitle:style];
78
+    }
79
+    
80
+    if (self.title)
81
+    {
82
+        titleLabel = [self setupTitle:style];
83
+    }
84
+    
85
+    [self centerTitleView:navigationBarBounds titleLabel:titleLabel subtitleLabel:subtitleLabel];
86
+    
87
+    self.viewController.navigationItem.titleView = self.titleView;
88
+}
89
+
90
+
91
+-(BOOL)isTitleOnly
92
+{
93
+    return self.title && !self.subtitle && !self.titleImageData;
94
+}
95
+
96
+
97
+-(BOOL)isTitleImage
98
+{
99
+    return self.titleImageData && ![self.titleImageData isEqual:[NSNull null]];
100
+}
101
+
102
+
103
+-(void)setupTitleImage
104
+{
105
+    UIImage *titleImage = [RCTConvert UIImage:self.titleImageData];
106
+    UIImageView *imageView = [[UIImageView alloc] initWithImage:titleImage];
107
+    imageView.contentMode = UIViewContentModeScaleAspectFit;
108
+    imageView.autoresizingMask = self.titleView.autoresizingMask;
109
+    
110
+    self.viewController.navigationItem.titleView = imageView;
111
+}
112
+
113
+
114
+-(void)centerTitleView:(CGRect)navigationBarBounds titleLabel:(UILabel*)titleLabel subtitleLabel:(UILabel*)subtitleLabel
115
+{
116
+    CGRect titleViewFrame = navigationBarBounds;
117
+    titleViewFrame.size.width = MAX(titleLabel.frame.size.width, subtitleLabel.frame.size.width);;
118
+    self.titleView.frame = titleViewFrame;
119
+    
120
+    for (UIView *view in self.titleView.subviews)
121
+    {
122
+        CGRect viewFrame = view.frame;
123
+        viewFrame.size.width = self.titleView.frame.size.width;
124
+        viewFrame.origin.x = (self.titleView.frame.size.width - viewFrame.size.width)/2;
125
+        view.frame = viewFrame;
126
+    }
127
+    
128
+}
129
+
130
+
131
+-(UILabel*)setupSubtitle:(NSDictionary*)style
132
+{
133
+    CGRect subtitleFrame = self.titleView.frame;
134
+    subtitleFrame.size.height /= 2;
135
+    subtitleFrame.origin.y = subtitleFrame.size.height;
136
+    
137
+    UILabel *subtitleLabel = [[UILabel alloc] initWithFrame:subtitleFrame];
138
+    subtitleLabel.text = self.subtitle;
139
+    subtitleLabel.textAlignment = NSTextAlignmentCenter;
140
+    subtitleLabel.backgroundColor = [UIColor clearColor];
141
+    subtitleLabel.autoresizingMask = self.titleView.autoresizingMask;
142
+    UIFont *subtitleFont = [UIFont systemFontOfSize:14.f];
143
+    
144
+    id fontSize = style[@"navBarSubtitleFontSize"];
145
+    if (fontSize) {
146
+        CGFloat fontSizeFloat = [RCTConvert CGFloat:fontSize];
147
+        subtitleFont = [UIFont boldSystemFontOfSize:fontSizeFloat];
148
+    }
149
+    
150
+    subtitleLabel.font = subtitleFont;
151
+    
152
+    id navBarSubtitleTextColor = style[@"navBarSubtitleTextColor"];
153
+    if (navBarSubtitleTextColor)
154
+    {
155
+        UIColor *color = navBarSubtitleTextColor != (id)[NSNull null] ? [RCTConvert UIColor:navBarSubtitleTextColor] : nil;
156
+        subtitleLabel.textColor = color;
157
+    }
158
+    
159
+    CGSize labelSize = [subtitleLabel.text sizeWithAttributes:@{NSFontAttributeName:subtitleFont}];
160
+    CGRect labelframe = subtitleLabel.frame;
161
+    labelframe.size = labelSize;
162
+    subtitleLabel.frame = labelframe;
163
+    
164
+    [self.titleView addSubview:subtitleLabel];
165
+    
166
+    return subtitleLabel;
167
+}
168
+
169
+
170
+-(UILabel*)setupTitle:(NSDictionary*)style
171
+{
172
+    CGRect titleFrame = self.titleView.frame;
173
+    if (self.subtitle)
174
+    {
175
+        titleFrame.size.height /= 2;
176
+    }
177
+    UILabel *titleLabel = [[UILabel alloc] initWithFrame:titleFrame];
178
+    titleLabel.text = self.title;
179
+    titleLabel.textAlignment = NSTextAlignmentCenter;
180
+    titleLabel.backgroundColor = [UIColor clearColor];
181
+    
182
+    titleLabel.autoresizingMask = self.titleView.autoresizingMask;
183
+    
184
+    UIFont *titleFont = [UIFont boldSystemFontOfSize:17.f];
185
+    
186
+    id fontSize = style[@"navBarTitleFontSize"];
187
+    if (fontSize) {
188
+        CGFloat fontSizeFloat = [RCTConvert CGFloat:fontSize];
189
+        titleFont = [UIFont boldSystemFontOfSize:fontSizeFloat];
190
+    }
191
+    
192
+    titleLabel.font = titleFont;
193
+    
194
+    CGSize labelSize = [titleLabel.text sizeWithAttributes:@{NSFontAttributeName:titleFont}];
195
+    CGRect labelframe = titleLabel.frame;
196
+    labelframe.size = labelSize;
197
+    titleLabel.frame = labelframe;
198
+    
199
+    if (!self.subtitle)
200
+    {
201
+        titleLabel.center = self.titleView.center;
202
+    }
203
+    
204
+    id navBarTextColor = style[@"navBarTextColor"];
205
+    if (navBarTextColor)
206
+    {
207
+        UIColor *color = navBarTextColor != (id)[NSNull null] ? [RCTConvert UIColor:navBarTextColor] : nil;
208
+        titleLabel.textColor = color;
209
+    }
210
+    
211
+    [self.titleView addSubview:titleLabel];
212
+    
213
+    return titleLabel;
214
+}
215
+
216
+
217
+@end

+ 14
- 0
ios/Helpers/RCTHelpers.h View File

@@ -0,0 +1,14 @@
1
+//
2
+//  RCTHelpers.h
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Artal Druk on 25/05/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import "RCTRootView.h"
11
+
12
+@interface RCTHelpers : NSObject
13
++(BOOL)removeYellowBox:(RCTRootView*)reactRootView;
14
+@end

+ 78
- 0
ios/Helpers/RCTHelpers.m View File

@@ -0,0 +1,78 @@
1
+//
2
+//  RCTHelpers.m
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Artal Druk on 25/05/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import "RCTHelpers.h"
10
+#import "RCTView.h"
11
+#import "RCTScrollView.h"
12
+
13
+@implementation RCTHelpers
14
+
15
++(NSArray*)getAllSubviewsForView:(UIView*)view
16
+{
17
+    NSMutableArray *allSubviews = [NSMutableArray new];
18
+    for (UIView *subview in view.subviews)
19
+    {
20
+        [allSubviews addObject:subview];
21
+        [allSubviews addObjectsFromArray:[self getAllSubviewsForView:subview]];
22
+    }
23
+    return allSubviews;
24
+}
25
+
26
+/*
27
+    The YellowBox is added to each RCTRootView. Regardless if there are warnings or not, if there's a warning anywhere in the app - it is added
28
+    Since it is always appears on the top, it blocks interactions with other components.
29
+    It is most noticeable in RCCLightBox and RCCNotification where button (for example) are not clickable if placed at the bottom part of the view
30
+*/
31
+
32
++(BOOL)removeYellowBox:(RCTRootView*)reactRootView
33
+{
34
+#ifndef DEBUG
35
+    return YES;
36
+#endif
37
+    
38
+    BOOL removed = NO;
39
+    
40
+    NSArray* subviews = [self getAllSubviewsForView:reactRootView];
41
+    for (UIView *view in subviews)
42
+    {
43
+        if ([view isKindOfClass:[RCTView class]])
44
+        {
45
+            CGFloat r, g, b, a;
46
+            [view.backgroundColor getRed:&r green:&g blue:&b alpha:&a];
47
+            
48
+            //identify the yellow view by its hard-coded color and height
49
+            if((lrint(r * 255) == 250) && (lrint(g * 255) == 186) && (lrint(b * 255) == 48) && (lrint(a * 100) == 95) && (view.frame.size.height == 46))
50
+            {
51
+                UIView *yelloboxParentView = view;
52
+                while (view.superview != nil)
53
+                {
54
+                    yelloboxParentView = yelloboxParentView.superview;
55
+                    if ([yelloboxParentView isKindOfClass:[RCTScrollView class]])
56
+                    {
57
+                        yelloboxParentView = yelloboxParentView.superview;
58
+                        break;
59
+                    }
60
+                }
61
+                
62
+                [yelloboxParentView removeFromSuperview];
63
+                removed = YES;
64
+                break;
65
+            }
66
+        }
67
+        
68
+        if (removed)
69
+        {
70
+            break;
71
+        }
72
+    }
73
+    
74
+    return removed;
75
+}
76
+
77
+
78
+@end

+ 77
- 0
ios/RCCDrawerController/MMDrawerController/MMDrawerBarButtonItem.h View File

@@ -0,0 +1,77 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+#import <UIKit/UIKit.h>
22
+
23
+/**
24
+  `MMDrawerBarButtonItem` provides convenience methods to create `UIBarButtonItems` with a default hamburger-menu asset.
25
+ */
26
+
27
+@interface MMDrawerBarButtonItem : UIBarButtonItem
28
+
29
+///---------------------------------------
30
+/// @name Initializing a `MMDrawerBarButtonItem`
31
+///---------------------------------------
32
+
33
+/**
34
+ Creates and initializes an `MMDrawerBarButtonItem` without a border.
35
+ 
36
+ @param target The target to forward the `action` to when the button is pressed.
37
+ @param action The action to call when the button is pressed.
38
+ 
39
+ @return The newly-initialized bar button item.
40
+ */
41
+-(instancetype)initWithTarget:(id)target action:(SEL)action;
42
+
43
+/**
44
+ Returns the current color of the menu button for the state requested. This property is deprecated in iOS 7.0. Use `tintColor` instead.
45
+ 
46
+ @param state The UIControl state that the color is being requested for.
47
+ 
48
+ @return The menu button color for the requested state.
49
+ */
50
+-(UIColor *)menuButtonColorForState:(UIControlState)state __attribute__((deprecated("Use tintColor instead")));
51
+
52
+/**
53
+ Sets the color of the menu button for the specified state. For this control, only set colors for `UIControlStateNormal` and `UIControlStateHighlighted`. This property is deprecated in iOS 7.0. Use `tintColor` instead.
54
+ 
55
+ @param color The color to set.
56
+ @param state The state to set the color for.
57
+ */
58
+-(void)setMenuButtonColor:(UIColor *)color forState:(UIControlState)state __attribute__((deprecated("Use tintColor instead")));
59
+
60
+/**
61
+ Returns the current color of the shadow for the state requested. This property is deprecated in iOS 7.0. The menu button no longer supports a shadow.
62
+ 
63
+ @param state The UIControl state that the color is being requested for.
64
+ 
65
+ @return The menu button color for the requested state.
66
+ */
67
+-(UIColor *)shadowColorForState:(UIControlState)state __attribute__((deprecated("Shadow is no longer supported")));
68
+
69
+/**
70
+ Sets the color of the shadow for the specified state. For this control, only set colors for `UIControlStateNormal` and `UIControlStateHighlighted`. This property is deprecated in iOS 7.0. The menu button no longer supports a shadow.
71
+ 
72
+ @param color The color to set.
73
+ @param state The state to set the color for.
74
+ */
75
+-(void)setShadowColor:(UIColor *)color forState:(UIControlState)state __attribute__((deprecated("Shadow is no longer supported")));
76
+
77
+@end

+ 302
- 0
ios/RCCDrawerController/MMDrawerController/MMDrawerBarButtonItem.m View File

@@ -0,0 +1,302 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+
22
+#import "MMDrawerBarButtonItem.h"
23
+
24
+@interface MMDrawerMenuButtonView : UIButton
25
+@property (nonatomic,strong) UIColor * menuButtonNormalColor;
26
+@property (nonatomic,strong) UIColor * menuButtonHighlightedColor;
27
+
28
+@property (nonatomic,strong) UIColor * shadowNormalColor;
29
+@property (nonatomic,strong) UIColor * shadowHighlightedColor;
30
+
31
+-(UIColor *)menuButtonColorForState:(UIControlState)state;
32
+-(void)setMenuButtonColor:(UIColor *)color forState:(UIControlState)state;
33
+
34
+-(UIColor *)shadowColorForState:(UIControlState)state;
35
+-(void)setShadowColor:(UIColor *)color forState:(UIControlState)state;
36
+
37
+@end
38
+
39
+@implementation MMDrawerMenuButtonView
40
+
41
+-(instancetype)initWithFrame:(CGRect)frame{
42
+    self = [super initWithFrame:frame];
43
+    if(self){
44
+        [self setMenuButtonNormalColor:[[UIColor whiteColor] colorWithAlphaComponent:0.9f]];
45
+        [self setMenuButtonHighlightedColor:[UIColor colorWithRed:139.0/255.0
46
+                                                            green:135.0/255.0
47
+                                                             blue:136.0/255.0
48
+                                                            alpha:0.9f]];
49
+        
50
+        [self setShadowNormalColor:[[UIColor blackColor] colorWithAlphaComponent:0.5f]];
51
+        [self setShadowHighlightedColor:[[UIColor blackColor] colorWithAlphaComponent:0.2f]];
52
+    }
53
+    return self;
54
+}
55
+
56
+-(UIColor *)menuButtonColorForState:(UIControlState)state{
57
+    UIColor * color;
58
+    switch (state) {
59
+        case UIControlStateNormal:
60
+            color = self.menuButtonNormalColor;
61
+            break;
62
+        case UIControlStateHighlighted:
63
+            color = self.menuButtonHighlightedColor;
64
+            break;
65
+        default:
66
+            break;
67
+    }
68
+    return color;
69
+}
70
+
71
+-(void)setMenuButtonColor:(UIColor *)color forState:(UIControlState)state{
72
+    switch (state) {
73
+        case UIControlStateNormal:
74
+            [self setMenuButtonNormalColor:color];
75
+            break;
76
+        case UIControlStateHighlighted:
77
+            [self setMenuButtonHighlightedColor:color];
78
+            break;
79
+        default:
80
+            break;
81
+    }
82
+    [self setNeedsDisplay];
83
+}
84
+
85
+-(UIColor *)shadowColorForState:(UIControlState)state{
86
+    UIColor * color;
87
+    switch (state) {
88
+        case UIControlStateNormal:
89
+            color = self.shadowNormalColor;
90
+            break;
91
+        case UIControlStateHighlighted:
92
+            color = self.shadowHighlightedColor;
93
+            break;
94
+        default:
95
+            break;
96
+    }
97
+    return color;
98
+}
99
+
100
+-(void)setShadowColor:(UIColor *)color forState:(UIControlState)state{
101
+    switch (state) {
102
+        case UIControlStateNormal:
103
+            [self setShadowNormalColor:color];
104
+            break;
105
+        case UIControlStateHighlighted:
106
+            [self setShadowHighlightedColor:color];
107
+            break;
108
+        default:
109
+            break;
110
+    }
111
+    [self setNeedsDisplay];
112
+}
113
+
114
+-(void)drawRect:(CGRect)rect{
115
+    //// General Declarations
116
+    CGContextRef context = UIGraphicsGetCurrentContext();
117
+    
118
+    //Sizes
119
+    CGFloat buttonWidth = CGRectGetWidth(self.bounds)*.80;
120
+    CGFloat buttonHeight = CGRectGetHeight(self.bounds)*.16;
121
+    CGFloat xOffset = CGRectGetWidth(self.bounds)*.10;
122
+    CGFloat yOffset = CGRectGetHeight(self.bounds)*.12;
123
+    CGFloat cornerRadius = 1.0;
124
+    
125
+    //// Color Declarations
126
+    UIColor*  buttonColor = [self menuButtonColorForState:self.state];
127
+    UIColor*  shadowColor = [self shadowColorForState:self.state];
128
+
129
+    
130
+    //// Shadow Declarations
131
+    UIColor* shadow =  shadowColor;
132
+    CGSize shadowOffset = CGSizeMake(0.0, 1.0);
133
+    CGFloat shadowBlurRadius = 0;
134
+    
135
+    //// Top Bun Drawing
136
+    UIBezierPath* topBunPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(xOffset, yOffset, buttonWidth, buttonHeight) cornerRadius:cornerRadius];
137
+    CGContextSaveGState(context);
138
+    CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, shadow.CGColor);
139
+    [buttonColor setFill];
140
+    [topBunPath fill];
141
+    CGContextRestoreGState(context);
142
+    
143
+    //// Meat Drawing
144
+    UIBezierPath* meatPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(xOffset, yOffset*2 + buttonHeight, buttonWidth, buttonHeight) cornerRadius:cornerRadius];
145
+    CGContextSaveGState(context);
146
+    CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, shadow.CGColor);
147
+    [buttonColor setFill];
148
+    [meatPath fill];
149
+    CGContextRestoreGState(context);
150
+    
151
+    //// Bottom Bun Drawing
152
+    UIBezierPath* bottomBunPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(xOffset, yOffset*3 + buttonHeight*2, buttonWidth, buttonHeight) cornerRadius:cornerRadius];
153
+    CGContextSaveGState(context);
154
+    CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, shadow.CGColor);
155
+    [buttonColor setFill];
156
+    [bottomBunPath fill];
157
+    CGContextRestoreGState(context);
158
+}
159
+
160
+-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
161
+    [super touchesBegan:touches withEvent:event];
162
+    [self setNeedsDisplay];
163
+}
164
+
165
+-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
166
+    [super touchesEnded:touches withEvent:event];
167
+    [self setNeedsDisplay];
168
+}
169
+
170
+-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
171
+    [super touchesCancelled:touches withEvent:event];
172
+    [self setNeedsDisplay];
173
+}
174
+
175
+-(void)setSelected:(BOOL)selected{
176
+    [super setSelected:selected];
177
+    [self setNeedsDisplay];
178
+}
179
+
180
+-(void)setHighlighted:(BOOL)highlighted{
181
+    [super setHighlighted:highlighted];
182
+    [self setNeedsDisplay];
183
+}
184
+
185
+-(void)setTintColor:(UIColor *)tintColor{
186
+    if([super respondsToSelector:@selector(setTintColor:)]){
187
+        [super setTintColor:tintColor];
188
+    }
189
+}
190
+
191
+-(void)tintColorDidChange{
192
+     [self setNeedsDisplay];
193
+}
194
+
195
+@end
196
+
197
+@interface MMDrawerBarButtonItem ()
198
+@property (nonatomic,strong) MMDrawerMenuButtonView * buttonView;
199
+
200
+@end
201
+
202
+@implementation MMDrawerBarButtonItem
203
+
204
++(UIImage*)drawerButtonItemImage{
205
+    
206
+    static UIImage *drawerButtonImage = nil;
207
+    static dispatch_once_t onceToken;
208
+    dispatch_once(&onceToken, ^{
209
+
210
+        UIGraphicsBeginImageContextWithOptions( CGSizeMake(26, 26), NO, 0 );
211
+        
212
+        //// Color Declarations
213
+        UIColor* fillColor = [UIColor whiteColor];
214
+        
215
+        //// Frames
216
+        CGRect frame = CGRectMake(0, 0, 26, 26);
217
+        
218
+        //// Bottom Bar Drawing
219
+        UIBezierPath* bottomBarPath = [UIBezierPath bezierPathWithRect: CGRectMake(CGRectGetMinX(frame) + floor((CGRectGetWidth(frame) - 16) * 0.50000 + 0.5), CGRectGetMinY(frame) + floor((CGRectGetHeight(frame) - 1) * 0.72000 + 0.5), 16, 1)];
220
+        [fillColor setFill];
221
+        [bottomBarPath fill];
222
+        
223
+        
224
+        //// Middle Bar Drawing
225
+        UIBezierPath* middleBarPath = [UIBezierPath bezierPathWithRect: CGRectMake(CGRectGetMinX(frame) + floor((CGRectGetWidth(frame) - 16) * 0.50000 + 0.5), CGRectGetMinY(frame) + floor((CGRectGetHeight(frame) - 1) * 0.48000 + 0.5), 16, 1)];
226
+        [fillColor setFill];
227
+        [middleBarPath fill];
228
+        
229
+        
230
+        //// Top Bar Drawing
231
+        UIBezierPath* topBarPath = [UIBezierPath bezierPathWithRect: CGRectMake(CGRectGetMinX(frame) + floor((CGRectGetWidth(frame) - 16) * 0.50000 + 0.5), CGRectGetMinY(frame) + floor((CGRectGetHeight(frame) - 1) * 0.24000 + 0.5), 16, 1)];
232
+        [fillColor setFill];
233
+        [topBarPath fill];
234
+        
235
+        drawerButtonImage = UIGraphicsGetImageFromCurrentImageContext();
236
+    });
237
+    
238
+    return drawerButtonImage;
239
+}
240
+
241
+-(instancetype)initWithTarget:(id)target action:(SEL)action{
242
+    
243
+    if((floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)){
244
+        return [self initWithImage:[self.class drawerButtonItemImage]
245
+                             style:UIBarButtonItemStylePlain
246
+                            target:target
247
+                            action:action];
248
+    }
249
+    else {
250
+        MMDrawerMenuButtonView * buttonView = [[MMDrawerMenuButtonView alloc] initWithFrame:CGRectMake(0, 0, 26, 26)];
251
+        [buttonView addTarget:self action:@selector(touchUpInside:) forControlEvents:UIControlEventTouchUpInside];
252
+        self = [self initWithCustomView:buttonView];
253
+        if(self){
254
+            [self setButtonView:buttonView];
255
+        }
256
+        self.action = action;
257
+        self.target = target;
258
+        return self;
259
+    }
260
+}
261
+
262
+-(instancetype)initWithCoder:(NSCoder *)aDecoder{
263
+    // non-ideal way to get the target/action, but it works
264
+    UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCoder: aDecoder];
265
+    return [self initWithTarget:barButtonItem.target action:barButtonItem.action];
266
+}
267
+
268
+-(void)touchUpInside:(id)sender{
269
+
270
+#pragma clang diagnostic push
271
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"    
272
+    [self.target performSelector:self.action withObject:sender];
273
+#pragma clang diagnostic pop;
274
+    
275
+}
276
+
277
+-(UIColor *)menuButtonColorForState:(UIControlState)state{
278
+    return [self.buttonView menuButtonColorForState:state];
279
+}
280
+
281
+-(void)setMenuButtonColor:(UIColor *)color forState:(UIControlState)state{
282
+    [self.buttonView setMenuButtonColor:color forState:state];
283
+}
284
+
285
+-(UIColor *)shadowColorForState:(UIControlState)state{
286
+    return [self.buttonView shadowColorForState:state];
287
+}
288
+
289
+-(void)setShadowColor:(UIColor *)color forState:(UIControlState)state{
290
+    [self.buttonView setShadowColor:color forState:state];
291
+}
292
+
293
+-(void)setTintColor:(UIColor *)tintColor{
294
+    if([super respondsToSelector:@selector(setTintColor:)]){
295
+        [super setTintColor:tintColor];
296
+    }
297
+    if([self.buttonView respondsToSelector:@selector(setTintColor:)]){
298
+        [self.buttonView setTintColor:tintColor];
299
+    }
300
+}
301
+
302
+@end

+ 111
- 0
ios/RCCDrawerController/MMDrawerController/MMDrawerController+Subclass.h View File

@@ -0,0 +1,111 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+#import "MMDrawerController.h"
22
+
23
+/**
24
+ This class extension is designed for use by subclasses of `MMDrawerController` to customize the functionality to support a specific use-case by a developer. When importing this file, there is no need to also call `#import MMDrawerController.h`.
25
+ 
26
+ None of these methods are meant to be called by non-subclasses of `MMDrawerController`.
27
+ */
28
+
29
+@interface MMDrawerController (Subclass)
30
+///---------------------------------------
31
+/// @name Gesture Interaction
32
+///---------------------------------------
33
+/** 
34
+ `MMDrawerController`'s single-tap gesture recognizer callback. This method is called every time the `UITapGestureRecognizer` is triggered.
35
+ 
36
+ @param tapGesture The single-tap gesture recognizer instance that triggered the callback
37
+ */
38
+-(void)tapGestureCallback:(UITapGestureRecognizer *)tapGesture __attribute((objc_requires_super));
39
+
40
+/** 
41
+ `MMDrawerController`'s pan gesture recognizer callback. This method is called every time the `UIPanGestureRecognizer` is updated.
42
+ 
43
+ @warning This method do the minimal amount of work to keep the pan gesture responsive.
44
+ 
45
+ @param panGesture The pan gesture recognizer instance that triggered the callback
46
+ */
47
+-(void)panGestureCallback:(UIPanGestureRecognizer *)panGesture __attribute((objc_requires_super));
48
+
49
+/**
50
+ A `UIGestureRecognizerDelegate` method that is queried by `MMDrawerController`'s gestures to determine if it should receive the touch.
51
+ 
52
+ @param gestureRecognizer The gesture recognizer that is asking if it should recieve a touch
53
+ @param touch The touch in question in gestureRecognizer.view's coordinate space
54
+ */
55
+-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch __attribute((objc_requires_super));
56
+
57
+///---------------------------------------
58
+/// @name Drawer Presentation
59
+///---------------------------------------
60
+/** 
61
+ Sets the initial conditions for `MMDrawerController` and its child view controllers to prepare the drawer for a transition. If a drawer is open and the opposite drawer is being presented, it prepares that drawer to be hidden and vice-versa for the closing drawer.
62
+ 
63
+ @param drawer The drawer side that will be presented
64
+ @param animated A boolean that indicates whether the presentation is being animated or not
65
+ */
66
+-(void)prepareToPresentDrawer:(MMDrawerSide)drawer animated:(BOOL)animated __attribute((objc_requires_super));
67
+
68
+///---------------------------------------
69
+/// @name Opening/Closing Drawer
70
+///---------------------------------------
71
+/**
72
+ The method that handles closing the drawer. You can subclass this method to get a callback every time the drawer is about to be closed. You can inspect the current open side to determine what side is about to be closed.
73
+ 
74
+ @param animated A boolean that indicates whether the drawer should close with animation
75
+ @param velocity A float indicating how fast the drawer should close
76
+ @param animationOptions A mask defining the animation options of the animation
77
+ @param completion A completion block to be called when the drawer is finished closing
78
+ */
79
+-(void)closeDrawerAnimated:(BOOL)animated velocity:(CGFloat)velocity animationOptions:(UIViewAnimationOptions)options completion:(void (^)(BOOL))completion __attribute((objc_requires_super));
80
+
81
+/**
82
+ The method that handles opening the drawer. You can subclass this method to get a callback every time the drawer is about to be opened.
83
+ 
84
+ @param drawerSide The drawer side that will be opened
85
+ @param animated A boolean that indicates whether the drawer should open with animation
86
+ @param velocity A float indicating how fast the drawer should open
87
+ @param animationOptions A mask defining the animation options of the animation
88
+ @param completion A completion block to be called when the drawer is finished opening
89
+ */
90
+-(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated velocity:(CGFloat)velocity animationOptions:(UIViewAnimationOptions)options completion:(void (^)(BOOL))completion __attribute((objc_requires_super));
91
+
92
+///---------------------------------------
93
+/// @name `UIViewController` Subclass Methods
94
+///---------------------------------------
95
+/**
96
+ Included here to ensure subclasses call `super`.
97
+ 
98
+ @param toInterfaceOrientation The interface orientation that the interface is moving to
99
+ @param duration The duration of the interface orientation animation
100
+ */
101
+-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration __attribute((objc_requires_super));
102
+
103
+/** 
104
+ Included here to ensure subclasses call `super`.
105
+ 
106
+ @param toInterfaceOrientation The interface orientation that the interface is moving to
107
+ @param duration The duration of the interface orientation animation
108
+ */
109
+-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration __attribute((objc_requires_super));
110
+
111
+@end

+ 480
- 0
ios/RCCDrawerController/MMDrawerController/MMDrawerController.h View File

@@ -0,0 +1,480 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+
22
+#import <UIKit/UIKit.h>
23
+
24
+/**
25
+ `MMDrawerController` is a side drawer navigation container view controller designed to support the growing number of applications that leverage the side drawer paradigm. This library is designed to exclusively support side drawer navigation in light-weight, focused approach.
26
+ 
27
+ ## Creating a MMDrawerController
28
+ `MMDrawerController` is a container view controller, similiar to `UINavigationController` or `UITabBarController`, with up to three child view controllers - Center, LeftDrawer, and RightDrawer. To create a `MMDrawerController`, you must first instantiate the drawer view controllers and the initial center controller, then call one of the init methods listed in this class.
29
+ 
30
+ ## Handling a UINavigationController as the centerViewController
31
+ `MMDrawerController` automatically supports handling a `UINavigationController` as the `centerViewController`, and will correctly handle the proper gestures on each view (the navigation bar view as well as the content view for the visible view controller). Note that while this library does support other container view controllers, the open/close gestures are not customized to support them.
32
+ 
33
+ ## Accessing MMDrawerController from the Child View Controller
34
+ You can leverage the category class (UIViewController+MMDrawerController) included with this library to access information about the parent `MMDrawerController`. Note that if you are contained within a UINavigationController, the `drawerContainerViewController` will still return the proper reference to the `drawerContainerViewController` parent, even though it is not the direct parent. Refer to the documentation included with the category for more information.
35
+ 
36
+ ## How MMDrawerOpenCenterInteractionMode is handled
37
+ `MMDrawerOpenCenterInteractionMode` controls how the user should be able to interact with the center view controller when either drawer is open. By default, this is set to `MMDrawerOpenCenterInteractionModeNavigationBarOnly`, which allows the user to interact with UINavigationBarItems while either drawer is open (typicaly used to click the menu button to close). If you set the interaction mode to `MMDrawerOpenCenterInteractionModeNone`, no items within the center view will be able to be interacted with while a drawer is open. Note that this setting has no effect at all on the `MMCloseDrawerGestureMode`.
38
+ 
39
+ ## How Open/Close Gestures are handled
40
+ Two gestures are added to every instance of a drawer controller, one for pan and one for touch. `MMDrawerController` is the delegate for each of the gesture recoginzers, and determines if a touch should be sent to the appropriate gesture when a touch is detected compared with the masks set for open and close gestures and the state of the drawer controller.
41
+ 
42
+ ## Integrating with State Restoration
43
+ In order to opt in to state restoration for `MMDrawerController`, you must set the `restorationIdentifier` of your drawer controller. Instances of your centerViewController, leftDrawerViewController and rightDrawerViewController must also be configured with their own `restorationIdentifier` (and optionally a restorationClass) if you intend for those to be restored as well. If your MMDrawerController had an open drawer when your app was sent to the background, that state will also be restored.
44
+ 
45
+ ## What this library doesn't do.
46
+ This library is not meant for:
47
+ - Top or bottom drawer views
48
+ - Displaying both drawers at one time
49
+ - Displaying a minimum drawer width
50
+ - Support container view controllers other than `UINavigationController` as the center view controller.
51
+ */
52
+
53
+typedef NS_ENUM(NSInteger,MMDrawerSide){
54
+    MMDrawerSideNone = 0,
55
+    MMDrawerSideLeft,
56
+    MMDrawerSideRight,
57
+};
58
+
59
+typedef NS_OPTIONS(NSInteger, MMOpenDrawerGestureMode) {
60
+    MMOpenDrawerGestureModeNone                     = 0,
61
+    MMOpenDrawerGestureModePanningNavigationBar     = 1 << 1,
62
+    MMOpenDrawerGestureModePanningCenterView        = 1 << 2,
63
+    MMOpenDrawerGestureModeBezelPanningCenterView   = 1 << 3,
64
+    MMOpenDrawerGestureModeCustom                   = 1 << 4,
65
+    MMOpenDrawerGestureModeAll                      =   MMOpenDrawerGestureModePanningNavigationBar     |
66
+    MMOpenDrawerGestureModePanningCenterView        |
67
+    MMOpenDrawerGestureModeBezelPanningCenterView   |
68
+    MMOpenDrawerGestureModeCustom,
69
+};
70
+
71
+typedef NS_OPTIONS(NSInteger, MMCloseDrawerGestureMode) {
72
+    MMCloseDrawerGestureModeNone                    = 0,
73
+    MMCloseDrawerGestureModePanningNavigationBar    = 1 << 1,
74
+    MMCloseDrawerGestureModePanningCenterView       = 1 << 2,
75
+    MMCloseDrawerGestureModeBezelPanningCenterView  = 1 << 3,
76
+    MMCloseDrawerGestureModeTapNavigationBar        = 1 << 4,
77
+    MMCloseDrawerGestureModeTapCenterView           = 1 << 5,
78
+    MMCloseDrawerGestureModePanningDrawerView       = 1 << 6,
79
+    MMCloseDrawerGestureModeCustom                  = 1 << 7,
80
+    MMCloseDrawerGestureModeAll                     =   MMCloseDrawerGestureModePanningNavigationBar    |
81
+    MMCloseDrawerGestureModePanningCenterView       |
82
+    MMCloseDrawerGestureModeBezelPanningCenterView  |
83
+    MMCloseDrawerGestureModeTapNavigationBar        |
84
+    MMCloseDrawerGestureModeTapCenterView           |
85
+    MMCloseDrawerGestureModePanningDrawerView       |
86
+    MMCloseDrawerGestureModeCustom,
87
+};
88
+
89
+typedef NS_ENUM(NSInteger, MMDrawerOpenCenterInteractionMode) {
90
+    MMDrawerOpenCenterInteractionModeNone,
91
+    MMDrawerOpenCenterInteractionModeFull,
92
+    MMDrawerOpenCenterInteractionModeNavigationBarOnly,
93
+};
94
+
95
+@class  MMDrawerController;
96
+typedef void (^MMDrawerControllerDrawerVisualStateBlock)(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible);
97
+
98
+@interface MMDrawerController : UIViewController
99
+
100
+///---------------------------------------
101
+/// @name Accessing Drawer Container View Controller Properties
102
+///---------------------------------------
103
+
104
+/**
105
+ The center view controller.
106
+ 
107
+ This can only be set via the init methods, as well as the `setNewCenterViewController:...` methods. The size of this view controller will automatically be set to the size of the drawer container view controller, and it's position is modified from within this class. Do not modify the frame externally.
108
+ */
109
+@property (nonatomic, strong) UIViewController * centerViewController;
110
+
111
+/**
112
+ The left drawer view controller.
113
+ 
114
+ The size of this view controller is managed within this class, and is automatically set to the appropriate size based on the `maximumLeftDrawerWidth`. Do not modify the frame externally.
115
+ */
116
+@property (nonatomic, strong) UIViewController * leftDrawerViewController;
117
+
118
+/**
119
+ The right drawer view controller.
120
+ 
121
+ The size of this view controller is managed within this class, and is automatically set to the appropriate size based on the `maximumRightDrawerWidth`. Do not modify the frame externally.
122
+ */
123
+@property (nonatomic, strong) UIViewController * rightDrawerViewController;
124
+
125
+/**
126
+ The maximum width of the `leftDrawerViewController`.
127
+ 
128
+ By default, this is set to 280. If the `leftDrawerViewController` is nil, this property will return 0.0;
129
+ */
130
+@property (nonatomic, assign) CGFloat maximumLeftDrawerWidth;
131
+
132
+/**
133
+ The maximum width of the `rightDrawerViewController`.
134
+ 
135
+ By default, this is set to 280. If the `rightDrawerViewController` is nil, this property will return 0.0;
136
+ 
137
+ */
138
+@property (nonatomic, assign) CGFloat maximumRightDrawerWidth;
139
+
140
+/**
141
+ The visible width of the `leftDrawerViewController`.
142
+ 
143
+ Note this value can be greater than `maximumLeftDrawerWidth` during the full close animation when setting a new center view controller;
144
+ */
145
+@property (nonatomic, assign, readonly) CGFloat visibleLeftDrawerWidth;
146
+
147
+/**
148
+ The visible width of the `rightDrawerViewController`.
149
+ 
150
+ Note this value can be greater than `maximumRightDrawerWidth` during the full close animation when setting a new center view controller;
151
+ */
152
+@property (nonatomic, assign, readonly) CGFloat visibleRightDrawerWidth;
153
+
154
+/**
155
+ The animation velocity of the open and close methods, measured in points per second.
156
+ 
157
+ By default, this is set to 840 points per second (three times the default drawer width), meaning it takes 1/3 of a second for the `centerViewController` to open/close across the default drawer width. Note that there is a minimum .1 second duration for built in animations, to account for small distance animations.
158
+ */
159
+@property (nonatomic, assign) CGFloat animationVelocity;
160
+
161
+/**
162
+ A boolean that determines whether or not the panning gesture will "hard-stop" at the maximum width for a given drawer side.
163
+ 
164
+ By default, this value is set to YES. Enabling `shouldStretchDrawer` will give the pan a gradual asymptotic stopping point much like `UIScrollView` behaves. Note that if this value is set to YES, the `drawerVisualStateBlock` can be passed a `percentVisible` greater than 1.0, so be sure to handle that case appropriately.
165
+ */
166
+@property (nonatomic, assign) BOOL shouldStretchDrawer;
167
+
168
+/**
169
+ The current open side of the drawer.
170
+ 
171
+ Note this value will change as soon as a pan gesture opens a drawer, or when a open/close animation is finished.
172
+ */
173
+@property (nonatomic, assign, readonly) MMDrawerSide openSide;
174
+
175
+/**
176
+ How a user is allowed to open a drawer using gestures.
177
+ 
178
+ By default, this is set to `MMOpenDrawerGestureModeNone`. Note these gestures may affect user interaction with the `centerViewController`, so be sure to use appropriately.
179
+ */
180
+@property (nonatomic, assign) MMOpenDrawerGestureMode openDrawerGestureModeMask;
181
+
182
+/**
183
+ How a user is allowed to close a drawer.
184
+ 
185
+ By default, this is set to `MMCloseDrawerGestureModeNone`. Note these gestures may affect user interaction with the `centerViewController`, so be sure to use appropriately.
186
+ */
187
+@property (nonatomic, assign) MMCloseDrawerGestureMode closeDrawerGestureModeMask;
188
+
189
+/**
190
+ The value determining if the user can interact with the `centerViewController` when a side drawer is open.
191
+ 
192
+ By default, it is `MMDrawerOpenCenterInteractionModeNavigationBarOnly`, meaning that the user can only interact with the buttons on the `UINavigationBar`, if the center view controller is a `UINavigationController`. Otherwise, the user cannot interact with any other center view controller elements.
193
+ */
194
+@property (nonatomic, assign) MMDrawerOpenCenterInteractionMode centerHiddenInteractionMode;
195
+
196
+/**
197
+ The flag determining if a shadow should be drawn off of `centerViewController` when a drawer is open.
198
+ 
199
+ By default, this is set to YES.
200
+ */
201
+@property (nonatomic, assign) BOOL showsShadow;
202
+
203
+/**
204
+ The shadow radius of `centerViewController` when a drawer is open.
205
+ 
206
+ By default, this is set to 10.0f;
207
+ */
208
+@property (nonatomic, assign) CGFloat shadowRadius;
209
+
210
+/**
211
+ The shadow opacity of `centerViewController` when a drawer is open.
212
+ 
213
+ By default, this is set to 0.8f;
214
+ */
215
+@property (nonatomic, assign) CGFloat shadowOpacity;
216
+
217
+/**
218
+ The shadow offset of `centerViewController` when a drawer is open.
219
+ 
220
+ By default, this is set to (0, -3);
221
+ */
222
+@property (nonatomic, assign) CGSize shadowOffset;
223
+
224
+/**
225
+ The color of the shadow drawn off of 'centerViewController` when a drawer is open.
226
+ 
227
+ By default, this is set to the systme default (opaque black).
228
+ */
229
+@property (nonatomic, strong) UIColor * shadowColor;
230
+
231
+/**
232
+ The flag determining if a custom background view should appear beneath the status bar, forcing the child content to be drawn lower than the status bar.
233
+ 
234
+ By default, this is set to NO.
235
+ */
236
+@property (nonatomic, assign) BOOL showsStatusBarBackgroundView;
237
+
238
+/**
239
+ The color of the status bar background view if `showsStatusBarBackgroundView` is set to YES.
240
+ 
241
+ By default, this is set `[UIColor blackColor]`.
242
+ */
243
+@property (nonatomic, strong) UIColor * statusBarViewBackgroundColor;
244
+
245
+/**
246
+ The value determining panning range of centerView's bezel if the user can open drawer with 'MMOpenDrawerGestureModeBezelPanningCenterView' or close drawer with 'MMCloseDrawerGestureModeBezelPanningCenterView' .
247
+ 
248
+ By default, this is set 20.0f.
249
+ */
250
+@property (nonatomic, assign) CGFloat bezelPanningCenterViewRange;
251
+
252
+/**
253
+ The value determining if the user can open or close drawer with panGesture velocity.
254
+ 
255
+ By default, this is set 200.0f.
256
+ */
257
+@property (nonatomic, assign) CGFloat panVelocityXAnimationThreshold;
258
+
259
+///---------------------------------------
260
+/// @name Initializing a `MMDrawerController`
261
+///---------------------------------------
262
+
263
+/**
264
+ Creates and initializes an `MMDrawerController` object with the specified center view controller, left drawer view controller, and right drawer view controller.
265
+ 
266
+ @param centerViewController The center view controller. This argument must not be `nil`.
267
+ @param leftDrawerViewController The left drawer view controller.
268
+ @param rightDrawerViewController The right drawer controller.
269
+ 
270
+ @return The newly-initialized drawer container view controller.
271
+ */
272
+-(instancetype)initWithCenterViewController:(UIViewController *)centerViewController leftDrawerViewController:(UIViewController *)leftDrawerViewController rightDrawerViewController:(UIViewController *)rightDrawerViewController;
273
+
274
+/**
275
+ Creates and initializes an `MMDrawerController` object with the specified center view controller, left drawer view controller.
276
+ 
277
+ @param centerViewController The center view controller. This argument must not be `nil`.
278
+ @param leftDrawerViewController The left drawer view controller.
279
+ 
280
+ @return The newly-initialized drawer container view controller.
281
+ */
282
+-(instancetype)initWithCenterViewController:(UIViewController *)centerViewController leftDrawerViewController:(UIViewController *)leftDrawerViewController;
283
+
284
+/**
285
+ Creates and initializes an `MMDrawerController` object with the specified center view controller, right drawer view controller.
286
+ 
287
+ @param centerViewController The center view controller. This argument must not be `nil`.
288
+ @param rightDrawerViewController The right drawer controller.
289
+ 
290
+ @return The newly-initialized drawer container view controller.
291
+ */
292
+-(instancetype)initWithCenterViewController:(UIViewController *)centerViewController rightDrawerViewController:(UIViewController *)rightDrawerViewController;
293
+
294
+///---------------------------------------
295
+/// @name Opening and Closing a Drawer
296
+///---------------------------------------
297
+
298
+/**
299
+ Toggles the drawer open/closed based on the `drawer` passed in.
300
+ 
301
+ Note that if you attempt to toggle a drawer closed while the other is open, nothing will happen. For example, if you pass in MMDrawerSideLeft, but the right drawer is open, nothing will happen. In addition, the completion block will be called with the finished flag set to NO.
302
+ 
303
+ @param drawerSide The `MMDrawerSide` to toggle. This value cannot be `MMDrawerSideNone`.
304
+ @param animated Determines whether the `drawer` should be toggle animated.
305
+ @param completion The block that is called when the toggle is complete, or if no toggle took place at all.
306
+ 
307
+ */
308
+-(void)toggleDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated completion:(void(^)(BOOL finished))completion;
309
+
310
+/**
311
+ Closes the open drawer.
312
+ 
313
+ @param animated Determines whether the drawer side should be closed animated
314
+ @param completion The block that is called when the close is complete
315
+ 
316
+ */
317
+-(void)closeDrawerAnimated:(BOOL)animated completion:(void(^)(BOOL finished))completion;
318
+
319
+/**
320
+ Opens the `drawer` passed in.
321
+ 
322
+ @param drawerSide The `MMDrawerSide` to open. This value cannot be `MMDrawerSideNone`.
323
+ @param animated Determines whether the `drawer` should be open animated.
324
+ @param completion The block that is called when the toggle is open.
325
+ 
326
+ */
327
+-(void)openDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated completion:(void(^)(BOOL finished))completion;
328
+
329
+///---------------------------------------
330
+/// @name Setting a new Center View Controller
331
+///---------------------------------------
332
+
333
+/**
334
+ Sets the new `centerViewController`.
335
+ 
336
+ This sets the view controller and will automatically adjust the frame based on the current state of the drawer controller. If `closeAnimated` is YES, it will immediately change the center view controller, and close the drawer from its current position.
337
+ 
338
+ @param centerViewController The new `centerViewController`.
339
+ @param closeAnimated Determines whether the drawer should be closed with an animation.
340
+ @param completion The block called when the animation is finsihed.
341
+ 
342
+ */
343
+-(void)setCenterViewController:(UIViewController *)centerViewController withCloseAnimation:(BOOL)closeAnimated completion:(void(^)(BOOL finished))completion;
344
+
345
+
346
+/**
347
+ Sets the new `centerViewController.overlayViewColor`.
348
+ 
349
+ This sets the overlay view color
350
+ 
351
+ @param color The new `UIColor`.
352
+ 
353
+ */
354
+-(void)setCenterOverlayColor:(UIColor*)color;
355
+
356
+
357
+/**
358
+ Sets the new `centerViewController`.
359
+ 
360
+ This sets the view controller and will automatically adjust the frame based on the current state of the drawer controller. If `closeFullAnimated` is YES, the current center view controller will animate off the screen, the new center view controller will then be set, followed by the drawer closing across the full width of the screen.
361
+ 
362
+ @param newCenterViewController The new `centerViewController`.
363
+ @param fullCloseAnimated Determines whether the drawer should be closed with an animation.
364
+ @param completion The block called when the animation is finsihed.
365
+ 
366
+ */
367
+-(void)setCenterViewController:(UIViewController *)newCenterViewController withFullCloseAnimation:(BOOL)fullCloseAnimated completion:(void(^)(BOOL finished))completion;
368
+
369
+///---------------------------------------
370
+/// @name Animating the Width of a Drawer
371
+///---------------------------------------
372
+
373
+/**
374
+ Sets the maximum width of the left drawer view controller.
375
+ 
376
+ If the drawer is open, and `animated` is YES, it will animate the drawer frame as well as adjust the center view controller. If the drawer is not open, this change will take place immediately.
377
+ 
378
+ @param width The new width of left drawer view controller. This must be greater than zero.
379
+ @param animated Determines whether the drawer should be adjusted with an animation.
380
+ @param completion The block called when the animation is finished.
381
+ 
382
+ */
383
+-(void)setMaximumLeftDrawerWidth:(CGFloat)width animated:(BOOL)animated completion:(void(^)(BOOL finished))completion;
384
+
385
+/**
386
+ Sets the maximum width of the right drawer view controller.
387
+ 
388
+ If the drawer is open, and `animated` is YES, it will animate the drawer frame as well as adjust the center view controller. If the drawer is not open, this change will take place immediately.
389
+ 
390
+ @param width The new width of right drawer view controller. This must be greater than zero.
391
+ @param animated Determines whether the drawer should be adjusted with an animation.
392
+ @param completion The block called when the animation is finished.
393
+ 
394
+ */
395
+-(void)setMaximumRightDrawerWidth:(CGFloat)width animated:(BOOL)animated completion:(void(^)(BOOL finished))completion;
396
+
397
+///---------------------------------------
398
+/// @name Previewing a Drawer
399
+///---------------------------------------
400
+
401
+/**
402
+ Bounce preview for the specified `drawerSide` a distance of 40 points.
403
+ 
404
+ @param drawerSide The drawer to preview. This value cannot be `MMDrawerSideNone`.
405
+ @param completion The block called when the animation is finsihed.
406
+ 
407
+ */
408
+-(void)bouncePreviewForDrawerSide:(MMDrawerSide)drawerSide completion:(void(^)(BOOL finished))completion;
409
+
410
+/**
411
+ Bounce preview for the specified `drawerSide`.
412
+ 
413
+ @param drawerSide The drawer side to preview. This value cannot be `MMDrawerSideNone`.
414
+ @param distance The distance to bounce.
415
+ @param completion The block called when the animation is finsihed.
416
+ 
417
+ */
418
+-(void)bouncePreviewForDrawerSide:(MMDrawerSide)drawerSide distance:(CGFloat)distance completion:(void(^)(BOOL finished))completion;
419
+
420
+///---------------------------------------
421
+/// @name Custom Drawer Animations
422
+///---------------------------------------
423
+
424
+/**
425
+ Sets a callback to be called when a drawer visual state needs to be updated.
426
+ 
427
+ This block is responsible for updating the drawer's view state, and the drawer controller will handle animating to that state from the current state. This block will be called when the drawer is opened or closed, as well when the user is panning the drawer. This block is not responsible for doing animations directly, but instead just updating the state of the properies (such as alpha, anchor point, transform, etc). Note that if `shouldStretchDrawer` is set to YES, it is possible for `percentVisible` to be greater than 1.0. If `shouldStretchDrawer` is set to NO, `percentVisible` will never be greater than 1.0.
428
+ 
429
+ Note that when the drawer is finished opening or closing, the side drawer controller view will be reset with the following properies:
430
+ 
431
+ - alpha: 1.0
432
+ - transform: CATransform3DIdentity
433
+ - anchorPoint: (0.5,0.5)
434
+ 
435
+ @param drawerVisualStateBlock A block object to be called that allows the implementer to update visual state properties on the drawer. `percentVisible` represents the amount of the drawer space that is current visible, with drawer space being defined as the edge of the screen to the maxmimum drawer width. Note that you do have access to the drawerController, which will allow you to update things like the anchor point of the side drawer layer.
436
+ */
437
+-(void)setDrawerVisualStateBlock:(void(^)(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible))drawerVisualStateBlock;
438
+
439
+///---------------------------------------
440
+/// @name Gesture Completion Handling
441
+///---------------------------------------
442
+
443
+/**
444
+ Sets a callback to be called when a gesture has been completed.
445
+ 
446
+ This block is called when a gesture action has been completed. You can query the `openSide` of the `drawerController` to determine what the new state of the drawer is.
447
+ 
448
+ @param gestureCompletionBlock A block object to be called that allows the implementer be notified when a gesture action has been completed.
449
+ */
450
+-(void)setGestureCompletionBlock:(void(^)(MMDrawerController * drawerController, UIGestureRecognizer * gesture))gestureCompletionBlock;
451
+
452
+///---------------------------------------
453
+/// @name Gesture Start Handling
454
+///---------------------------------------
455
+
456
+/**
457
+ Sets a callback to be called when a gesture starts
458
+ 
459
+ This block is called when a gesture action has started.
460
+ 
461
+ @param gestureCompletionBlock A block object to be called that allows the implementer be notified when a gesture action has started.
462
+ */
463
+-(void)setGestureStartBlock:(void (^)(MMDrawerController *, UIGestureRecognizer *))gestureStartBlock;
464
+
465
+///---------------------------------------
466
+/// @name Custom Gesture Handler
467
+///---------------------------------------
468
+
469
+/**
470
+ Sets a callback to be called to determine if a UIGestureRecognizer should recieve the given UITouch.
471
+ 
472
+ This block provides a way to allow a gesture to be recognized with custom logic. For example, you may have a certain part of your view that should accept a pan gesture recognizer to open the drawer, but not another a part. If you return YES, the gesture is recognized and the appropriate action is taken. This provides similar support to how Facebook allows you to pan on the background view of the main table view, but not the content itself. You can inspect the `openSide` property of the `drawerController` to determine the current state of the drawer, and apply the appropriate logic within your block.
473
+ 
474
+ Note that either `openDrawerGestureModeMask` must contain `MMOpenDrawerGestureModeCustom`, or `closeDrawerGestureModeMask` must contain `MMCloseDrawerGestureModeCustom` for this block to be consulted.
475
+ 
476
+ @param gestureShouldRecognizeTouchBlock A block object to be called to determine if the given `touch` should be recognized by the given gesture.
477
+ */
478
+-(void)setGestureShouldRecognizeTouchBlock:(BOOL(^)(MMDrawerController * drawerController, UIGestureRecognizer * gesture, UITouch * touch))gestureShouldRecognizeTouchBlock;
479
+
480
+@end

+ 1529
- 0
ios/RCCDrawerController/MMDrawerController/MMDrawerController.m
File diff suppressed because it is too large
View File


+ 61
- 0
ios/RCCDrawerController/MMDrawerController/MMDrawerVisualState.h View File

@@ -0,0 +1,61 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+
22
+#import <Foundation/Foundation.h>
23
+#import "MMDrawerController.h"
24
+
25
+/**
26
+ `MMDrawerVisualState` provides prebuilt visual state update blocks that can be used in the callback block of `MMDrawerController` for drawer animation.
27
+ */
28
+
29
+@interface MMDrawerVisualState : NSObject
30
+
31
+/**
32
+ Creates a slide and scale visual state block that gives an experience similar to Mailbox.app. It scales from 90% to 100%, and translates 50 pixels in the x direction. In addition, it also sets alpha from 0.0 to 1.0.
33
+ 
34
+ @return The visual state block.
35
+ */
36
++(MMDrawerControllerDrawerVisualStateBlock)slideAndScaleVisualStateBlock;
37
+
38
+/**
39
+ Creates a slide visual state block that gives the user an experience that slides at the same speed of the center view controller during animation. This is equal to calling `parallaxVisualStateBlockWithParallaxFactor:` with a parallax factor of 1.0.
40
+ 
41
+ @return The visual state block.
42
+ */
43
++(MMDrawerControllerDrawerVisualStateBlock)slideVisualStateBlock;
44
+
45
+/**
46
+ Creates a swinging door visual state block that gives the user an experience that animates the drawer in along the hinge. 
47
+ 
48
+ @return The visual state block.
49
+ */
50
++(MMDrawerControllerDrawerVisualStateBlock)swingingDoorVisualStateBlock;
51
+
52
+/**
53
+ Creates a parallax experience that slides the side drawer view controller at a different rate than the center view controller during animation. For every parallaxFactor of points moved by the center view controller, the side drawer view controller will move 1 point. Passing in 1.0 is the  equivalent of a applying a sliding animation, while passing in MAX_FLOAT is the equivalent of having no animation at all.
54
+ 
55
+ @param parallaxFactor The amount of parallax applied to the side drawer conroller. This value must be greater than 1.0. The closer the value is to 1.0, the faster the side drawer view controller will be parallaxing.
56
+ 
57
+ @return The visual state block.
58
+ */
59
++(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxFactor:(CGFloat)parallaxFactor;
60
+
61
+@end

+ 150
- 0
ios/RCCDrawerController/MMDrawerController/MMDrawerVisualState.m View File

@@ -0,0 +1,150 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+
22
+#import "MMDrawerVisualState.h"
23
+#import <QuartzCore/QuartzCore.h>
24
+
25
+@implementation MMDrawerVisualState
26
++(MMDrawerControllerDrawerVisualStateBlock)slideAndScaleVisualStateBlock{
27
+    MMDrawerControllerDrawerVisualStateBlock visualStateBlock =
28
+    ^(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible){
29
+        CGFloat minScale = .90;
30
+        CGFloat scale = minScale + (percentVisible*(1.0-minScale));
31
+        CATransform3D scaleTransform =  CATransform3DMakeScale(scale, scale, scale);
32
+        
33
+        CGFloat maxDistance = 50;
34
+        CGFloat distance = maxDistance * percentVisible;
35
+        CATransform3D translateTransform = CATransform3DIdentity;
36
+        UIViewController * sideDrawerViewController;
37
+        if(drawerSide == MMDrawerSideLeft) {
38
+            sideDrawerViewController = drawerController.leftDrawerViewController;
39
+            translateTransform = CATransform3DMakeTranslation((maxDistance-distance), 0.0, 0.0);
40
+        }
41
+        else if(drawerSide == MMDrawerSideRight){
42
+            sideDrawerViewController = drawerController.rightDrawerViewController;
43
+            translateTransform = CATransform3DMakeTranslation(-(maxDistance-distance), 0.0, 0.0);
44
+        }
45
+        
46
+        [sideDrawerViewController.view.layer setTransform:CATransform3DConcat(scaleTransform, translateTransform)];
47
+        [sideDrawerViewController.view setAlpha:percentVisible];
48
+    };
49
+    return visualStateBlock;
50
+}
51
+
52
++(MMDrawerControllerDrawerVisualStateBlock)slideVisualStateBlock{
53
+    return [self parallaxVisualStateBlockWithParallaxFactor:1.0];
54
+}
55
+
56
+
57
++(MMDrawerControllerDrawerVisualStateBlock)swingingDoorVisualStateBlock{
58
+    MMDrawerControllerDrawerVisualStateBlock visualStateBlock =
59
+    ^(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible){
60
+        UIViewController * sideDrawerViewController;
61
+        CGPoint anchorPoint;
62
+        CGFloat maxDrawerWidth = 0.0;
63
+        CGFloat xOffset;
64
+        CGFloat angle = 0.0;
65
+        
66
+        if(drawerSide==MMDrawerSideLeft){
67
+            
68
+            sideDrawerViewController = drawerController.leftDrawerViewController;
69
+            anchorPoint =  CGPointMake(1.0, .5);
70
+            maxDrawerWidth = MAX(drawerController.maximumLeftDrawerWidth,drawerController.visibleLeftDrawerWidth);
71
+            xOffset = -(maxDrawerWidth/2.0) + (maxDrawerWidth)*percentVisible;
72
+            angle = -M_PI_2+(percentVisible*M_PI_2);
73
+        }
74
+        else {
75
+            sideDrawerViewController = drawerController.rightDrawerViewController;
76
+            anchorPoint = CGPointMake(0.0, .5);
77
+            maxDrawerWidth = MAX(drawerController.maximumRightDrawerWidth,drawerController.visibleRightDrawerWidth);
78
+            xOffset = (maxDrawerWidth/2.0) - (maxDrawerWidth)*percentVisible;
79
+            angle = M_PI_2-(percentVisible*M_PI_2);
80
+        }
81
+        
82
+        [sideDrawerViewController.view.layer setAnchorPoint:anchorPoint];
83
+        [sideDrawerViewController.view.layer setShouldRasterize:YES];
84
+        [sideDrawerViewController.view.layer setRasterizationScale:[[UIScreen mainScreen] scale]];
85
+        
86
+        CATransform3D swingingDoorTransform = CATransform3DIdentity;
87
+        if (percentVisible <= 1.f) {
88
+            
89
+            CATransform3D identity = CATransform3DIdentity;
90
+            identity.m34 = -1.0/1000.0;
91
+            CATransform3D rotateTransform = CATransform3DRotate(identity, angle, 0.0, 1.0, 0.0);
92
+            
93
+            CATransform3D translateTransform = CATransform3DMakeTranslation(xOffset, 0.0, 0.0);
94
+            
95
+            CATransform3D concatTransform = CATransform3DConcat(rotateTransform, translateTransform);
96
+            
97
+            swingingDoorTransform = concatTransform;
98
+        }
99
+        else{
100
+            CATransform3D overshootTransform = CATransform3DMakeScale(percentVisible, 1.f, 1.f);
101
+            
102
+            NSInteger scalingModifier = 1.f;
103
+            if (drawerSide == MMDrawerSideRight) {
104
+                scalingModifier = -1.f;
105
+            }
106
+            
107
+            overshootTransform = CATransform3DTranslate(overshootTransform, scalingModifier*maxDrawerWidth/2, 0.f, 0.f);
108
+            swingingDoorTransform = overshootTransform;
109
+        }
110
+        
111
+        [sideDrawerViewController.view.layer setTransform:swingingDoorTransform];
112
+    };
113
+    return visualStateBlock;
114
+}
115
+
116
++(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxFactor:(CGFloat)parallaxFactor{
117
+    MMDrawerControllerDrawerVisualStateBlock visualStateBlock =
118
+    ^(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible){
119
+        NSParameterAssert(parallaxFactor >= 1.0);
120
+        CATransform3D transform = CATransform3DIdentity;
121
+        UIViewController * sideDrawerViewController;
122
+        if(drawerSide == MMDrawerSideLeft) {
123
+            sideDrawerViewController = drawerController.leftDrawerViewController;
124
+            CGFloat distance = MAX(drawerController.maximumLeftDrawerWidth,drawerController.visibleLeftDrawerWidth);
125
+            if (percentVisible <= 1.f) {
126
+                transform = CATransform3DMakeTranslation((-distance)/parallaxFactor+(distance*percentVisible/parallaxFactor), 0.0, 0.0);
127
+            }
128
+            else{
129
+                transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f);
130
+                transform = CATransform3DTranslate(transform, drawerController.maximumLeftDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f);
131
+            }
132
+        }
133
+        else if(drawerSide == MMDrawerSideRight){
134
+            sideDrawerViewController = drawerController.rightDrawerViewController;
135
+            CGFloat distance = MAX(drawerController.maximumRightDrawerWidth,drawerController.visibleRightDrawerWidth);
136
+            if(percentVisible <= 1.f){
137
+                transform = CATransform3DMakeTranslation((distance)/parallaxFactor-(distance*percentVisible)/parallaxFactor, 0.0, 0.0);
138
+            }
139
+            else{
140
+                transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f);
141
+                transform = CATransform3DTranslate(transform, -drawerController.maximumRightDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f);
142
+            }
143
+        }
144
+        
145
+        [sideDrawerViewController.view.layer setTransform:transform];
146
+    };
147
+    return visualStateBlock;
148
+}
149
+
150
+@end

+ 42
- 0
ios/RCCDrawerController/MMDrawerController/MMExampleDrawerVisualStateManager.h View File

@@ -0,0 +1,42 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+
22
+#import <Foundation/Foundation.h>
23
+#import "MMDrawerVisualState.h"
24
+
25
+typedef NS_ENUM(NSInteger, MMDrawerAnimationType){
26
+    MMDrawerAnimationTypeNone,
27
+    MMDrawerAnimationTypeSlide,
28
+    MMDrawerAnimationTypeSlideAndScale,
29
+    MMDrawerAnimationTypeSwingingDoor,
30
+    MMDrawerAnimationTypeParallax,
31
+};
32
+
33
+@interface MMExampleDrawerVisualStateManager : NSObject
34
+
35
+@property (nonatomic,assign) MMDrawerAnimationType leftDrawerAnimationType;
36
+@property (nonatomic,assign) MMDrawerAnimationType rightDrawerAnimationType;
37
+
38
++ (MMExampleDrawerVisualStateManager *)sharedManager;
39
+
40
+-(MMDrawerControllerDrawerVisualStateBlock)drawerVisualStateBlockForDrawerSide:(MMDrawerSide)drawerSide;
41
+
42
+@end

+ 97
- 0
ios/RCCDrawerController/MMDrawerController/MMExampleDrawerVisualStateManager.m View File

@@ -0,0 +1,97 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+
22
+#import "MMExampleDrawerVisualStateManager.h"
23
+
24
+#import <QuartzCore/QuartzCore.h>
25
+
26
+@implementation MMExampleDrawerVisualStateManager
27
+
28
++ (MMExampleDrawerVisualStateManager *)sharedManager {
29
+    static MMExampleDrawerVisualStateManager *_sharedManager = nil;
30
+    static dispatch_once_t onceToken;
31
+    dispatch_once(&onceToken, ^{
32
+        _sharedManager = [[MMExampleDrawerVisualStateManager alloc] init];
33
+        [_sharedManager setLeftDrawerAnimationType:MMDrawerAnimationTypeParallax];
34
+        [_sharedManager setRightDrawerAnimationType:MMDrawerAnimationTypeParallax];
35
+    });
36
+    
37
+    return _sharedManager;
38
+}
39
+
40
+-(MMDrawerControllerDrawerVisualStateBlock)drawerVisualStateBlockForDrawerSide:(MMDrawerSide)drawerSide{
41
+    MMDrawerAnimationType animationType;
42
+    if(drawerSide == MMDrawerSideLeft){
43
+        animationType = self.leftDrawerAnimationType;
44
+    }
45
+    else {
46
+        animationType = self.rightDrawerAnimationType;
47
+    }
48
+    
49
+    MMDrawerControllerDrawerVisualStateBlock visualStateBlock = nil;
50
+    switch (animationType) {
51
+        case MMDrawerAnimationTypeSlide:
52
+            visualStateBlock = [MMDrawerVisualState slideVisualStateBlock];
53
+            break;
54
+        case MMDrawerAnimationTypeSlideAndScale:
55
+            visualStateBlock = [MMDrawerVisualState slideAndScaleVisualStateBlock];
56
+            break;
57
+        case MMDrawerAnimationTypeParallax:
58
+            visualStateBlock = [MMDrawerVisualState parallaxVisualStateBlockWithParallaxFactor:2.0];
59
+            break;
60
+        case MMDrawerAnimationTypeSwingingDoor:
61
+            visualStateBlock = [MMDrawerVisualState swingingDoorVisualStateBlock];
62
+            break;
63
+        default:
64
+            visualStateBlock =  ^(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible){
65
+                
66
+                UIViewController * sideDrawerViewController;
67
+                CATransform3D transform;
68
+                CGFloat maxDrawerWidth;
69
+                
70
+                if(drawerSide == MMDrawerSideLeft){
71
+                    sideDrawerViewController = drawerController.leftDrawerViewController;
72
+                    maxDrawerWidth = drawerController.maximumLeftDrawerWidth;
73
+                }
74
+                else if(drawerSide == MMDrawerSideRight){
75
+                    sideDrawerViewController = drawerController.rightDrawerViewController;
76
+                    maxDrawerWidth = drawerController.maximumRightDrawerWidth;
77
+                }
78
+                
79
+                if(percentVisible > 1.0){
80
+                    transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f);
81
+                    
82
+                    if(drawerSide == MMDrawerSideLeft){
83
+                        transform = CATransform3DTranslate(transform, maxDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f);
84
+                    }else if(drawerSide == MMDrawerSideRight){
85
+                        transform = CATransform3DTranslate(transform, -maxDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f);
86
+                    }
87
+                }
88
+                else {
89
+                    transform = CATransform3DIdentity;
90
+                }
91
+                [sideDrawerViewController.view.layer setTransform:transform];
92
+            };
93
+            break;
94
+    }
95
+    return visualStateBlock;
96
+}
97
+@end

+ 45
- 0
ios/RCCDrawerController/MMDrawerController/UIViewController+MMDrawerController.h View File

@@ -0,0 +1,45 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+#import <UIKit/UIKit.h>
22
+
23
+#import "MMDrawerController.h"
24
+
25
+/**
26
+ A helper category on `UIViewController` that exposes the parent drawer controller, the visible side drawer frame, and a `mm_drawerWillAppear` method that is called when the drawer is about to appear.
27
+ */
28
+
29
+@interface UIViewController (MMDrawerController)
30
+
31
+///---------------------------------------
32
+/// @name Accessing Drawer View Controller Properties
33
+///---------------------------------------
34
+
35
+/**
36
+ The `MMDrawerController` that the view controller is contained within. If the view controller is not contained within a `MMDrawerController`, this property is nil. Note that if the view controller is contained within a `UINavigationController`, that navigation controller is contained within a `MMDrawerController`, this property will return a refernce to the `MMDrawerController`, despite the fact that it is not the direct parent of the view controller.
37
+ */
38
+@property(nonatomic, strong, readonly) MMDrawerController *mm_drawerController;
39
+
40
+/**
41
+ The visible rect of the side drawer view controller in the drawer controller coordinate space. If the view controller is not a drawer in a `MMDrawerController`, then this property returns `CGRectNull`
42
+ */
43
+@property(nonatomic, assign, readonly) CGRect mm_visibleDrawerFrame;
44
+
45
+@end

+ 64
- 0
ios/RCCDrawerController/MMDrawerController/UIViewController+MMDrawerController.m View File

@@ -0,0 +1,64 @@
1
+// Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/)
2
+//
3
+// Permission is hereby granted, free of charge, to any person obtaining a copy
4
+// of this software and associated documentation files (the "Software"), to deal
5
+// in the Software without restriction, including without limitation the rights
6
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+// copies of the Software, and to permit persons to whom the Software is
8
+// furnished to do so, subject to the following conditions:
9
+//
10
+// The above copyright notice and this permission notice shall be included in
11
+// all copies or substantial portions of the Software.
12
+//
13
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+// THE SOFTWARE.
20
+
21
+
22
+#import "UIViewController+MMDrawerController.h"
23
+
24
+@implementation UIViewController (MMDrawerController)
25
+
26
+
27
+-(MMDrawerController*)mm_drawerController{
28
+    UIViewController *parentViewController = self.parentViewController;
29
+    while (parentViewController != nil) {
30
+        if([parentViewController isKindOfClass:[MMDrawerController class]]){
31
+            return (MMDrawerController *)parentViewController;
32
+        }
33
+        parentViewController = parentViewController.parentViewController;
34
+    }
35
+    return nil;
36
+}
37
+
38
+-(CGRect)mm_visibleDrawerFrame{
39
+    if([self isEqual:self.mm_drawerController.leftDrawerViewController] ||
40
+       [self.navigationController isEqual:self.mm_drawerController.leftDrawerViewController]){
41
+        CGRect rect = self.mm_drawerController.view.bounds;
42
+        rect.size.width = self.mm_drawerController.maximumLeftDrawerWidth;
43
+        if (self.mm_drawerController.showsStatusBarBackgroundView) {
44
+            rect.size.height -= 20.0f;
45
+        }
46
+        return rect;
47
+        
48
+    }
49
+    else if([self isEqual:self.mm_drawerController.rightDrawerViewController] ||
50
+             [self.navigationController isEqual:self.mm_drawerController.rightDrawerViewController]){
51
+        CGRect rect = self.mm_drawerController.view.bounds;
52
+        rect.size.width = self.mm_drawerController.maximumRightDrawerWidth;
53
+        rect.origin.x = CGRectGetWidth(self.mm_drawerController.view.bounds)-rect.size.width;
54
+        if (self.mm_drawerController.showsStatusBarBackgroundView) {
55
+            rect.size.height -= 20.0f;
56
+        }
57
+        return rect;
58
+    }
59
+    else {
60
+        return CGRectNull;
61
+    }
62
+}
63
+
64
+@end

+ 10
- 0
ios/RCCDrawerController/RCCDrawerController.h View File

@@ -0,0 +1,10 @@
1
+#import <UIKit/UIKit.h>
2
+#import "RCTBridge.h"
3
+#import "MMDrawerController.h"
4
+#import "RCCDrawerProtocol.h"
5
+
6
+
7
+@interface RCCDrawerController : MMDrawerController <RCCDrawerDelegate>
8
+
9
+
10
+@end

+ 154
- 0
ios/RCCDrawerController/RCCDrawerController.m View File

@@ -0,0 +1,154 @@
1
+#import "RCCDrawerController.h"
2
+#import "RCCViewController.h"
3
+#import "MMExampleDrawerVisualStateManager.h"
4
+#import "RCCDrawerHelper.h"
5
+#import "RCTConvert.h"
6
+#import "RCCManagerModule.h"
7
+
8
+#define RCCDRAWERCONTROLLER_ANIMATION_DURATION 0.33f
9
+
10
+
11
+@implementation RCCDrawerController
12
+
13
+@synthesize drawerStyle = _drawerStyle;
14
+
15
+
16
+
17
+- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary*)globalProps bridge:(RCTBridge *)bridge
18
+{
19
+    
20
+    self.drawerStyle = props[@"style"];
21
+    
22
+    // center
23
+    if ([children count] < 1) return nil;
24
+    UIViewController *centerViewController = [RCCViewController controllerWithLayout:children[0] globalProps:globalProps bridge:bridge];
25
+    
26
+    // left
27
+    UIViewController *leftViewController = nil;
28
+    NSString *componentLeft = props[@"componentLeft"];
29
+    NSDictionary *passPropsLeft = props[@"passPropsLeft"];
30
+    if (componentLeft) leftViewController = [[RCCViewController alloc] initWithComponent:componentLeft passProps:passPropsLeft navigatorStyle:nil globalProps:globalProps bridge:bridge];
31
+    
32
+    // right
33
+    UIViewController *rightViewController = nil;
34
+    NSString *componentRight = props[@"componentRight"];
35
+    NSDictionary *passPropsRight = props[@"passPropsRight"];
36
+    if (componentRight) rightViewController = [[RCCViewController alloc] initWithComponent:componentRight passProps:passPropsRight navigatorStyle:nil globalProps:globalProps bridge:bridge];
37
+    
38
+    self = [super initWithCenterViewController:centerViewController
39
+                      leftDrawerViewController:leftViewController
40
+                     rightDrawerViewController:rightViewController];
41
+    
42
+    [self setAnimationTypeWithName:props[@"animationType"]];
43
+    
44
+    // default is all MMOpenDrawerGestureModeAll and MMCloseDrawerGestureModeAll
45
+    self.openDrawerGestureModeMask = MMOpenDrawerGestureModeAll;
46
+    self.closeDrawerGestureModeMask = MMCloseDrawerGestureModeAll;
47
+    
48
+    NSNumber *disableOpenGesture = props[@"disableOpenGesture"];
49
+    if ([disableOpenGesture boolValue]) {
50
+        self.openDrawerGestureModeMask = MMOpenDrawerGestureModeNone;
51
+    }
52
+    
53
+    [self setStyle];
54
+    
55
+    [self setDrawerVisualStateBlock:^(MMDrawerController *drawerController, MMDrawerSide drawerSide, CGFloat percentVisible) {
56
+        MMDrawerControllerDrawerVisualStateBlock block;
57
+        block = [[MMExampleDrawerVisualStateManager sharedManager] drawerVisualStateBlockForDrawerSide:drawerSide];
58
+        if (block) {
59
+            block(drawerController, drawerSide, percentVisible);
60
+        }
61
+    }];
62
+    
63
+    [self setGestureStartBlock:^(MMDrawerController *drawerController, UIGestureRecognizer *gesture) {
64
+        [RCCManagerModule cancelAllRCCViewControllerReactTouches];
65
+     }];
66
+                                               
67
+    self.view.backgroundColor = [UIColor clearColor];
68
+    
69
+    if (!self) return nil;
70
+    return self;
71
+}
72
+
73
+
74
+-(void)setStyle {
75
+    
76
+    if (self.drawerStyle[@"drawerShadow"]) {
77
+        self.showsShadow = ([self.drawerStyle[@"drawerShadow"] boolValue]) ? YES : NO;
78
+    }
79
+    
80
+    NSNumber *leftDrawerWidth = self.drawerStyle[@"leftDrawerWidth"];
81
+    if (leftDrawerWidth) {
82
+        self.maximumLeftDrawerWidth = self.view.bounds.size.width * MIN(1, (leftDrawerWidth.floatValue/100.0));
83
+    }
84
+    
85
+    NSNumber *rightDrawerWidth = self.drawerStyle[@"rightDrawerWidth"];
86
+    if (rightDrawerWidth) {
87
+        self.maximumRightDrawerWidth = self.view.bounds.size.width * MIN(1, (rightDrawerWidth.floatValue/100.0));
88
+    }
89
+    
90
+    NSString *contentOverlayColor = self.drawerStyle[@"contentOverlayColor"];
91
+    if (contentOverlayColor)
92
+    {
93
+        UIColor *color = contentOverlayColor != (id)[NSNull null] ? [RCTConvert UIColor:contentOverlayColor] : nil;
94
+        [self setCenterOverlayColor:color];
95
+    }
96
+}
97
+
98
+
99
+- (void)performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams bridge:(RCTBridge *)bridge
100
+{
101
+    MMDrawerSide side = MMDrawerSideLeft;
102
+    if ([actionParams[@"side"] isEqualToString:@"right"]) side = MMDrawerSideRight;
103
+    BOOL animated = actionParams[@"animated"] ? [actionParams[@"animated"] boolValue] : YES;
104
+    
105
+    // open
106
+    if ([performAction isEqualToString:@"open"])
107
+    {
108
+        [self openDrawerSide:side animated:animated completion:nil];
109
+        return;
110
+    }
111
+    
112
+    // close
113
+    if ([performAction isEqualToString:@"close"])
114
+    {
115
+        if (self.openSide == side) {
116
+            [self closeDrawerAnimated:animated completion:nil];
117
+        }
118
+        
119
+        return;
120
+    }
121
+    
122
+    // toggle
123
+    if ([performAction isEqualToString:@"toggle"])
124
+    {
125
+        [super toggleDrawerSide:side animated:animated completion:nil];
126
+        return;
127
+    }
128
+    
129
+    // setStyle
130
+    if ([performAction isEqualToString:@"setStyle"])
131
+    {
132
+        if (actionParams[@"animationType"]) {
133
+            NSString *animationTypeString = actionParams[@"animationType"];
134
+            [self setAnimationTypeWithName:animationTypeString];
135
+        }
136
+        return;
137
+    }
138
+    
139
+}
140
+
141
+-(void)setAnimationTypeWithName:(NSString*)animationTypeName {
142
+    MMDrawerAnimationType animationType = MMDrawerAnimationTypeNone;
143
+    
144
+    if ([animationTypeName isEqualToString:@"door"]) animationType = MMDrawerAnimationTypeSwingingDoor;
145
+    else if ([animationTypeName isEqualToString:@"parallax"]) animationType = MMDrawerAnimationTypeParallax;
146
+    else if ([animationTypeName isEqualToString:@"slide"]) animationType = MMDrawerAnimationTypeSlide;
147
+    else if ([animationTypeName isEqualToString:@"slide-and-scale"]) animationType = MMDrawerAnimationTypeSlideAndScale;
148
+    
149
+    [MMExampleDrawerVisualStateManager sharedManager].leftDrawerAnimationType = animationType;
150
+    [MMExampleDrawerVisualStateManager sharedManager].rightDrawerAnimationType = animationType;
151
+}
152
+
153
+
154
+@end

+ 35
- 0
ios/RCCDrawerController/RCCDrawerHelper.h View File

@@ -0,0 +1,35 @@
1
+//
2
+//  RCCDrawerHelper.h
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Ran Greenberg on 07/04/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import <UIKit/UIKit.h>
11
+
12
+#define DRAWER_DEFAULT_WIDTH_PERCENTAGE 80
13
+
14
+typedef NS_ENUM(NSInteger,RCCDrawerSide){
15
+    RCCDrawerSideLeft,
16
+    RCCDrawerSideRight
17
+};
18
+
19
+
20
+@interface RCCDrawerHelper : NSObject
21
+
22
++(UIButton*)createOverlayButton:(id)target;
23
+
24
++(void)addOverlayButtonToScreen:(UIButton*)buttonToAdd
25
+                    contextView:(UIView*)view
26
+                           side:(RCCDrawerSide)side
27
+                  sideMenuWidth:(CGFloat)sideMenuWidth
28
+              animationDuration:(CGFloat)duration;
29
+
30
++(void)overlayButtonPressed:(UIButton*)button animationDuration:(CGFloat)duration;
31
++(UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize;
32
+
33
+
34
+
35
+@end

+ 96
- 0
ios/RCCDrawerController/RCCDrawerHelper.m View File

@@ -0,0 +1,96 @@
1
+//
2
+//  RCCDrawerHelper.m
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Ran Greenberg on 07/04/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import "RCCDrawerHelper.h"
10
+
11
+@implementation RCCDrawerHelper
12
+
13
+static CGFloat _sideMenuWidth;
14
+
15
++(UIButton*)createOverlayButton:(id)target {
16
+    UIButton *overlayButton = [[UIButton alloc] init];
17
+    overlayButton.backgroundColor = [UIColor clearColor];
18
+    [overlayButton addTarget:target action:@selector(overlayButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
19
+    
20
+    return overlayButton;
21
+}
22
+
23
+
24
++(void)addOverlayButtonToScreen:(UIButton*)buttonToAdd
25
+                    contextView:(UIView*)view
26
+                           side:(RCCDrawerSide)side
27
+                  sideMenuWidth:(CGFloat)sideMenuWidth
28
+              animationDuration:(CGFloat)duration {
29
+    
30
+    _sideMenuWidth = sideMenuWidth;
31
+    
32
+    CGRect buttonFrame = view.bounds;
33
+    
34
+    buttonFrame.origin.x = [RCCDrawerHelper overlayButtonX:sideMenuWidth side:side];
35
+    
36
+    switch (side) {
37
+        case RCCDrawerSideLeft:
38
+        {
39
+            buttonFrame.origin.x = sideMenuWidth;
40
+        }
41
+            
42
+            break;
43
+        case RCCDrawerSideRight:
44
+        {
45
+            buttonFrame.origin.x = 0;
46
+        }
47
+            
48
+            break;
49
+            
50
+        default:
51
+            break;
52
+    }
53
+    
54
+    buttonFrame.size.width = buttonFrame.size.width - sideMenuWidth;
55
+    buttonToAdd.frame = buttonFrame;
56
+    [view addSubview:buttonToAdd];
57
+}
58
+
59
++(void)overlayButtonPressed:(UIButton*)button animationDuration:(CGFloat)duration {
60
+    [button removeFromSuperview];
61
+}
62
+
63
+
64
++(CGFloat)overlayButtonX:(CGFloat)sideMenuWidth side:(RCCDrawerSide)side {
65
+    switch (side) {
66
+        case RCCDrawerSideLeft:
67
+        {
68
+            return sideMenuWidth;
69
+        }
70
+            
71
+            break;
72
+        case RCCDrawerSideRight:
73
+        {
74
+            return 0;
75
+        }
76
+            
77
+            break;
78
+            
79
+        default:
80
+            break;
81
+    }
82
+}
83
+
84
+
85
++ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
86
+    //UIGraphicsBeginImageContext(newSize);
87
+    // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
88
+    // Pass 1.0 to force exact pixel size.
89
+    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
90
+    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
91
+    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
92
+    UIGraphicsEndImageContext();
93
+    return newImage;
94
+}
95
+
96
+@end

+ 24
- 0
ios/RCCDrawerController/RCCDrawerProtocol.h View File

@@ -0,0 +1,24 @@
1
+//
2
+//  RCCDrawerProtocol.h
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Ran Greenberg on 23/03/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+
10
+
11
+@class RCTBridge;
12
+
13
+
14
+@protocol RCCDrawerDelegate <NSObject>
15
+
16
+@property (nonatomic, strong) UIButton *overlayButton;
17
+@property (nonatomic, strong) NSDictionary *drawerStyle;
18
+
19
+@required
20
+- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary*)globalProps bridge:(RCTBridge *)bridge;
21
+- (void)performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams bridge:(RCTBridge *)bridge;
22
+
23
+@end
24
+

+ 22
- 0
ios/RCCDrawerController/RCCTheSideBarManagerViewController.h View File

@@ -0,0 +1,22 @@
1
+//
2
+//  DarwerTheSideBarManagerViewController.h
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Ran Greenberg on 22/03/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import "TheSidebarController.h"
10
+#import "RCCDrawerProtocol.h"
11
+
12
+typedef NS_ENUM(NSInteger,TheSideBarSide){
13
+    TheSideBarSideNone = 0,
14
+    TheSideBarSideLeft,
15
+    TheSideBarSideRight,
16
+};
17
+
18
+
19
+@interface RCCTheSideBarManagerViewController : TheSidebarController <RCCDrawerDelegate>
20
+
21
+
22
+@end

+ 258
- 0
ios/RCCDrawerController/RCCTheSideBarManagerViewController.m View File

@@ -0,0 +1,258 @@
1
+//
2
+//  DarwerTheSideBarManagerViewController.m
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Ran Greenberg on 22/03/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import "RCCTheSideBarManagerViewController.h"
10
+#import "RCCViewController.h"
11
+#import "RCCDrawerHelper.h"
12
+#import "RCTConvert.h"
13
+
14
+
15
+@interface RCCTheSideBarManagerViewController () <TheSidebarControllerDelegate>
16
+
17
+@property (nonatomic) BOOL isOpen;
18
+
19
+@property (nonatomic) SidebarTransitionStyle animationStyle;
20
+
21
+@property (nonatomic, strong) RCCViewController *leftViewController;
22
+@property (nonatomic, strong) RCCViewController *rightViewController;
23
+@property (nonatomic, strong) RCCViewController *centerViewController;
24
+
25
+
26
+@property (nonatomic, strong) UIColor *originalWindowBackgroundColor;
27
+
28
+@end
29
+
30
+@implementation RCCTheSideBarManagerViewController
31
+
32
+@synthesize overlayButton = _overlayButton, drawerStyle = _drawerStyle;
33
+
34
+
35
+-(UIButton*)overlayButton {
36
+    if (!_overlayButton) {
37
+        _overlayButton = [RCCDrawerHelper createOverlayButton:self];
38
+    }
39
+    return _overlayButton;
40
+}
41
+
42
+- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary*)globalProps bridge:(RCTBridge *)bridge {
43
+    
44
+    if ([children count] < 1) return nil;
45
+    
46
+    UIViewController *centerVC = [RCCViewController controllerWithLayout:children[0] globalProps:props bridge:bridge];
47
+    UIViewController *leftVC = nil;
48
+    UIViewController *rightVC = nil;
49
+    
50
+    // left
51
+    NSString *componentLeft = props[@"componentLeft"];
52
+    if (componentLeft)  {
53
+        leftVC = [[RCCViewController alloc] initWithComponent:componentLeft passProps:props[@"passPropsLeft"] navigatorStyle:nil globalProps:props bridge:bridge];
54
+    }
55
+    
56
+    // right
57
+    NSString *componentRight = props[@"componentRight"];
58
+    if (componentRight) {
59
+        rightVC = [[RCCViewController alloc] initWithComponent:componentRight passProps:props[@"passPropsRight"] navigatorStyle:nil globalProps:props bridge:bridge];
60
+    }
61
+    
62
+    self = [super initWithContentViewController:centerVC
63
+                      leftSidebarViewController:leftVC
64
+                     rightSidebarViewController:rightVC];
65
+    if (!self) return nil;
66
+    
67
+    self.leftViewController = leftVC;
68
+    self.rightViewController = rightVC;
69
+    self.centerViewController = centerVC;
70
+    self.drawerStyle = props[@"style"];
71
+    self.delegate = self;
72
+    self.isOpen = NO;
73
+    [self setAnimationType:props[@"animationType"]];
74
+    [self setStyle];
75
+    
76
+    return self;
77
+}
78
+
79
+
80
+-(void)viewDidDisappear:(BOOL)animated {
81
+    [super viewDidDisappear:animated];
82
+    
83
+    UIWindow *appDelegateWindow = [[[UIApplication sharedApplication] delegate] window];
84
+    [appDelegateWindow setBackgroundColor:self.originalWindowBackgroundColor];
85
+    
86
+}
87
+
88
+
89
+-(void)setStyle:(TheSideBarSide)side {
90
+    
91
+    if(side == TheSideBarSideLeft && !self.leftViewController) return;
92
+    if(side == TheSideBarSideRight && !self.rightViewController) return;
93
+    
94
+    CGRect sideBarFrame = self.view.frame;
95
+    
96
+    switch (side) {
97
+        case TheSideBarSideLeft:
98
+        {
99
+            NSNumber *leftDrawerWidth = self.drawerStyle[@"leftDrawerWidth"];
100
+            if (!leftDrawerWidth) leftDrawerWidth = [NSNumber numberWithInteger:DRAWER_DEFAULT_WIDTH_PERCENTAGE];
101
+            
102
+            self.visibleWidth = self.view.bounds.size.width * MIN(1, (leftDrawerWidth.floatValue/100.0));
103
+            sideBarFrame.size.width = self.view.bounds.size.width * MIN(1, (leftDrawerWidth.floatValue/100.0));
104
+            self.leftViewController.view.frame = sideBarFrame;
105
+        }
106
+            break;
107
+            
108
+        case TheSideBarSideRight:
109
+        {
110
+            NSNumber *rightDrawerWidth = self.drawerStyle[@"rightDrawerWidth"];
111
+            if (!rightDrawerWidth) rightDrawerWidth = [NSNumber numberWithInteger:DRAWER_DEFAULT_WIDTH_PERCENTAGE];
112
+            
113
+            self.visibleWidth = self.view.bounds.size.width * MIN(1, (rightDrawerWidth.floatValue/100.0));
114
+            sideBarFrame.size.width = self.view.bounds.size.width * MIN(1, (rightDrawerWidth.floatValue/100.0));
115
+            sideBarFrame.origin.x = self.view.frame.size.width - self.visibleWidth;
116
+            self.rightViewController.view.frame = sideBarFrame;
117
+        }
118
+            break;
119
+            
120
+        default:
121
+            break;
122
+    }
123
+}
124
+
125
+
126
+-(void)setStyle {
127
+    
128
+    [self setStyle:TheSideBarSideLeft];
129
+    [self setStyle:TheSideBarSideRight];
130
+    
131
+    NSString *contentOverlayColor = self.drawerStyle[@"contentOverlayColor"];
132
+    if (contentOverlayColor)
133
+    {
134
+        UIColor *color = contentOverlayColor != (id)[NSNull null] ? [RCTConvert UIColor:contentOverlayColor] : nil;
135
+        self.overlayContentColor = color;
136
+    }
137
+    
138
+    UIImage *backgroundImage = nil;
139
+    id icon = self.drawerStyle[@"backgroundImage"];
140
+    UIWindow *appDelegateWindow = [[[UIApplication sharedApplication] delegate] window];
141
+    self.originalWindowBackgroundColor = appDelegateWindow.backgroundColor;
142
+    
143
+    if (icon)
144
+    {
145
+        backgroundImage = [RCTConvert UIImage:icon];
146
+        if (backgroundImage) {
147
+            backgroundImage = [RCCDrawerHelper imageWithImage:backgroundImage scaledToSize:appDelegateWindow.bounds.size];
148
+            [appDelegateWindow setBackgroundColor:[UIColor colorWithPatternImage:backgroundImage]];
149
+        }
150
+    }
151
+}
152
+
153
+
154
+-(void)setAnimationType:(NSString*)type {
155
+    if ([type isEqualToString:@"airbnb"]) self.animationStyle = SidebarTransitionStyleAirbnb;
156
+    else if ([type isEqualToString:@"facebook"]) self.animationStyle = SidebarTransitionStyleFacebook;
157
+    else if ([type isEqualToString:@"luvocracy"]) self.animationStyle = SidebarTransitionStyleLuvocracy;
158
+    else if ([type isEqualToString:@"wunder-list"]) self.animationStyle = SidebarTransitionStyleWunderlist;
159
+    
160
+    //    currently unsuported animation types
161
+    //    else if ([type isEqualToString:@"feedly"]) self.animationStyle = SidebarTransitionStyleFeedly;
162
+    //    else if ([type isEqualToString:@"flipboard"]) self.animationStyle = SidebarTransitionStyleFlipboard;
163
+    
164
+    
165
+    // default
166
+    else self.animationStyle = SidebarTransitionStyleAirbnb;
167
+}
168
+
169
+- (void)performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams bridge:(RCTBridge *)bridge {
170
+    
171
+    TheSideBarSide side = TheSideBarSideLeft;
172
+    
173
+    if ([actionParams[@"side"] isEqualToString:@"right"]) side = TheSideBarSideRight;
174
+    
175
+    // open
176
+    if ([performAction isEqualToString:@"open"])
177
+    {
178
+        [self openSideMenu:side];
179
+        return;
180
+    }
181
+    
182
+    // close
183
+    if ([performAction isEqualToString:@"close"])
184
+    {
185
+        [self overlayButtonPressed:self.overlayButton];
186
+        return;
187
+    }
188
+    
189
+    // toggle
190
+    if ([performAction isEqualToString:@"toggle"])
191
+    {
192
+        [self setStyle:side];
193
+        if (self.isOpen) {
194
+            [self overlayButtonPressed:self.overlayButton];
195
+        }
196
+        else {
197
+            [self openSideMenu:side];
198
+        }
199
+        self.isOpen = !self.isOpen;
200
+        return;
201
+    }
202
+    
203
+    // setStyle
204
+    if ([performAction isEqualToString:@"setStyle"])
205
+    {
206
+        if (actionParams[@"animationType"]) {
207
+            NSString *animationTypeString = actionParams[@"animationType"];
208
+            
209
+            CGRect leftSideBarFrame = self.leftViewController.view.frame;
210
+            leftSideBarFrame.origin.x = 0;
211
+            self.leftViewController.view.frame = leftSideBarFrame;
212
+            
213
+            CGRect rightSideBarFrame = self.rightViewController.view.frame;
214
+            rightSideBarFrame.origin.x = self.view.frame.size.width - self.visibleWidth;
215
+            self.rightViewController.view.frame = rightSideBarFrame;
216
+            
217
+            [self setAnimationType:animationTypeString];
218
+        }
219
+        return;
220
+    }
221
+}
222
+
223
+
224
+-(void)openSideMenu:(TheSideBarSide)side{
225
+    
226
+    RCCDrawerSide drawerSide;
227
+    
228
+    switch (side) {
229
+        case TheSideBarSideLeft:
230
+        {
231
+            [self presentLeftSidebarViewControllerWithStyle:self.animationStyle];
232
+            drawerSide = RCCDrawerSideLeft;
233
+        }
234
+            
235
+            break;
236
+        case TheSideBarSideRight:
237
+        {
238
+            [self presentRightSidebarViewControllerWithStyle:self.animationStyle];
239
+            drawerSide = RCCDrawerSideRight;
240
+        }
241
+            
242
+            break;
243
+            
244
+        default:
245
+            break;
246
+    }
247
+    
248
+    [RCCDrawerHelper addOverlayButtonToScreen:self.overlayButton contextView:self.view side:drawerSide sideMenuWidth:self.visibleWidth animationDuration:self.animationDuration];
249
+}
250
+
251
+-(void)overlayButtonPressed:(UIButton*)button {
252
+    [self dismissSidebarViewController];
253
+    [RCCDrawerHelper overlayButtonPressed:button animationDuration:self.animationDuration];
254
+    self.isOpen = NO;
255
+}
256
+
257
+
258
+@end

+ 28
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarAirbnbAnimation.h View File

@@ -0,0 +1,28 @@
1
+// SidebarAirbnbAnimation.h
2
+// TheSidebarController
3
+// 
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+// 
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+// 
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+#import "SidebarAnimation.h"
25
+
26
+@interface SidebarAirbnbAnimation : SidebarAnimation
27
+
28
+@end

+ 135
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarAirbnbAnimation.m View File

@@ -0,0 +1,135 @@
1
+// SidebarAirbnbAnimation.m
2
+// TheSidebarController
3
+//
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+//
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+//
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+
25
+#import "SidebarAirbnbAnimation.h"
26
+
27
+@implementation SidebarAirbnbAnimation
28
+
29
++ (void)animateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
30
+{
31
+    [self resetSidebarPosition:sidebarView];
32
+    [self resetContentPosition:contentView];
33
+    
34
+    
35
+    // Animation settings for content view
36
+    CATransform3D contentTransform = CATransform3DIdentity;
37
+    contentTransform.m34 = -1.0f / 800.0f;
38
+    contentView.layer.zPosition = 100;
39
+    
40
+    // Animation settings for menu view
41
+    CATransform3D sidebarTransform = CATransform3DIdentity;
42
+    sidebarTransform = CATransform3DScale(sidebarTransform, 1.7, 1.7, 1.7);
43
+    sidebarView.layer.transform = sidebarTransform;
44
+    
45
+    sidebarTransform = CATransform3DIdentity;
46
+    sidebarTransform = CATransform3DScale(sidebarTransform, 1.0, 1.0, 1.0);
47
+    
48
+    if(side == LeftSide)
49
+    {
50
+        contentTransform = CATransform3DTranslate(contentTransform, visibleWidth - (contentView.frame.size.width / 2 * 0.4), 0.0, 0.0);
51
+        contentTransform = CATransform3DScale(contentTransform, 0.6, 0.6, 0.6);
52
+        contentTransform = CATransform3DRotate(contentTransform, DEG2RAD(-45), 0.0, 1.0, 0.0);
53
+    }
54
+    else
55
+    {
56
+        contentTransform = CATransform3DTranslate(contentTransform, 0 - visibleWidth + (contentView.frame.size.width / 2 * 0.4), 0.0, 0.0);
57
+        contentTransform = CATransform3DScale(contentTransform, 0.6, 0.6, 0.6);
58
+        contentTransform = CATransform3DRotate(contentTransform, DEG2RAD(45), 0.0, 1.0, 0.0);
59
+    }
60
+    
61
+    UIView *overlayContentView = [self overlayContentView:contentView.bounds];
62
+    [contentView addSubview:overlayContentView];
63
+    
64
+    
65
+    
66
+    // Animate content view
67
+    [UIView animateWithDuration:animationDuration
68
+                          delay:0.0
69
+                        options:UIViewAnimationOptionCurveEaseInOut
70
+                     animations:^{
71
+                         contentView.layer.transform = contentTransform;
72
+                         overlayContentView.backgroundColor = [self overlayContentColor];
73
+                         
74
+                     }
75
+                     completion:^(BOOL finished) {
76
+                         completion(finished);
77
+                     }];
78
+    
79
+    // Animate menu view
80
+    [UIView animateWithDuration:animationDuration
81
+                          delay:0.0
82
+                        options:UIViewAnimationOptionCurveEaseInOut
83
+                     animations:^{
84
+                         sidebarView.layer.transform = sidebarTransform;
85
+                     }
86
+                     completion:nil];
87
+}
88
+
89
+
90
++ (void)reverseAnimateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
91
+{
92
+    // Animation settings for content view
93
+    CATransform3D contentTransform = CATransform3DIdentity;
94
+    contentTransform.m34 = -1.0f / 800.0f;
95
+    contentView.layer.zPosition = 100;
96
+    contentTransform = CATransform3DTranslate(contentTransform, 0.0, 0.0, 0.0);
97
+    contentTransform = CATransform3DScale(contentTransform, 1.0, 1.0, 1.0);
98
+    contentTransform = CATransform3DRotate(contentTransform, DEG2RAD(0), 0.0, 1.0, 0.0);
99
+    
100
+    // Animation settings for menu view
101
+    __block CATransform3D sidebarTransform = CATransform3DIdentity;
102
+    sidebarTransform = CATransform3DScale(sidebarTransform, 1.7, 1.7, 1.7);
103
+    
104
+    UIView *overlayContentView = [self overlayContentView:contentView.bounds];
105
+    [contentView addSubview:overlayContentView];
106
+    
107
+    
108
+    // Animate content view
109
+    [UIView animateWithDuration:animationDuration
110
+                          delay:0.0
111
+                        options:UIViewAnimationOptionCurveEaseInOut
112
+                     animations:^{
113
+                         contentView.layer.transform = contentTransform;
114
+                         overlayContentView.backgroundColor = [UIColor clearColor];
115
+                     }
116
+                     completion:^(BOOL finished) {
117
+                         completion(finished);
118
+                     }];
119
+    
120
+    // Animate menu view
121
+    [UIView animateWithDuration:animationDuration
122
+                          delay:0.0
123
+                        options:UIViewAnimationOptionCurveEaseInOut
124
+                     animations:^{
125
+                         sidebarView.layer.transform = sidebarTransform;
126
+                     }
127
+                     completion:^(BOOL finished) {
128
+                         sidebarTransform = CATransform3DIdentity;
129
+                         sidebarTransform = CATransform3DScale(sidebarTransform, 1.0, 1.0, 1.0);
130
+                         sidebarView.layer.transform = sidebarTransform;
131
+                         [overlayContentView removeFromSuperview];
132
+                     }];
133
+}
134
+
135
+@end

+ 80
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarAnimation.h View File

@@ -0,0 +1,80 @@
1
+// SidebarAnimation.h
2
+// TheSidebarController
3
+// 
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+// 
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+// 
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+#import <Foundation/Foundation.h>
25
+#import <QuartzCore/QuartzCore.h>
26
+#import <UIKit/UIKit.h>
27
+
28
+#define DEG2RAD(degrees) (degrees * M_PI / 180)
29
+#define SIDEBAR_ANIMATIONS \
30
+    @"SidebarFacebookAnimation", \
31
+    @"SidebarAirbnbAnimation", \
32
+    @"SidebarLuvocracyAnimation", \
33
+    @"SidebarFeedlyAnimation", \
34
+    @"SidebarFlipboardAnimation", \
35
+    @"SidebarWunderlistAnimation"
36
+
37
+
38
+typedef NS_ENUM(NSInteger, SidebarTransitionStyle)
39
+{
40
+    SidebarTransitionStyleFacebook,
41
+    SidebarTransitionStyleAirbnb,
42
+    SidebarTransitionStyleLuvocracy,
43
+    SidebarTransitionStyleFeedly,
44
+    SidebarTransitionStyleFlipboard,
45
+    SidebarTransitionStyleWunderlist
46
+};
47
+
48
+typedef NS_ENUM(NSInteger, Side)
49
+{
50
+    LeftSide,
51
+    RightSide,
52
+};
53
+
54
+
55
+@class SidebarAnimation;
56
+@interface SidebarAnimation : NSObject
57
+
58
++ (void)animateContentView:(UIView *)contentView
59
+               sidebarView:(UIView *)sidebarView
60
+                  fromSide:(Side)side
61
+              visibleWidth:(CGFloat)visibleWidth
62
+                  duration:(NSTimeInterval)animationDuration
63
+                completion:(void (^)(BOOL finished))completion;
64
+
65
++ (void)reverseAnimateContentView:(UIView *)contentView
66
+                      sidebarView:(UIView *)sidebarView
67
+                         fromSide:(Side)side
68
+                     visibleWidth:(CGFloat)visibleWidth
69
+                         duration:(NSTimeInterval)animationDuration
70
+                       completion:(void (^)(BOOL finished))completion;
71
+
72
++ (void)resetSidebarPosition:(UIView *)sidebarView;
73
++ (void)resetContentPosition:(UIView *)contentView;
74
+
75
++(UIView*)overlayContentView:(CGRect)frame;
76
+
77
++(void)setOverlayContentColor:(UIColor*)color;
78
++(UIColor*)overlayContentColor;
79
+
80
+@end

+ 101
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarAnimation.m View File

@@ -0,0 +1,101 @@
1
+// SidebarAnimation.m
2
+// TheSidebarController
3
+//
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+//
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+//
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+
25
+#import "SidebarAnimation.h"
26
+
27
+
28
+
29
+@implementation SidebarAnimation
30
+
31
+static UIColor *overlayContentColor;
32
+
33
++(void)setOverlayContentColor:(UIColor*)color {
34
+    overlayContentColor = color;
35
+}
36
+
37
++(UIColor*)overlayContentColor {
38
+    return overlayContentColor;
39
+}
40
+
41
++ (void)animateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
42
+{
43
+    
44
+}
45
+
46
++ (void)reverseAnimateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
47
+{
48
+    
49
+}
50
+
51
++ (void)resetSidebarPosition:(UIView *)sidebarView
52
+{
53
+    CATransform3D resetTransform = CATransform3DIdentity;
54
+    resetTransform = CATransform3DRotate(resetTransform, DEG2RAD(0), 1, 1, 1);
55
+    resetTransform = CATransform3DScale(resetTransform, 1.0, 1.0, 1.0);
56
+    resetTransform = CATransform3DTranslate(resetTransform, 0.0, 0.0, 0.0);
57
+    sidebarView.layer.transform = resetTransform;
58
+    
59
+    CGRect resetFrame = sidebarView.frame;
60
+    resetFrame.origin.x = 0;
61
+    resetFrame.origin.y = 0;
62
+    sidebarView.frame = resetFrame;
63
+    
64
+    [sidebarView.superview sendSubviewToBack:sidebarView];
65
+    sidebarView.layer.zPosition = 0;
66
+}
67
+
68
++ (void)resetContentPosition:(UIView *)contentView
69
+{
70
+    CATransform3D resetTransform = CATransform3DIdentity;
71
+    resetTransform = CATransform3DRotate(resetTransform, DEG2RAD(0), 1, 1, 1);
72
+    resetTransform = CATransform3DScale(resetTransform, 1.0, 1.0, 1.0);
73
+    resetTransform = CATransform3DTranslate(resetTransform, 0.0, 0.0, 0.0);
74
+    contentView.layer.transform = resetTransform;
75
+    
76
+    CGRect resetFrame = contentView.frame;
77
+    resetFrame.origin.x = 0;
78
+    resetFrame.origin.y = 0;
79
+    contentView.frame = resetFrame;
80
+    
81
+    [contentView.superview bringSubviewToFront:contentView];
82
+    contentView.layer.zPosition = 0;
83
+}
84
+
85
+
86
++(UIView*)overlayContentView:(CGRect)frame {
87
+    
88
+    static UIView *overlayView;
89
+    static dispatch_once_t onceToken;
90
+    
91
+    dispatch_once(&onceToken, ^{
92
+        overlayView = [[UIView alloc] initWithFrame:frame];
93
+        overlayView.backgroundColor = [UIColor clearColor];
94
+        overlayView.userInteractionEnabled = NO;
95
+    });
96
+    
97
+    return overlayView;
98
+}
99
+
100
+
101
+@end

+ 28
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarFacebookAnimation.h View File

@@ -0,0 +1,28 @@
1
+// SidebarFacebookAnimation.h
2
+// TheSidebarController
3
+// 
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+// 
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+// 
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+#import "SidebarAnimation.h"
25
+
26
+@interface SidebarFacebookAnimation : SidebarAnimation
27
+
28
+@end

+ 83
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarFacebookAnimation.m View File

@@ -0,0 +1,83 @@
1
+// SidebarFacebookAnimation.m
2
+// TheSidebarController
3
+//
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+//
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+//
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+
25
+#import "SidebarFacebookAnimation.h"
26
+
27
+@implementation SidebarFacebookAnimation
28
+
29
++ (void)animateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
30
+{
31
+    [self resetSidebarPosition:sidebarView];
32
+    [self resetContentPosition:contentView];
33
+    
34
+    
35
+    CGRect contentFrame = contentView.frame;
36
+    
37
+    if(side == LeftSide)
38
+    {
39
+        contentFrame.origin.x += visibleWidth;
40
+    }
41
+    else
42
+    {
43
+        contentFrame.origin.x -= visibleWidth;
44
+    }
45
+    
46
+    UIView *overlayContentView = [self overlayContentView:contentView.bounds];
47
+    [contentView addSubview:overlayContentView];
48
+    
49
+    [UIView animateWithDuration:animationDuration
50
+                          delay:0.0
51
+                        options:UIViewAnimationOptionCurveEaseInOut
52
+                     animations:^{
53
+                         contentView.frame = contentFrame;
54
+                         overlayContentView.backgroundColor = [self overlayContentColor];
55
+                     }
56
+                     completion:^(BOOL finished) {
57
+                         completion(finished);
58
+                     }];
59
+}
60
+
61
+
62
++ (void)reverseAnimateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
63
+{
64
+    CGRect contentFrame = contentView.frame;
65
+    contentFrame.origin.x = 0;
66
+    
67
+    UIView *overlayContentView = [self overlayContentView:contentView.bounds];
68
+    [contentView addSubview:overlayContentView];
69
+    
70
+    [UIView animateWithDuration:animationDuration
71
+                          delay:0.0
72
+                        options:UIViewAnimationOptionCurveEaseInOut
73
+                     animations:^{
74
+                         contentView.frame = contentFrame;
75
+                         overlayContentView.backgroundColor = [UIColor clearColor];
76
+                     }
77
+                     completion:^(BOOL finished) {
78
+                         completion(finished);
79
+                         [overlayContentView removeFromSuperview];
80
+                     }];
81
+}
82
+
83
+@end

+ 28
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarFeedlyAnimation.h View File

@@ -0,0 +1,28 @@
1
+// SidebarFeedlyAnimation.h
2
+// TheSidebarController
3
+// 
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+// 
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+// 
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+#import "SidebarAnimation.h"
25
+
26
+@interface SidebarFeedlyAnimation : SidebarAnimation
27
+
28
+@end

+ 89
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarFeedlyAnimation.m View File

@@ -0,0 +1,89 @@
1
+// SidebarFeedlyAnimation.m
2
+// TheSidebarController
3
+//
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+//
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+//
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+
25
+#import "SidebarFeedlyAnimation.h"
26
+
27
+@implementation SidebarFeedlyAnimation
28
+
29
++ (void)animateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
30
+{
31
+    [self resetSidebarPosition:sidebarView];
32
+    [self resetContentPosition:contentView];
33
+    
34
+        
35
+    CGRect sidebarFrame = sidebarView.frame;
36
+    [sidebarView.superview bringSubviewToFront:sidebarView];
37
+    
38
+    if(side == LeftSide)
39
+    {
40
+        sidebarFrame.origin.x = -sidebarFrame.size.width;
41
+        sidebarView.frame = sidebarFrame;
42
+        sidebarFrame.origin.x += visibleWidth;
43
+    }
44
+    else
45
+    {
46
+        sidebarFrame.origin.x = sidebarFrame.size.width;
47
+        sidebarView.frame = sidebarFrame;
48
+        sidebarFrame.origin.x -= visibleWidth;
49
+    }
50
+    
51
+    [UIView animateWithDuration:animationDuration
52
+                          delay:0.0
53
+                        options:UIViewAnimationOptionCurveEaseInOut
54
+                     animations:^{
55
+                         sidebarView.frame = sidebarFrame;
56
+                         contentView.alpha = 0.3;
57
+                     }
58
+                     completion:^(BOOL finished) {
59
+                         completion(finished);
60
+                     }];
61
+}
62
+
63
+
64
++ (void)reverseAnimateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
65
+{
66
+    CGRect sidebarFrame = sidebarView.frame;
67
+    
68
+    if(side == LeftSide)
69
+    {
70
+        sidebarFrame.origin.x -= visibleWidth;
71
+    }
72
+    else
73
+    {
74
+        sidebarFrame.origin.x += visibleWidth;
75
+    }
76
+    
77
+    [UIView animateWithDuration:animationDuration
78
+                          delay:0.0
79
+                        options:UIViewAnimationOptionCurveEaseInOut
80
+                     animations:^{
81
+                         sidebarView.frame = sidebarFrame;
82
+                         contentView.alpha = 1;
83
+                     }
84
+                     completion:^(BOOL finished) {
85
+                         completion(finished);
86
+                     }];
87
+}
88
+
89
+@end

+ 28
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarFlipboardAnimation.h View File

@@ -0,0 +1,28 @@
1
+// SidebarFlipboardAnimation.h
2
+// TheSidebarController
3
+// 
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+// 
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+// 
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+#import "SidebarAnimation.h"
25
+
26
+@interface SidebarFlipboardAnimation : SidebarAnimation
27
+
28
+@end

+ 99
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarFlipboardAnimation.m View File

@@ -0,0 +1,99 @@
1
+// SidebarFlipboardAnimation.m
2
+// TheSidebarController
3
+//
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+//
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+//
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+
25
+#import "SidebarFlipboardAnimation.h"
26
+
27
+@implementation SidebarFlipboardAnimation
28
+
29
++ (void)animateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
30
+{
31
+    [self resetSidebarPosition:sidebarView];
32
+    [self resetContentPosition:contentView];
33
+    
34
+    
35
+    CGRect sidebarFrame = sidebarView.frame;
36
+    [sidebarView.superview bringSubviewToFront:sidebarView];
37
+    
38
+    CATransform3D contentTransform = CATransform3DIdentity;
39
+    contentTransform = CATransform3DScale(contentTransform, 0.9, 0.9, 0.9);
40
+    
41
+    if(side == LeftSide)
42
+    {
43
+        sidebarFrame.origin.x = -sidebarFrame.size.width;
44
+        sidebarView.frame = sidebarFrame;
45
+        sidebarFrame.origin.x += visibleWidth;
46
+    }
47
+    else
48
+    {
49
+        sidebarFrame.origin.x = sidebarFrame.size.width;
50
+        sidebarView.frame = sidebarFrame;
51
+        sidebarFrame.origin.x -= visibleWidth;
52
+    }
53
+    
54
+    [UIView animateWithDuration:animationDuration
55
+                          delay:0.0
56
+                        options:UIViewAnimationOptionCurveEaseInOut
57
+                     animations:^{
58
+                         sidebarView.frame = sidebarFrame;
59
+                         contentView.alpha = 0.3;
60
+                         contentView.layer.transform = contentTransform;
61
+                     }
62
+                     completion:^(BOOL finished) {
63
+                         completion(finished);
64
+                     }];
65
+    
66
+    
67
+    
68
+}
69
+
70
++ (void)reverseAnimateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
71
+{
72
+    CGRect sidebarFrame = sidebarView.frame;
73
+    CATransform3D contentTransform = CATransform3DIdentity;
74
+    contentTransform = CATransform3DScale(contentTransform, 1.0, 1.0, 1.0);
75
+    
76
+    if(side == LeftSide)
77
+    {
78
+        sidebarFrame.origin.x -= visibleWidth;
79
+    }
80
+    else
81
+    {
82
+        sidebarFrame.origin.x += visibleWidth;
83
+    }
84
+    
85
+    [UIView animateWithDuration:animationDuration
86
+                          delay:0.0
87
+                        options:UIViewAnimationOptionCurveEaseInOut
88
+                     animations:^{
89
+                         sidebarView.frame = sidebarFrame;
90
+                         contentView.alpha = 1;
91
+                         contentView.layer.transform = contentTransform;
92
+                     }
93
+                     completion:^(BOOL finished) {
94
+                         completion(finished);
95
+                     }];
96
+}
97
+
98
+
99
+@end

+ 28
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarLuvocracyAnimation.h View File

@@ -0,0 +1,28 @@
1
+// SidebarLuvocracyAnimation.h
2
+// TheSidebarController
3
+// 
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+// 
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+// 
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+#import "SidebarAnimation.h"
25
+
26
+@interface SidebarLuvocracyAnimation : SidebarAnimation
27
+
28
+@end

+ 111
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarLuvocracyAnimation.m View File

@@ -0,0 +1,111 @@
1
+// SidebarLuvocracyAnimation.m
2
+// TheSidebarController
3
+//
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+//
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+//
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+
25
+#import "SidebarLuvocracyAnimation.h"
26
+
27
+@implementation SidebarLuvocracyAnimation
28
+
29
++ (void)animateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
30
+{
31
+    [self resetSidebarPosition:sidebarView];
32
+    [self resetContentPosition:contentView];
33
+    
34
+    // Animation settings for content view
35
+    CATransform3D contentTransform = CATransform3DIdentity;
36
+    contentTransform.m34 = -1.0f / 800.0f;
37
+    contentView.layer.zPosition = 100;
38
+    
39
+    // Animation settings for sidebar view
40
+    CATransform3D sidebarTransform = CATransform3DIdentity;
41
+    sidebarTransform = CATransform3DScale(sidebarTransform, 1.7, 1.7, 1.7);
42
+    sidebarView.layer.transform = sidebarTransform;
43
+    
44
+    sidebarTransform = CATransform3DIdentity;
45
+    sidebarTransform = CATransform3DScale(sidebarTransform, 1.0, 1.0, 1.0);
46
+    
47
+    if(side == LeftSide)
48
+    {
49
+        contentTransform = CATransform3DTranslate(contentTransform, visibleWidth - (contentView.frame.size.width / 2 * 0.4), 0.0, 0.0);
50
+        contentTransform = CATransform3DScale(contentTransform, 0.6, 0.6, 0.6);
51
+    }
52
+    else
53
+    {
54
+        contentTransform = CATransform3DTranslate(contentTransform, 0 - visibleWidth + (contentView.frame.size.width / 2 * 0.4), 0.0, 0.0);
55
+        contentTransform = CATransform3DScale(contentTransform, 0.6, 0.6, 0.6);
56
+    }
57
+    
58
+    UIView *overlayContentView = [self overlayContentView:contentView.bounds];
59
+    [contentView addSubview:overlayContentView];
60
+    
61
+    // Animate
62
+    [UIView animateWithDuration:animationDuration
63
+                          delay:0.0
64
+                        options:UIViewAnimationOptionCurveEaseInOut
65
+                     animations:^{
66
+                         contentView.layer.transform = contentTransform;
67
+                         sidebarView.layer.transform = sidebarTransform;
68
+                         overlayContentView.backgroundColor = [self overlayContentColor];
69
+                     }
70
+                     completion:^(BOOL finished) {
71
+                         completion(finished);
72
+                     }];
73
+}
74
+
75
+
76
++ (void)reverseAnimateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
77
+{
78
+    // Animation settings for content view
79
+    CATransform3D contentTransform = CATransform3DIdentity;
80
+    contentTransform.m34 = -1.0f / 800.0f;
81
+    contentView.layer.zPosition = 100;
82
+    contentTransform = CATransform3DTranslate(contentTransform, 0.0, 0.0, 0.0);
83
+    contentTransform = CATransform3DScale(contentTransform, 1.0, 1.0, 1.0);
84
+    
85
+    // Animation settings for menu view
86
+    __block CATransform3D sidebarTransform = CATransform3DIdentity;
87
+    sidebarTransform = CATransform3DScale(sidebarTransform, 1.7, 1.7, 1.7);
88
+    
89
+    UIView *overlayContentView = [self overlayContentView:contentView.bounds];
90
+    [contentView addSubview:overlayContentView];
91
+    
92
+    // Animate
93
+    [UIView animateWithDuration:animationDuration
94
+                          delay:0.0
95
+                        options:UIViewAnimationOptionCurveEaseInOut
96
+                     animations:^{
97
+                         contentView.layer.transform = contentTransform;
98
+                         sidebarView.layer.transform = sidebarTransform;
99
+                         overlayContentView.backgroundColor = [UIColor clearColor];
100
+                     }
101
+                     completion:^(BOOL finished) {
102
+                         completion(finished);
103
+                         sidebarTransform = CATransform3DIdentity;
104
+                         sidebarTransform = CATransform3DScale(sidebarTransform, 1.0, 1.0, 1.0);
105
+                         sidebarView.layer.transform = sidebarTransform;
106
+                         [overlayContentView removeFromSuperview];
107
+                     }];
108
+}
109
+
110
+
111
+@end

+ 28
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarWunderlistAnimation.h View File

@@ -0,0 +1,28 @@
1
+// SidebarWunderlistAnimation.h
2
+// TheSidebarController
3
+// 
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+// 
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+// 
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+#import "SidebarAnimation.h"
25
+
26
+@interface SidebarWunderlistAnimation : SidebarAnimation
27
+
28
+@end

+ 103
- 0
ios/RCCDrawerController/TheSidebarController/Animations/SidebarWunderlistAnimation.m View File

@@ -0,0 +1,103 @@
1
+// SidebarWunderlistAnimation.m
2
+// TheSidebarController
3
+//
4
+// Copyright (c) 2014 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+//
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+//
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+
25
+#import "SidebarWunderlistAnimation.h"
26
+
27
+@implementation SidebarWunderlistAnimation
28
+
29
++ (void)animateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
30
+{
31
+    [self resetSidebarPosition:sidebarView];
32
+    [self resetContentPosition:contentView];
33
+    
34
+    
35
+    CGRect contentFrame = contentView.frame;
36
+    CGRect sidebarFrame = sidebarView.frame;
37
+    
38
+    if(side == LeftSide)
39
+    {
40
+        contentFrame.origin.x += visibleWidth;
41
+        sidebarFrame.origin.x -= 50;
42
+    }
43
+    else
44
+    {
45
+        contentFrame.origin.x -= visibleWidth;
46
+        sidebarFrame.origin.x += 50;
47
+    }
48
+    
49
+    sidebarView.frame = sidebarFrame;
50
+    sidebarFrame.origin.x = 0;
51
+    
52
+    UIView *overlayContentView = [self overlayContentView:contentView.bounds];
53
+    [contentView addSubview:overlayContentView];
54
+    
55
+    [UIView animateWithDuration:animationDuration
56
+                          delay:0.0
57
+                        options:UIViewAnimationOptionCurveEaseInOut
58
+                     animations:^{
59
+                         contentView.frame = contentFrame;
60
+                         sidebarView.frame = sidebarFrame;
61
+                         overlayContentView.backgroundColor = [self overlayContentColor];
62
+                     }
63
+                     completion:^(BOOL finished) {
64
+                         completion(finished);
65
+                     }];
66
+}
67
+
68
+
69
++ (void)reverseAnimateContentView:(UIView *)contentView sidebarView:(UIView *)sidebarView fromSide:(Side)side visibleWidth:(CGFloat)visibleWidth duration:(NSTimeInterval)animationDuration completion:(void (^)(BOOL))completion
70
+{
71
+    CGRect contentFrame = contentView.frame;
72
+    contentFrame.origin.x = 0;
73
+    
74
+    CGRect sidebarFrame = sidebarView.frame;
75
+    
76
+    if(side == LeftSide)
77
+    {
78
+        sidebarFrame.origin.x -= 50;
79
+    }
80
+    else
81
+    {
82
+        sidebarFrame.origin.x += 50;
83
+    }
84
+    
85
+    UIView *overlayContentView = [self overlayContentView:contentView.bounds];
86
+    [contentView addSubview:overlayContentView];
87
+    
88
+    [UIView animateWithDuration:animationDuration
89
+                          delay:0.0
90
+                        options:UIViewAnimationOptionCurveEaseInOut
91
+                     animations:^{
92
+                         contentView.frame = contentFrame;
93
+                         sidebarView.frame = sidebarFrame;
94
+                         overlayContentView.backgroundColor = [UIColor clearColor];
95
+                     }
96
+                     completion:^(BOOL finished) {
97
+                         completion(finished);
98
+                         [overlayContentView removeFromSuperview];
99
+                     }];
100
+}
101
+
102
+
103
+@end

+ 91
- 0
ios/RCCDrawerController/TheSidebarController/TheSidebarController.h View File

@@ -0,0 +1,91 @@
1
+// TheSidebarController.h
2
+// TheSidebarController
3
+//
4
+// Copyright (c) 2013 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+//
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+//
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+
25
+#import <UIKit/UIKit.h>
26
+#import "Animations/SidebarAnimation.h"
27
+
28
+@protocol TheSidebarControllerDelegate;
29
+
30
+@interface TheSidebarController : UIViewController
31
+
32
+@property (strong, nonatomic) UIViewController *contentViewController;
33
+@property (strong, nonatomic) UIViewController *leftSidebarViewController;
34
+@property (strong, nonatomic) UIViewController *rightSidebarViewController;
35
+
36
+@property (assign, nonatomic) NSTimeInterval animationDuration;
37
+@property (assign, nonatomic) CGFloat visibleWidth;
38
+@property (assign, nonatomic) BOOL sidebarIsPresenting;
39
+@property (assign, nonatomic) id<TheSidebarControllerDelegate> delegate;
40
+@property (assign, nonatomic) BOOL storyboardsUseAutolayout;
41
+@property (nonatomic, strong) UIColor *overlayContentColor;
42
+
43
+- (id)initWithContentViewController:(UIViewController *)contentViewController
44
+          leftSidebarViewController:(UIViewController *)leftSidebarViewController;
45
+
46
+- (id)initWithContentViewController:(UIViewController *)contentViewController
47
+         rightSidebarViewController:(UIViewController *)rightSidebarViewController;
48
+
49
+- (id)initWithContentViewController:(UIViewController *)contentViewController
50
+          leftSidebarViewController:(UIViewController *)leftSidebarViewController
51
+         rightSidebarViewController:(UIViewController *)rightSidebarViewController;
52
+
53
+- (id)initWithContentViewController:(UIViewController *)contentViewController
54
+          leftSidebarViewController:(UIViewController *)leftSidebarViewController
55
+           storyboardsUseAutoLayout:(BOOL)storyboardsUseAutoLayout;
56
+
57
+- (id)initWithContentViewController:(UIViewController *)contentViewController
58
+         rightSidebarViewController:(UIViewController *)rightSidebarViewController
59
+           storyboardsUseAutoLayout:(BOOL)storyboardsUseAutoLayout;
60
+
61
+- (id)initWithContentViewController:(UIViewController *)contentViewController
62
+          leftSidebarViewController:(UIViewController *)leftSidebarViewController
63
+         rightSidebarViewController:(UIViewController *)rightSidebarViewController
64
+           storyboardsUseAutoLayout:(BOOL)storyboardsUseAutoLayout;
65
+
66
+- (void)dismissSidebarViewController;
67
+- (void)presentLeftSidebarViewController;
68
+- (void)presentLeftSidebarViewControllerWithStyle:(SidebarTransitionStyle)transitionStyle;
69
+- (void)presentRightSidebarViewController;
70
+- (void)presentRightSidebarViewControllerWithStyle:(SidebarTransitionStyle)transitionStyle;
71
+
72
+@end
73
+
74
+
75
+
76
+@protocol TheSidebarControllerDelegate <NSObject>
77
+
78
+@optional
79
+- (void)sidebarController:(TheSidebarController *)sidebarController willShowViewController:(UIViewController *)viewController;
80
+- (void)sidebarController:(TheSidebarController *)sidebarController didShowViewController:(UIViewController *)viewController;
81
+- (void)sidebarController:(TheSidebarController *)sidebarController willHideViewController:(UIViewController *)viewController;
82
+- (void)sidebarController:(TheSidebarController *)sidebarController didHideViewController:(UIViewController *)viewController;
83
+@end
84
+
85
+
86
+
87
+@interface UIViewController(TheSidebarController)
88
+
89
+@property (strong, readonly, nonatomic) TheSidebarController *sidebarController;
90
+
91
+@end

+ 414
- 0
ios/RCCDrawerController/TheSidebarController/TheSidebarController.m View File

@@ -0,0 +1,414 @@
1
+// TheSidebarController.m
2
+// TheSidebarController
3
+//
4
+// Copyright (c) 2013 Jon Danao (danao.org | jondanao)
5
+//
6
+// Permission is hereby granted, free of charge, to any person obtaining a copy
7
+// of this software and associated documentation files (the "Software"), to deal
8
+// in the Software without restriction, including without limitation the rights
9
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+// copies of the Software, and to permit persons to whom the Software is
11
+// furnished to do so, subject to the following conditions:
12
+//
13
+// The above copyright notice and this permission notice shall be included in
14
+// all copies or substantial portions of the Software.
15
+//
16
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+// THE SOFTWARE.
23
+
24
+
25
+#import "TheSidebarController.h"
26
+
27
+
28
+static const CGFloat kAnimationDuration = 0.3f;
29
+static const CGFloat kVisibleWidth = 310.0f;
30
+
31
+
32
+@interface TheSidebarController()
33
+
34
+@property (assign, nonatomic) SidebarTransitionStyle selectedTransitionStyle;
35
+@property (assign, nonatomic) Side selectedSide;
36
+@property (strong, nonatomic) UIViewController *selectedSidebarViewController;
37
+@property (strong, nonatomic) NSArray *sidebarAnimations;
38
+@property (strong, nonatomic) UIViewController *contentContainerViewController;
39
+@property (strong, nonatomic) UIViewController *leftSidebarContainerViewController;
40
+@property (strong, nonatomic) UIViewController *rightSidebarContainerViewController;
41
+@property (assign, nonatomic) CATransform3D contentTransform;
42
+
43
+- (void)showSidebarViewControllerFromSide:(Side)side withTransitionStyle:(SidebarTransitionStyle)transitionStyle;
44
+- (void)hideSidebarViewController;
45
+- (void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view;
46
+
47
+@end
48
+
49
+
50
+@implementation TheSidebarController
51
+
52
+#pragma mark - Designated Initializer
53
+- (id)init
54
+{
55
+    return [self initWithContentViewController:nil leftSidebarViewController:nil rightSidebarViewController:nil];
56
+}
57
+
58
+- (id)initWithContentViewController:(UIViewController *)contentViewController leftSidebarViewController:(UIViewController *)leftSidebarViewController
59
+{
60
+    return [self initWithContentViewController:contentViewController leftSidebarViewController:leftSidebarViewController rightSidebarViewController:nil];
61
+}
62
+
63
+- (id)initWithContentViewController:(UIViewController *)contentViewController rightSidebarViewController:(UIViewController *)rightSidebarViewController
64
+{
65
+    return [self initWithContentViewController:contentViewController leftSidebarViewController:nil rightSidebarViewController:rightSidebarViewController];
66
+}
67
+
68
+- (id)initWithContentViewController:(UIViewController *)contentViewController leftSidebarViewController:(UIViewController *)leftSidebarViewController rightSidebarViewController:(UIViewController *)rightSidebarViewController
69
+{
70
+    self = [super init];
71
+    
72
+    if(self)
73
+    {
74
+        _contentContainerViewController = [[UIViewController alloc] init];
75
+        _leftSidebarContainerViewController = [[UIViewController alloc] init];
76
+        _rightSidebarContainerViewController = [[UIViewController alloc] init];
77
+        
78
+        _contentContainerViewController.view.backgroundColor = [UIColor clearColor];
79
+        _leftSidebarContainerViewController.view.backgroundColor = [UIColor clearColor];
80
+        _rightSidebarContainerViewController.view.backgroundColor = [UIColor clearColor];
81
+        
82
+        _contentViewController = contentViewController;
83
+        _leftSidebarViewController = leftSidebarViewController;
84
+        _rightSidebarViewController = rightSidebarViewController;
85
+        
86
+        _animationDuration = kAnimationDuration;
87
+        _visibleWidth = kVisibleWidth;
88
+        _sidebarAnimations = @[SIDEBAR_ANIMATIONS];
89
+        _sidebarIsPresenting = NO;
90
+    }
91
+    
92
+    return self;
93
+}
94
+
95
+- (id)initWithContentViewController:(UIViewController *)contentViewController
96
+          leftSidebarViewController:(UIViewController *)leftSidebarViewController
97
+           storyboardsUseAutoLayout:(BOOL)storyboardsUseAutoLayout
98
+{
99
+    self.storyboardsUseAutolayout = storyboardsUseAutoLayout;
100
+    return [self initWithContentViewController:contentViewController leftSidebarViewController:leftSidebarViewController];
101
+}
102
+
103
+- (id)initWithContentViewController:(UIViewController *)contentViewController
104
+         rightSidebarViewController:(UIViewController *)rightSidebarViewController
105
+           storyboardsUseAutoLayout:(BOOL)storyboardsUseAutoLayout
106
+{
107
+    self.storyboardsUseAutolayout = storyboardsUseAutoLayout;
108
+    return [self initWithContentViewController:contentViewController rightSidebarViewController:rightSidebarViewController];
109
+}
110
+
111
+- (id)initWithContentViewController:(UIViewController *)contentViewController
112
+          leftSidebarViewController:(UIViewController *)leftSidebarViewController
113
+         rightSidebarViewController:(UIViewController *)rightSidebarViewController
114
+           storyboardsUseAutoLayout:(BOOL)storyboardsUseAutoLayout
115
+{
116
+    self.storyboardsUseAutolayout = storyboardsUseAutoLayout;
117
+    return [self initWithContentViewController:contentViewController leftSidebarViewController:leftSidebarViewController rightSidebarViewController:rightSidebarViewController];
118
+}
119
+
120
+#pragma mark - UIViewController Lifecycle
121
+- (void)viewDidLoad
122
+{
123
+    NSAssert(self.contentViewController != nil, @"contentViewController was not set");
124
+    
125
+    [super viewDidLoad];
126
+    self.view.translatesAutoresizingMaskIntoConstraints = self.storyboardsUseAutolayout;
127
+    self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
128
+    
129
+    if(self.leftSidebarViewController)
130
+    {
131
+        // Parent View Controller
132
+        [self addChildViewController:self.leftSidebarContainerViewController];
133
+        [self.view addSubview:self.leftSidebarContainerViewController.view];
134
+        [self.leftSidebarContainerViewController didMoveToParentViewController:self];
135
+        self.leftSidebarContainerViewController.view.translatesAutoresizingMaskIntoConstraints = self.storyboardsUseAutolayout;
136
+        self.leftSidebarContainerViewController.view.hidden = YES;
137
+        
138
+        // Child View Controller
139
+        [self.leftSidebarContainerViewController addChildViewController:self.leftSidebarViewController];
140
+        [self.leftSidebarContainerViewController.view addSubview:self.leftSidebarViewController.view];
141
+        [self.leftSidebarViewController didMoveToParentViewController:self.leftSidebarContainerViewController];
142
+    }
143
+    
144
+    if(self.rightSidebarViewController)
145
+    {
146
+        // Parent View Controller
147
+        [self addChildViewController:self.rightSidebarContainerViewController];
148
+        [self.view addSubview:self.rightSidebarContainerViewController.view];
149
+        [self.rightSidebarContainerViewController didMoveToParentViewController:self];
150
+        self.rightSidebarContainerViewController.view.translatesAutoresizingMaskIntoConstraints = self.storyboardsUseAutolayout;
151
+        self.rightSidebarContainerViewController.view.hidden = YES;
152
+        
153
+        // Child View Controller
154
+        [self.rightSidebarContainerViewController addChildViewController:self.rightSidebarViewController];
155
+        [self.rightSidebarContainerViewController.view addSubview:self.rightSidebarViewController.view];
156
+        [self.rightSidebarViewController didMoveToParentViewController:self.rightSidebarContainerViewController];
157
+    }
158
+    
159
+    
160
+    // Parent View Controller
161
+    [self addChildViewController:self.contentContainerViewController];
162
+    [self.view addSubview:self.contentContainerViewController.view];
163
+    [self.contentContainerViewController didMoveToParentViewController:self];
164
+    
165
+    // Child View Controller
166
+    [self.contentContainerViewController addChildViewController:self.contentViewController];
167
+    [self.contentContainerViewController.view addSubview:self.contentViewController.view];
168
+    [self.contentViewController didMoveToParentViewController:self.contentContainerViewController];
169
+}
170
+
171
+- (void)viewWillAppear:(BOOL)animated
172
+{
173
+    [super viewWillAppear:animated];
174
+}
175
+
176
+- (void)viewWillDisappear:(BOOL)animated
177
+{
178
+    [super viewWillDisappear:animated];
179
+}
180
+
181
+- (void)viewWillLayoutSubviews
182
+{
183
+    [super viewWillLayoutSubviews];
184
+}
185
+
186
+- (void)didReceiveMemoryWarning
187
+{
188
+    [super didReceiveMemoryWarning];
189
+}
190
+
191
+
192
+#pragma mark - TheSidebarController Presentation Methods
193
+- (void)dismissSidebarViewController
194
+{
195
+    [self hideSidebarViewController];
196
+}
197
+
198
+- (void)presentLeftSidebarViewController
199
+{
200
+    [self presentLeftSidebarViewControllerWithStyle:SidebarTransitionStyleFacebook];
201
+}
202
+
203
+- (void)presentLeftSidebarViewControllerWithStyle:(SidebarTransitionStyle)transitionStyle
204
+{
205
+    NSAssert(self.leftSidebarViewController != nil, @"leftSidebarViewController was not set");
206
+    [self showSidebarViewControllerFromSide:LeftSide withTransitionStyle:transitionStyle];
207
+}
208
+
209
+- (void)presentRightSidebarViewController
210
+{
211
+    [self presentRightSidebarViewControllerWithStyle:SidebarTransitionStyleFacebook];
212
+}
213
+
214
+- (void)presentRightSidebarViewControllerWithStyle:(SidebarTransitionStyle)transitionStyle
215
+{
216
+    NSAssert(self.rightSidebarViewController != nil, @"rightSidebarViewController was not set");
217
+    [self showSidebarViewControllerFromSide:RightSide withTransitionStyle:transitionStyle];
218
+}
219
+
220
+
221
+#pragma mark - TheSidebarController Private Methods
222
+- (void)showSidebarViewControllerFromSide:(Side)side withTransitionStyle:(SidebarTransitionStyle)transitionStyle
223
+{
224
+    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
225
+    self.view.autoresizingMask = UIViewAutoresizingNone;
226
+    
227
+    if(side == LeftSide)
228
+    {
229
+        self.leftSidebarContainerViewController.view.hidden = NO;
230
+        self.rightSidebarContainerViewController.view.hidden = YES;
231
+        self.selectedSidebarViewController = self.leftSidebarViewController;
232
+        self.view.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
233
+    }
234
+    else if(side == RightSide)
235
+    {
236
+        self.rightSidebarContainerViewController.view.hidden = NO;
237
+        self.leftSidebarContainerViewController.view.hidden = YES;
238
+        self.selectedSidebarViewController = self.rightSidebarViewController;
239
+        self.view.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight;
240
+    }
241
+    
242
+    self.selectedSide = side;
243
+    self.selectedTransitionStyle = transitionStyle;
244
+    
245
+    if([self.delegate conformsToProtocol:@protocol(TheSidebarControllerDelegate)] && [self.delegate respondsToSelector:@selector(sidebarController:willShowViewController:)])
246
+    {
247
+        [self.delegate sidebarController:self willShowViewController:self.selectedSidebarViewController];
248
+    }
249
+    
250
+    NSString *animationClassName = self.sidebarAnimations[transitionStyle];
251
+    Class animationClass = NSClassFromString(animationClassName);
252
+    [animationClass setOverlayContentColor:self.overlayContentColor];
253
+    [animationClass animateContentView:self.contentContainerViewController.view
254
+                           sidebarView:self.selectedSidebarViewController.parentViewController.view
255
+                              fromSide:self.selectedSide
256
+                          visibleWidth:self.visibleWidth
257
+                              duration:self.animationDuration
258
+                            completion:^(BOOL finished) {
259
+                                [[UIApplication sharedApplication] endIgnoringInteractionEvents];
260
+                                self.sidebarIsPresenting = YES;
261
+                                
262
+                                if([self.delegate conformsToProtocol:@protocol(TheSidebarControllerDelegate)] && [self.delegate respondsToSelector:@selector(sidebarController:didShowViewController:)])
263
+                                {
264
+                                    [self.delegate sidebarController:self didShowViewController:self.selectedSidebarViewController];
265
+                                }
266
+                            }
267
+     ];
268
+}
269
+
270
+- (void)hideSidebarViewController
271
+{
272
+    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
273
+    
274
+    if([self.delegate conformsToProtocol:@protocol(TheSidebarControllerDelegate)] && [self.delegate respondsToSelector:@selector(sidebarController:willHideViewController:)])
275
+    {
276
+        [self.delegate sidebarController:self willHideViewController:self.selectedSidebarViewController];
277
+    }
278
+    
279
+    NSString *animationClassName = self.sidebarAnimations[self.selectedTransitionStyle];
280
+    Class animationClass = NSClassFromString(animationClassName);
281
+    [animationClass reverseAnimateContentView:self.contentContainerViewController.view
282
+                                  sidebarView:self.selectedSidebarViewController.parentViewController.view
283
+                                     fromSide:self.selectedSide
284
+                                 visibleWidth:self.visibleWidth
285
+                                     duration:self.animationDuration
286
+                                   completion:^(BOOL finished) {
287
+                                       [[UIApplication sharedApplication] endIgnoringInteractionEvents];
288
+                                       self.sidebarIsPresenting = NO;
289
+                                       
290
+                                       if([self.delegate conformsToProtocol:@protocol(TheSidebarControllerDelegate)] && [self.delegate respondsToSelector:@selector(sidebarController:didHideViewController:)])
291
+                                       {
292
+                                           [self.delegate sidebarController:self didHideViewController:self.selectedSidebarViewController];
293
+                                       }
294
+                                   }
295
+     ];
296
+}
297
+
298
+
299
+#pragma mark - UIViewController Setters
300
+- (void)setContentViewController:(UIViewController *)contentViewController
301
+{
302
+    // Old View Controller
303
+    UIViewController *oldViewController = self.contentViewController;
304
+    [oldViewController willMoveToParentViewController:nil];
305
+    [oldViewController.view removeFromSuperview];
306
+    [oldViewController removeFromParentViewController];
307
+    
308
+    // New View Controller
309
+    UIViewController *newViewController = contentViewController;
310
+    [self.contentContainerViewController addChildViewController:newViewController];
311
+    [self.contentContainerViewController.view addSubview:newViewController.view];
312
+    [newViewController didMoveToParentViewController:self.contentContainerViewController];
313
+    
314
+    _contentViewController = newViewController;
315
+}
316
+
317
+- (void)setLeftSidebarViewController:(UIViewController *)leftSidebarViewController
318
+{
319
+    // Old View Controller
320
+    UIViewController *oldViewController = self.leftSidebarViewController;
321
+    [oldViewController willMoveToParentViewController:nil];
322
+    [oldViewController.view removeFromSuperview];
323
+    [oldViewController removeFromParentViewController];
324
+    
325
+    // New View Controller
326
+    UIViewController *newViewController = leftSidebarViewController;
327
+    [self.leftSidebarContainerViewController addChildViewController:newViewController];
328
+    [self.leftSidebarContainerViewController.view addSubview:newViewController.view];
329
+    [newViewController didMoveToParentViewController:self.leftSidebarContainerViewController];
330
+    
331
+    _leftSidebarViewController = newViewController;
332
+}
333
+
334
+- (void)setRightSidebarViewController:(UIViewController *)rightSidebarViewController
335
+{
336
+    // Old View Controller
337
+    UIViewController *oldViewController = self.leftSidebarViewController;
338
+    [oldViewController willMoveToParentViewController:nil];
339
+    [oldViewController.view removeFromSuperview];
340
+    [oldViewController removeFromParentViewController];
341
+    
342
+    // New View Controller
343
+    UIViewController *newViewController = rightSidebarViewController;
344
+    [self.rightSidebarContainerViewController addChildViewController:newViewController];
345
+    [self.rightSidebarContainerViewController.view addSubview:newViewController.view];
346
+    [newViewController didMoveToParentViewController:self.rightSidebarContainerViewController];
347
+    
348
+    _rightSidebarViewController = newViewController;
349
+}
350
+
351
+
352
+#pragma mark - Autorotation Delegates
353
+- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
354
+{
355
+    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
356
+    
357
+    if((toInterfaceOrientation == UIInterfaceOrientationPortrait) ||
358
+       (toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown))
359
+    {
360
+        NSLog(@"Portrait");
361
+    }
362
+    else if((toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
363
+            (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight))
364
+    {
365
+        NSLog(@"Landscape");
366
+    }
367
+    
368
+    
369
+}
370
+
371
+
372
+#pragma mark - Helpers
373
+- (void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
374
+{
375
+    CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x, view.bounds.size.height * anchorPoint.y);
376
+    CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x, view.bounds.size.height * view.layer.anchorPoint.y);
377
+    
378
+    newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
379
+    oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
380
+    
381
+    CGPoint position = view.layer.position;
382
+    
383
+    position.x -= oldPoint.x;
384
+    position.x += newPoint.x;
385
+    
386
+    position.y -= oldPoint.y;
387
+    position.y += newPoint.y;
388
+    
389
+    view.layer.position = position;
390
+    view.layer.anchorPoint = anchorPoint;
391
+}
392
+
393
+@end
394
+
395
+
396
+#pragma mark - TheSidebarController Category
397
+@implementation UIViewController(TheSidebarController)
398
+
399
+- (TheSidebarController *)sidebarController
400
+{
401
+    if([self.parentViewController.parentViewController isKindOfClass:[TheSidebarController class]])
402
+    {
403
+        return (TheSidebarController *)self.parentViewController.parentViewController;
404
+    }
405
+    else if([self.parentViewController isKindOfClass:[UINavigationController class]] &&
406
+            [self.parentViewController.parentViewController.parentViewController isKindOfClass:[TheSidebarController class]])
407
+    {
408
+        return (TheSidebarController *)self.parentViewController.parentViewController.parentViewController;
409
+    }
410
+    
411
+    return nil;
412
+}
413
+
414
+@end

+ 18
- 0
ios/RCCExternalViewControllerProtocol.h View File

@@ -0,0 +1,18 @@
1
+//
2
+//  ExternalViewControllerProtocol.h
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Artal Druk on 01/06/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import "RCCViewController.h"
11
+
12
+@protocol RCCExternalViewControllerProtocol <NSObject>
13
+
14
+@property (nullable, nonatomic, weak) id <RCCViewControllerDelegate> controllerDelegate;
15
+
16
+-(void)setProps:(nullable NSDictionary*)props;
17
+
18
+@end

+ 7
- 0
ios/RCCLightBox.h View File

@@ -0,0 +1,7 @@
1
+
2
+#import <UIKit/UIKit.h>
3
+
4
+@interface RCCLightBox : NSObject
5
++(void)showWithParams:(NSDictionary*)params;
6
++(void)dismiss;
7
+@end

+ 235
- 0
ios/RCCLightBox.m View File

@@ -0,0 +1,235 @@
1
+#import "RCCLightBox.h"
2
+#import "RCCManager.h"
3
+#import "RCTRootView.h"
4
+#import "RCTRootViewDelegate.h"
5
+#import "RCTConvert.h"
6
+#import "RCTHelpers.h"
7
+#import <objc/runtime.h>
8
+
9
+const NSInteger kLightBoxTag = 0x101010;
10
+
11
+@interface RCCLightBoxView : UIView
12
+@property (nonatomic, strong) RCTRootView *reactView;
13
+@property (nonatomic, strong) UIVisualEffectView *visualEffectView;
14
+@property (nonatomic, strong) UIView *overlayColorView;
15
+@property (nonatomic, strong) NSDictionary *params;
16
+@property (nonatomic)         BOOL yellowBoxRemoved;
17
+@end
18
+
19
+@implementation RCCLightBoxView
20
+
21
+-(instancetype)initWithFrame:(CGRect)frame params:(NSDictionary*)params
22
+{
23
+    self = [super initWithFrame:frame];
24
+    if (self)
25
+    {
26
+        self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
27
+        
28
+        self.params = params;
29
+        self.yellowBoxRemoved = NO;
30
+        
31
+        NSDictionary *passProps = self.params[@"passProps"];
32
+        
33
+        NSDictionary *style = self.params[@"style"];
34
+        if (self.params != nil && style != nil)
35
+        {
36
+            
37
+            if (style[@"backgroundBlur"] != nil && ![style[@"backgroundBlur"] isEqualToString:@"none"])
38
+            {
39
+                self.visualEffectView = [[UIVisualEffectView alloc] init];
40
+                self.visualEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
41
+                self.visualEffectView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
42
+                [self addSubview:self.visualEffectView];
43
+            }
44
+            
45
+            if (style[@"backgroundColor"] != nil)
46
+            {
47
+                UIColor *backgroundColor = [RCTConvert UIColor:style[@"backgroundColor"]];
48
+                if (backgroundColor != nil)
49
+                {
50
+                    self.overlayColorView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
51
+                    self.overlayColorView.backgroundColor = backgroundColor;
52
+                    self.overlayColorView.alpha = 0;
53
+                    [self addSubview:self.overlayColorView];
54
+                }
55
+            }
56
+        }
57
+        
58
+        self.reactView = [[RCTRootView alloc] initWithBridge:[[RCCManager sharedInstance] getBridge] moduleName:self.params[@"component"] initialProperties:passProps];
59
+        self.reactView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
60
+        self.reactView.backgroundColor = [UIColor clearColor];
61
+        self.reactView.sizeFlexibility = RCTRootViewSizeFlexibilityWidthAndHeight;
62
+        self.reactView.center = self.center;
63
+        [self addSubview:self.reactView];
64
+        
65
+        [self.reactView.contentView.layer addObserver:self forKeyPath:@"frame" options:0 context:nil];
66
+        [self.reactView.contentView.layer addObserver:self forKeyPath:@"bounds" options:0 context:NULL];
67
+        
68
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRNReload) name:RCTReloadNotification object:nil];
69
+    }
70
+    return self;
71
+}
72
+
73
+-(void)layoutSubviews
74
+{
75
+    [super layoutSubviews];
76
+    
77
+    if(!self.yellowBoxRemoved)
78
+    {
79
+        self.yellowBoxRemoved = [RCTHelpers removeYellowBox:self.reactView];
80
+    }
81
+}
82
+
83
+-(void)removeAllObservers
84
+{
85
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
86
+    [self.reactView.contentView.layer removeObserver:self forKeyPath:@"frame" context:nil];
87
+    [self.reactView.contentView.layer removeObserver:self forKeyPath:@"bounds" context:NULL];
88
+}
89
+
90
+-(void)dealloc
91
+{
92
+    [self removeAllObservers];
93
+}
94
+
95
+-(void)onRNReload
96
+{
97
+    [self removeAllObservers];
98
+    [self removeFromSuperview];
99
+    self.reactView = nil;
100
+}
101
+
102
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
103
+{
104
+    CGSize frameSize = CGSizeZero;
105
+    if ([object isKindOfClass:[CALayer class]])
106
+        frameSize = ((CALayer*)object).frame.size;
107
+    if ([object isKindOfClass:[UIView class]])
108
+        frameSize = ((UIView*)object).frame.size;
109
+    
110
+    if (!CGSizeEqualToSize(frameSize, self.reactView.frame.size))
111
+    {
112
+        self.reactView.frame = CGRectMake((self.frame.size.width - frameSize.width) * 0.5, (self.frame.size.height - frameSize.height) * 0.5, frameSize.width, frameSize.height);
113
+    }
114
+}
115
+
116
+-(UIBlurEffect*)blurEfectForCurrentStyle
117
+{
118
+    NSDictionary *style = self.params[@"style"];
119
+    NSString *backgroundBlur = style[@"backgroundBlur"];
120
+    if ([backgroundBlur isEqualToString:@"none"])
121
+    {
122
+        return nil;
123
+    }
124
+    
125
+    UIBlurEffectStyle blurEffectStyle = UIBlurEffectStyleDark;
126
+    if ([backgroundBlur isEqualToString:@"light"])
127
+        blurEffectStyle = UIBlurEffectStyleLight;
128
+    else if ([backgroundBlur isEqualToString:@"xlight"])
129
+        blurEffectStyle = UIBlurEffectStyleExtraLight;
130
+    else if ([backgroundBlur isEqualToString:@"dark"])
131
+        blurEffectStyle = UIBlurEffectStyleDark;
132
+    return [UIBlurEffect effectWithStyle:blurEffectStyle];
133
+}
134
+
135
+-(void)showAnimated
136
+{
137
+    if (self.visualEffectView != nil || self.overlayColorView != nil)
138
+    {
139
+        [UIView animateWithDuration:0.3 animations:^()
140
+         {
141
+             if (self.visualEffectView != nil)
142
+             {
143
+                 self.visualEffectView.effect = [self blurEfectForCurrentStyle];
144
+             }
145
+             
146
+             if (self.overlayColorView != nil)
147
+             {
148
+                 self.overlayColorView.alpha = 1;
149
+             }
150
+         }];
151
+    }
152
+    
153
+    self.reactView.transform = CGAffineTransformMakeTranslation(0, 100);
154
+    self.reactView.alpha = 0;
155
+    [UIView animateWithDuration:0.6 delay:0.2 usingSpringWithDamping:0.65 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseOut animations:^()
156
+    {
157
+        self.reactView.transform = CGAffineTransformIdentity;
158
+        self.reactView.alpha = 1;
159
+    } completion:nil];
160
+}
161
+
162
+-(void)dismissAnimated
163
+{
164
+    BOOL hasOverlayViews = (self.visualEffectView != nil || self.overlayColorView != nil);
165
+    
166
+    [UIView animateWithDuration:0.2 animations:^()
167
+    {
168
+        self.reactView.transform = CGAffineTransformMakeTranslation(0, 80);
169
+        self.reactView.alpha = 0;
170
+    }
171
+                     completion:^(BOOL finished)
172
+    {
173
+        if (!hasOverlayViews)
174
+        {
175
+            [self removeFromSuperview];
176
+        }
177
+    }];
178
+    
179
+    if (hasOverlayViews)
180
+    {
181
+        [UIView animateWithDuration:0.25 delay:0.15 options:UIViewAnimationOptionCurveEaseOut animations:^()
182
+         {
183
+             if (self.visualEffectView != nil)
184
+             {
185
+                 self.visualEffectView.effect = nil;
186
+             }
187
+             
188
+             if (self.overlayColorView != nil)
189
+             {
190
+                 self.overlayColorView.alpha = 0;
191
+             }
192
+             
193
+         } completion:^(BOOL finished)
194
+         {
195
+             [self removeFromSuperview];
196
+         }];
197
+    }
198
+}
199
+
200
+@end
201
+
202
+@implementation RCCLightBox
203
+
204
++(UIWindow*)getWindow
205
+{
206
+    UIApplication *app = [UIApplication sharedApplication];
207
+    UIWindow *window = (app.keyWindow != nil) ? app.keyWindow : app.windows[0];
208
+    return window;
209
+}
210
+
211
++(void)showWithParams:(NSDictionary*)params
212
+{
213
+    UIWindow *window = [RCCLightBox getWindow];
214
+    if ([window viewWithTag:kLightBoxTag] != nil)
215
+    {
216
+        return;
217
+    }
218
+    
219
+    RCCLightBoxView *lightBox = [[RCCLightBoxView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) params:params];
220
+    lightBox.tag = kLightBoxTag;
221
+    [window addSubview:lightBox];
222
+    [lightBox showAnimated];
223
+}
224
+
225
++(void)dismiss
226
+{
227
+    UIWindow *window = [RCCLightBox getWindow];
228
+    RCCLightBoxView *lightBox = [window viewWithTag:kLightBoxTag];
229
+    if (lightBox != nil)
230
+    {
231
+        [lightBox dismissAnimated];
232
+    }
233
+}
234
+
235
+@end

+ 21
- 0
ios/RCCManager.h View File

@@ -0,0 +1,21 @@
1
+#import <Foundation/Foundation.h>
2
+#import "RCTBridgeModule.h"
3
+#import <UIKit/UIKit.h>
4
+
5
+@interface RCCManager : NSObject
6
+
7
++ (instancetype)sharedInstance;
8
++ (instancetype)sharedIntance;
9
+
10
+-(void)initBridgeWithBundleURL:(NSURL *)bundleURL;
11
+-(void)initBridgeWithBundleURL:(NSURL *)bundleURL launchOptions:(NSDictionary *)launchOptions;
12
+-(RCTBridge*)getBridge;
13
+-(UIWindow*)getAppWindow;
14
+
15
+-(void)registerController:(UIViewController*)controller componentId:(NSString*)componentId componentType:(NSString*)componentType;
16
+-(id)getControllerWithId:(NSString*)componentId componentType:(NSString*)componentType;
17
+-(void)unregisterController:(UIViewController*)vc;
18
+
19
+-(void)clearModuleRegistry;
20
+
21
+@end

+ 221
- 0
ios/RCCManager.m View File

@@ -0,0 +1,221 @@
1
+#import "RCCManager.h"
2
+#import "RCTBridge.h"
3
+#import "RCTRedBox.h"
4
+#import <Foundation/Foundation.h>
5
+
6
+@interface RCCManager() <RCTBridgeDelegate>
7
+@property (nonatomic, strong) NSMutableDictionary *modulesRegistry;
8
+@property (nonatomic, strong) RCTBridge *sharedBridge;
9
+@property (nonatomic, strong) NSURL *bundleURL;
10
+@end
11
+
12
+@implementation RCCManager
13
+
14
++ (instancetype)sharedInstance
15
+{
16
+  static RCCManager *sharedInstance = nil;
17
+  static dispatch_once_t onceToken = 0;
18
+
19
+  dispatch_once(&onceToken,^{
20
+    if (sharedInstance == nil)
21
+    {
22
+      sharedInstance = [[RCCManager alloc] init];
23
+    }
24
+  });
25
+
26
+  return sharedInstance;
27
+}
28
+
29
++ (instancetype)sharedIntance
30
+{
31
+  return [RCCManager sharedInstance];
32
+}
33
+
34
+- (instancetype)init
35
+{
36
+  self = [super init];
37
+  if (self)
38
+  {
39
+    self.modulesRegistry = [@{} mutableCopy];
40
+    
41
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRNReload) name:RCTReloadNotification object:nil];
42
+  }
43
+  return self;
44
+}
45
+
46
+-(void)clearModuleRegistry
47
+{
48
+  [self.modulesRegistry removeAllObjects];
49
+}
50
+
51
+-(void)onRNReload
52
+{
53
+  id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
54
+  appDelegate.window.rootViewController = nil;
55
+  [self clearModuleRegistry];
56
+}
57
+
58
+-(void)registerController:(UIViewController*)controller componentId:(NSString*)componentId componentType:(NSString*)componentType
59
+{
60
+  if (controller == nil || componentId == nil)
61
+  {
62
+    return;
63
+  }
64
+
65
+  NSMutableDictionary *componentsDic = self.modulesRegistry[componentType];
66
+  if (componentsDic == nil)
67
+  {
68
+    componentsDic = [@{} mutableCopy];
69
+    self.modulesRegistry[componentType] = componentsDic;
70
+  }
71
+
72
+  /*
73
+  TODO: we really want this error, but we need to unregister controllers when they dealloc
74
+  if (componentsDic[componentId])
75
+  {
76
+    [self.sharedBridge.redBox showErrorMessage:[NSString stringWithFormat:@"Controllers: controller with id %@ is already registered. Make sure all of the controller id's you use are unique.", componentId]];
77
+  }
78
+  */
79
+   
80
+  componentsDic[componentId] = controller;
81
+}
82
+
83
+-(void)unregisterController:(UIViewController*)vc
84
+{
85
+  if (vc == nil) return;
86
+  
87
+  for (NSString *key in [self.modulesRegistry allKeys])
88
+  {
89
+    NSMutableDictionary *componentsDic = self.modulesRegistry[key];
90
+    for (NSString *componentID in [componentsDic allKeys])
91
+    {
92
+      UIViewController *tmpVc = componentsDic[componentID];
93
+      if (tmpVc == vc)
94
+      {
95
+        [componentsDic removeObjectForKey:componentID];
96
+      }
97
+    }
98
+  }
99
+}
100
+
101
+-(id)getControllerWithId:(NSString*)componentId componentType:(NSString*)componentType
102
+{
103
+  if (componentId == nil)
104
+  {
105
+    return nil;
106
+  }
107
+
108
+  id component = nil;
109
+
110
+  NSMutableDictionary *componentsDic = self.modulesRegistry[componentType];
111
+  if (componentsDic != nil)
112
+  {
113
+    component = componentsDic[componentId];
114
+  }
115
+
116
+  return component;
117
+}
118
+
119
+-(void)initBridgeWithBundleURL:(NSURL *)bundleURL
120
+{
121
+  [self initBridgeWithBundleURL :bundleURL launchOptions:nil];
122
+}
123
+
124
+-(void)initBridgeWithBundleURL:(NSURL *)bundleURL launchOptions:(NSDictionary *)launchOptions
125
+{
126
+  if (self.sharedBridge) return;
127
+
128
+  self.bundleURL = bundleURL;
129
+  self.sharedBridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
130
+  
131
+  [self showSplashScreen];
132
+}
133
+
134
+-(void)showSplashScreen
135
+{
136
+  CGRect screenBounds = [UIScreen mainScreen].bounds;
137
+  UIView *splashView = nil;
138
+  
139
+  NSString* launchStoryBoard = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
140
+  if (launchStoryBoard != nil)
141
+  {//load the splash from the storyboard that's defined in the info.plist as the LaunchScreen
142
+    @try
143
+    {
144
+      splashView = [[NSBundle mainBundle] loadNibNamed:launchStoryBoard owner:self options:nil][0];
145
+      if (splashView != nil)
146
+      {
147
+        splashView.frame = CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height);
148
+      }
149
+    }
150
+    @catch(NSException *e)
151
+    {
152
+      splashView = nil;
153
+    }
154
+  }
155
+  else
156
+  {//load the splash from the DEfault image or from LaunchImage in the xcassets
157
+    CGFloat screenHeight = screenBounds.size.height;
158
+    
159
+    NSString* imageName = @"Default";
160
+    if (screenHeight == 568)
161
+      imageName = [imageName stringByAppendingString:@"-568h"];
162
+    else if (screenHeight == 667)
163
+      imageName = [imageName stringByAppendingString:@"-667h"];
164
+    else if (screenHeight == 736)
165
+      imageName = [imageName stringByAppendingString:@"-736h"];
166
+    
167
+    //xcassets LaunchImage files
168
+    UIImage *image = [UIImage imageNamed:imageName];
169
+    if (image == nil)
170
+    {
171
+      imageName = @"LaunchImage";
172
+      
173
+      if (screenHeight == 480)
174
+        imageName = [imageName stringByAppendingString:@"-700"];
175
+      if (screenHeight == 568)
176
+        imageName = [imageName stringByAppendingString:@"-700-568h"];
177
+      else if (screenHeight == 667)
178
+        imageName = [imageName stringByAppendingString:@"-800-667h"];
179
+      else if (screenHeight == 736)
180
+        imageName = [imageName stringByAppendingString:@"-800-Portrait-736h"];
181
+      
182
+      image = [UIImage imageNamed:imageName];
183
+    }
184
+    
185
+    if (image != nil)
186
+    {
187
+      splashView = [[UIImageView alloc] initWithImage:image];
188
+    }
189
+  }
190
+  
191
+  if (splashView != nil)
192
+  {
193
+    UIViewController *splashVC = [[UIViewController alloc] init];
194
+    splashVC.view = splashView;
195
+    
196
+    id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
197
+    appDelegate.window.rootViewController = splashVC;
198
+    [appDelegate.window makeKeyAndVisible];
199
+  }
200
+}
201
+
202
+-(RCTBridge*)getBridge
203
+{
204
+  return self.sharedBridge;
205
+}
206
+
207
+-(UIWindow*)getAppWindow
208
+{
209
+  UIApplication *app = [UIApplication sharedApplication];
210
+  UIWindow *window = (app.keyWindow != nil) ? app.keyWindow : app.windows[0];
211
+  return window;
212
+}
213
+
214
+#pragma mark - RCTBridgeDelegate methods
215
+
216
+- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
217
+{
218
+  return self.bundleURL;
219
+}
220
+
221
+@end

+ 8
- 0
ios/RCCManagerModule.h View File

@@ -0,0 +1,8 @@
1
+#import <Foundation/Foundation.h>
2
+#import "RCTBridgeModule.h"
3
+#import <UIKit/UIKit.h>
4
+
5
+
6
+@interface RCCManagerModule : NSObject <RCTBridgeModule>
7
++(void)cancelAllRCCViewControllerReactTouches;
8
+@end

+ 378
- 0
ios/RCCManagerModule.m View File

@@ -0,0 +1,378 @@
1
+#import "RCCManagerModule.h"
2
+#import "RCCManager.h"
3
+#import <UIKit/UIKit.h>
4
+#import "RCCNavigationController.h"
5
+#import "RCCViewController.h"
6
+#import "RCCDrawerController.h"
7
+#import "RCCLightBox.h"
8
+#import "RCTConvert.h"
9
+#import "RCCTabBarController.h"
10
+#import "RCCTheSideBarManagerViewController.h"
11
+#import "RCCNotification.h"
12
+
13
+#define kSlideDownAnimationDuration 0.35
14
+
15
+typedef NS_ENUM(NSInteger, RCCManagerModuleErrorCode)
16
+{
17
+    RCCManagerModuleCantCreateControllerErrorCode   = -100,
18
+    RCCManagerModuleCantFindTabControllerErrorCode  = -200,
19
+    RCCManagerModuleMissingParamsErrorCode          = -300
20
+};
21
+
22
+@implementation RCTConvert (RCCManagerModuleErrorCode)
23
+
24
+RCT_ENUM_CONVERTER(RCCManagerModuleErrorCode,
25
+                   (@{@"RCCManagerModuleCantCreateControllerErrorCode": @(RCCManagerModuleCantCreateControllerErrorCode),
26
+                      @"RCCManagerModuleCantFindTabControllerErrorCode": @(RCCManagerModuleCantFindTabControllerErrorCode),
27
+                      }), RCCManagerModuleCantCreateControllerErrorCode, integerValue)
28
+@end
29
+
30
+@implementation RCCManagerModule
31
+
32
+RCT_EXPORT_MODULE(RCCManager);
33
+
34
+#pragma mark - constatnts export
35
+
36
+- (NSDictionary *)constantsToExport
37
+{
38
+    return @{
39
+             //Error codes
40
+             @"RCCManagerModuleCantCreateControllerErrorCode" : @(RCCManagerModuleCantCreateControllerErrorCode),
41
+             @"RCCManagerModuleCantFindTabControllerErrorCode" : @(RCCManagerModuleCantFindTabControllerErrorCode),
42
+             };
43
+}
44
+
45
+- (dispatch_queue_t)methodQueue
46
+{
47
+    return dispatch_get_main_queue();
48
+}
49
+
50
+#pragma mark - helper methods
51
+
52
++(UIViewController*)modalPresenterViewControllers:(NSMutableArray*)returnAllPresenters
53
+{
54
+    UIViewController *modalPresenterViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
55
+    if ((returnAllPresenters != nil) && (modalPresenterViewController != nil))
56
+    {
57
+        [returnAllPresenters addObject:modalPresenterViewController];
58
+    }
59
+    
60
+    while (modalPresenterViewController.presentedViewController != nil)
61
+    {
62
+        modalPresenterViewController = modalPresenterViewController.presentedViewController;
63
+        
64
+        if (returnAllPresenters != nil)
65
+        {
66
+            [returnAllPresenters addObject:modalPresenterViewController];
67
+        }
68
+    }
69
+    return modalPresenterViewController;
70
+}
71
+
72
++(UIViewController*)lastModalPresenterViewController
73
+{
74
+    return [self modalPresenterViewControllers:nil];
75
+}
76
+
77
++(NSError*)rccErrorWithCode:(NSInteger)code description:(NSString*)description
78
+{
79
+    NSString *safeDescription = (description == nil) ? @"" : description;
80
+    return [NSError errorWithDomain:@"RCCControllers" code:code userInfo:@{NSLocalizedDescriptionKey: safeDescription}];
81
+}
82
+
83
++(void)handleRCTPromiseRejectBlock:(RCTPromiseRejectBlock)reject error:(NSError*)error
84
+{
85
+    reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error);
86
+}
87
+
88
++(void)cancelAllRCCViewControllerReactTouches
89
+{
90
+    [[NSNotificationCenter defaultCenter] postNotificationName:RCCViewControllerCancelReactTouchesNotification object:nil];
91
+}
92
+
93
+-(void)animateSnapshot:(UIView*)snapshot animationType:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve
94
+{
95
+    [UIView animateWithDuration:kSlideDownAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^()
96
+     {
97
+         if (animationType == nil || [animationType isEqualToString:@"slide-down"])
98
+         {
99
+             snapshot.transform = CGAffineTransformMakeTranslation(0, snapshot.frame.size.height);
100
+         }
101
+         else if ([animationType isEqualToString:@"fade"])
102
+         {
103
+             snapshot.alpha = 0;
104
+         }
105
+     }
106
+                     completion:^(BOOL finished)
107
+     {
108
+         [snapshot removeFromSuperview];
109
+         
110
+         if (resolve != nil)
111
+         {
112
+             resolve(nil);
113
+         }
114
+     }];
115
+}
116
+
117
+-(void)dismissAllModalPresenters:(NSMutableArray*)allPresentedViewControllers resolver:(RCTPromiseResolveBlock)resolve
118
+{
119
+    if (allPresentedViewControllers.count > 0)
120
+    {
121
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^
122
+        {
123
+            __block NSUInteger counter = 0;
124
+            for (UIViewController *viewController in allPresentedViewControllers)
125
+            {
126
+                counter++;
127
+                
128
+                [[RCCManager sharedIntance] unregisterController:viewController];
129
+                if (viewController.presentedViewController != nil)
130
+                {
131
+                    dispatch_semaphore_t dismiss_sema = dispatch_semaphore_create(0);
132
+                    
133
+                    dispatch_async(dispatch_get_main_queue(), ^
134
+                    {
135
+                        [viewController dismissViewControllerAnimated:NO completion:^()
136
+                         {
137
+                             if (counter == allPresentedViewControllers.count && allPresentedViewControllers.count > 0)
138
+                             {
139
+                                 [allPresentedViewControllers removeAllObjects];
140
+                                 
141
+                                 if (resolve != nil)
142
+                                 {
143
+                                     resolve(nil);
144
+                                 }
145
+                             }
146
+                             dispatch_semaphore_signal(dismiss_sema);
147
+                         }];
148
+                    });
149
+                    
150
+                    dispatch_semaphore_wait(dismiss_sema, DISPATCH_TIME_FOREVER);
151
+                }
152
+                else if (counter == allPresentedViewControllers.count && allPresentedViewControllers.count > 0)
153
+                {
154
+                    [allPresentedViewControllers removeAllObjects];
155
+                    
156
+                    if (resolve != nil)
157
+                    {
158
+                        dispatch_async(dispatch_get_main_queue(), ^
159
+                        {
160
+                            resolve(nil);
161
+                        });
162
+                    }
163
+                }
164
+            }
165
+        });
166
+    }
167
+    else if (resolve != nil)
168
+    {
169
+        resolve(nil);
170
+    }
171
+}
172
+
173
+#pragma mark - RCT exported methods
174
+
175
+RCT_EXPORT_METHOD(
176
+setRootController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps)
177
+{
178
+    if ([[RCCManager sharedInstance] getBridge].loading) {
179
+        [self deferSetRootControllerWhileBridgeLoading:layout animationType:animationType globalProps:globalProps];
180
+        return;
181
+    }
182
+    
183
+    dispatch_async(dispatch_get_main_queue(), ^{
184
+        [self performSetRootController:layout animationType:animationType globalProps:globalProps];
185
+   });
186
+}
187
+
188
+/**
189
+ * on RN31 there's a timing issue, we must wait for the bridge to finish loading
190
+ */
191
+-(void)deferSetRootControllerWhileBridgeLoading:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps
192
+{
193
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
194
+        [self setRootController:layout animationType:animationType globalProps:globalProps];
195
+    });
196
+}
197
+
198
+-(void)performSetRootController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps
199
+{
200
+    // first clear the registry to remove any refernece to the previous controllers
201
+    [[RCCManager sharedInstance] clearModuleRegistry];
202
+    
203
+    // create the new controller
204
+    UIViewController *controller = [RCCViewController controllerWithLayout:layout globalProps:globalProps bridge:[[RCCManager sharedInstance] getBridge]];
205
+    if (controller == nil) return;
206
+    
207
+    id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
208
+    BOOL animated = !((appDelegate.window.rootViewController == nil) || ([animationType isEqualToString:@"none"]));
209
+    
210
+    // if we're animating - add a snapshot now
211
+    UIViewController *presentedViewController = nil;
212
+    UIView *snapshot = nil;
213
+    if (animated)
214
+    {
215
+        if(appDelegate.window.rootViewController.presentedViewController != nil)
216
+            presentedViewController = appDelegate.window.rootViewController.presentedViewController;
217
+        else
218
+            presentedViewController = appDelegate.window.rootViewController;
219
+        
220
+        snapshot = [presentedViewController.view snapshotViewAfterScreenUpdates:NO];
221
+        [appDelegate.window.rootViewController.view addSubview:snapshot];
222
+    }
223
+    
224
+    // dismiss the modal controllers without animation just so they can be released
225
+    [self dismissAllControllers:@"none" resolver:^(id result)
226
+     {
227
+         // set the new controller as the root
228
+         appDelegate.window.rootViewController = controller;
229
+         [appDelegate.window makeKeyAndVisible];
230
+         [presentedViewController dismissViewControllerAnimated:NO completion:nil];
231
+         
232
+         if (animated)
233
+         {
234
+             // move the snaphot to the new root and animate it
235
+             [appDelegate.window.rootViewController.view addSubview:snapshot];
236
+             [self animateSnapshot:snapshot animationType:animationType resolver:nil];
237
+         }
238
+     } rejecter:nil];
239
+}
240
+
241
+RCT_EXPORT_METHOD(
242
+NavigationControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams)
243
+{
244
+  if (!controllerId || !performAction) return;
245
+  RCCNavigationController* controller = [[RCCManager sharedInstance] getControllerWithId:controllerId componentType:@"NavigationControllerIOS"];
246
+  if (!controller || ![controller isKindOfClass:[RCCNavigationController class]]) return;
247
+  return [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedInstance] getBridge]];
248
+}
249
+
250
+RCT_EXPORT_METHOD(
251
+DrawerControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams)
252
+{
253
+  if (!controllerId || !performAction) return;
254
+
255
+  id<RCCDrawerDelegate> controller = [[RCCManager sharedIntance] getControllerWithId:controllerId componentType:@"DrawerControllerIOS"];
256
+  if (!controller || (![controller isKindOfClass:[RCCDrawerController class]] && ![controller isKindOfClass:[RCCTheSideBarManagerViewController class]])) return;
257
+  return [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedIntance] getBridge]];
258
+
259
+}
260
+
261
+RCT_EXPORT_METHOD(
262
+TabBarControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
263
+{
264
+    if (!controllerId || !performAction)
265
+    {
266
+        [RCCManagerModule handleRCTPromiseRejectBlock:reject
267
+                                                error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleMissingParamsErrorCode description:@"missing params"]];
268
+        return;
269
+    }
270
+    
271
+    RCCTabBarController* controller = [[RCCManager sharedInstance] getControllerWithId:controllerId componentType:@"TabBarControllerIOS"];
272
+    if (!controller || ![controller isKindOfClass:[RCCTabBarController class]])
273
+    {
274
+        [RCCManagerModule handleRCTPromiseRejectBlock:reject
275
+                                                error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleCantFindTabControllerErrorCode description:@"could not find UITabBarController"]];
276
+        return;
277
+    }
278
+    [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedInstance] getBridge] completion:^(){ resolve(nil); }];
279
+}
280
+
281
+RCT_EXPORT_METHOD(
282
+modalShowLightBox:(NSDictionary*)params)
283
+{
284
+    [RCCLightBox showWithParams:params];
285
+}
286
+
287
+RCT_EXPORT_METHOD(
288
+modalDismissLightBox)
289
+{
290
+    [RCCLightBox dismiss];
291
+}
292
+
293
+RCT_EXPORT_METHOD(
294
+showController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
295
+{
296
+    UIViewController *controller = [RCCViewController controllerWithLayout:layout globalProps:globalProps bridge:[[RCCManager sharedInstance] getBridge]];
297
+    if (controller == nil)
298
+    {
299
+        [RCCManagerModule handleRCTPromiseRejectBlock:reject
300
+                                                error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleCantCreateControllerErrorCode description:@"could not create controller"]];
301
+        return;
302
+    }
303
+
304
+    [[RCCManagerModule lastModalPresenterViewController] presentViewController:controller
305
+                                                           animated:![animationType isEqualToString:@"none"]
306
+                                                         completion:^(){ resolve(nil); }];
307
+}
308
+
309
+-(BOOL)viewControllerIsModal:(UIViewController*)viewController
310
+{
311
+    BOOL viewControllerIsModal = (viewController.presentingViewController.presentedViewController == viewController)
312
+                                || ((viewController.navigationController != nil) && (viewController.navigationController.presentingViewController.presentedViewController == viewController.navigationController) && (viewController == viewController.navigationController.viewControllers[0]))
313
+                                || ([viewController.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]]);
314
+    return viewControllerIsModal;
315
+}
316
+
317
+RCT_EXPORT_METHOD(
318
+dismissController:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
319
+{
320
+    UIViewController* vc = [RCCManagerModule lastModalPresenterViewController];
321
+    if ([self viewControllerIsModal:vc])
322
+    {
323
+        [[RCCManager sharedIntance] unregisterController:vc];
324
+        
325
+        [vc dismissViewControllerAnimated:![animationType isEqualToString:@"none"]
326
+                               completion:^(){ resolve(nil); }];
327
+    }
328
+}
329
+
330
+RCT_EXPORT_METHOD(
331
+dismissAllControllers:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
332
+{
333
+    if([UIApplication sharedApplication].delegate.window.rootViewController.presentedViewController == nil)
334
+    {//if there are no modal - do nothing
335
+        resolve(nil);
336
+        return;
337
+    }
338
+    
339
+    NSMutableArray *allPresentedViewControllers = [NSMutableArray array];
340
+    [RCCManagerModule modalPresenterViewControllers:allPresentedViewControllers];
341
+    
342
+    BOOL animated = ![animationType isEqualToString:@"none"];
343
+    if (animated)
344
+    {
345
+        id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
346
+        UIView *snapshot = [appDelegate.window snapshotViewAfterScreenUpdates:NO];
347
+        [appDelegate.window addSubview:snapshot];
348
+        
349
+        [self dismissAllModalPresenters:allPresentedViewControllers resolver:^(id result)
350
+        {
351
+            [self animateSnapshot:snapshot animationType:animationType resolver:resolve];
352
+        }];
353
+    }
354
+    else
355
+    {
356
+        [self dismissAllModalPresenters:allPresentedViewControllers resolver:resolve];
357
+    }
358
+}
359
+
360
+RCT_EXPORT_METHOD(
361
+showNotification:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
362
+{
363
+    [RCCNotification showWithParams:params resolver:resolve rejecter:reject];
364
+}
365
+
366
+RCT_EXPORT_METHOD(
367
+dismissNotification:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
368
+{
369
+    [RCCNotification dismissWithParams:params resolver:resolve rejecter:reject];
370
+}
371
+
372
+RCT_EXPORT_METHOD(
373
+cancelAllReactTouches)
374
+{
375
+    [RCCManagerModule cancelAllRCCViewControllerReactTouches];
376
+}
377
+
378
+@end

+ 9
- 0
ios/RCCNavigationController.h View File

@@ -0,0 +1,9 @@
1
+#import <UIKit/UIKit.h>
2
+#import "RCTBridge.h"
3
+
4
+@interface RCCNavigationController : UINavigationController
5
+
6
+- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary*)globalProps bridge:(RCTBridge *)bridge;
7
+- (void)performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams bridge:(RCTBridge *)bridge;
8
+
9
+@end

+ 298
- 0
ios/RCCNavigationController.m View File

@@ -0,0 +1,298 @@
1
+#import "RCCNavigationController.h"
2
+#import "RCCViewController.h"
3
+#import "RCCManager.h"
4
+#import "RCTEventDispatcher.h"
5
+#import "RCTConvert.h"
6
+#import <objc/runtime.h>
7
+#import "RCCTitleViewHelper.h"
8
+
9
+@implementation RCCNavigationController
10
+
11
+NSString const *CALLBACK_ASSOCIATED_KEY = @"RCCNavigationController.CALLBACK_ASSOCIATED_KEY";
12
+NSString const *CALLBACK_ASSOCIATED_ID = @"RCCNavigationController.CALLBACK_ASSOCIATED_ID";
13
+
14
+- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary*)globalProps bridge:(RCTBridge *)bridge
15
+{
16
+  NSString *component = props[@"component"];
17
+  if (!component) return nil;
18
+  
19
+  NSDictionary *passProps = props[@"passProps"];
20
+  NSDictionary *navigatorStyle = props[@"style"];
21
+  
22
+  RCCViewController *viewController = [[RCCViewController alloc] initWithComponent:component passProps:passProps navigatorStyle:navigatorStyle globalProps:globalProps bridge:bridge];
23
+  if (!viewController) return nil;
24
+  
25
+  NSArray *leftButtons = props[@"leftButtons"];
26
+  if (leftButtons)
27
+  {
28
+    [self setButtons:leftButtons viewController:viewController side:@"left" animated:NO];
29
+  }
30
+  
31
+  NSArray *rightButtons = props[@"rightButtons"];
32
+  if (rightButtons)
33
+  {
34
+    [self setButtons:rightButtons viewController:viewController side:@"right" animated:NO];
35
+  }
36
+  
37
+  self = [super initWithRootViewController:viewController];
38
+  if (!self) return nil;
39
+  
40
+  self.navigationBar.translucent = NO; // default
41
+  
42
+  [self processTitleView:viewController
43
+                   props:props
44
+                   style:navigatorStyle];
45
+  
46
+  return self;
47
+}
48
+
49
+
50
+- (void)performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams bridge:(RCTBridge *)bridge
51
+{
52
+  BOOL animated = actionParams[@"animated"] ? [actionParams[@"animated"] boolValue] : YES;
53
+  
54
+  // push
55
+  if ([performAction isEqualToString:@"push"])
56
+  {
57
+    NSString *component = actionParams[@"component"];
58
+    if (!component) return;
59
+    
60
+    NSDictionary *passProps = actionParams[@"passProps"];
61
+    NSDictionary *navigatorStyle = actionParams[@"style"];
62
+    
63
+    // merge the navigatorStyle of our parent
64
+    if ([self.topViewController isKindOfClass:[RCCViewController class]])
65
+    {
66
+      RCCViewController *parent = (RCCViewController*)self.topViewController;
67
+      NSMutableDictionary *mergedStyle = [NSMutableDictionary dictionaryWithDictionary:parent.navigatorStyle];
68
+      
69
+      // there are a few styles that we don't want to remember from our parent (they should be local)
70
+      [mergedStyle removeObjectForKey:@"navBarHidden"];
71
+      [mergedStyle removeObjectForKey:@"statusBarHidden"];
72
+      [mergedStyle removeObjectForKey:@"navBarHideOnScroll"];
73
+      [mergedStyle removeObjectForKey:@"drawUnderNavBar"];
74
+      [mergedStyle removeObjectForKey:@"drawUnderTabBar"];
75
+      [mergedStyle removeObjectForKey:@"statusBarBlur"];
76
+      [mergedStyle removeObjectForKey:@"navBarBlur"];
77
+      [mergedStyle removeObjectForKey:@"navBarTranslucent"];
78
+      [mergedStyle removeObjectForKey:@"statusBarHideWithNavBar"];
79
+      
80
+      [mergedStyle addEntriesFromDictionary:navigatorStyle];
81
+      navigatorStyle = mergedStyle;
82
+    }
83
+    
84
+    RCCViewController *viewController = [[RCCViewController alloc] initWithComponent:component passProps:passProps navigatorStyle:navigatorStyle globalProps:nil bridge:bridge];
85
+    
86
+    [self processTitleView:viewController
87
+                     props:actionParams
88
+                     style:navigatorStyle];
89
+    
90
+    NSString *backButtonTitle = actionParams[@"backButtonTitle"];
91
+    if (backButtonTitle)
92
+    {
93
+      UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:backButtonTitle
94
+                                                                   style:UIBarButtonItemStylePlain
95
+                                                                  target:nil
96
+                                                                  action:nil];
97
+      
98
+      self.topViewController.navigationItem.backBarButtonItem = backItem;
99
+    }
100
+    else
101
+    {
102
+      self.topViewController.navigationItem.backBarButtonItem = nil;
103
+    }
104
+    
105
+    NSNumber *backButtonHidden = actionParams[@"backButtonHidden"];
106
+    BOOL backButtonHiddenBool = backButtonHidden ? [backButtonHidden boolValue] : NO;
107
+    if (backButtonHiddenBool)
108
+    {
109
+      viewController.navigationItem.hidesBackButton = YES;
110
+    }
111
+    
112
+    NSArray *leftButtons = actionParams[@"leftButtons"];
113
+    if (leftButtons)
114
+    {
115
+      [self setButtons:leftButtons viewController:viewController side:@"left" animated:NO];
116
+    }
117
+    
118
+    NSArray *rightButtons = actionParams[@"rightButtons"];
119
+    if (rightButtons)
120
+    {
121
+      [self setButtons:rightButtons viewController:viewController side:@"right" animated:NO];
122
+    }
123
+    
124
+    [self pushViewController:viewController animated:animated];
125
+    return;
126
+  }
127
+  
128
+  // pop
129
+  if ([performAction isEqualToString:@"pop"])
130
+  {
131
+    [self popViewControllerAnimated:animated];
132
+    return;
133
+  }
134
+  
135
+  // popToRoot
136
+  if ([performAction isEqualToString:@"popToRoot"])
137
+  {
138
+    [self popToRootViewControllerAnimated:animated];
139
+    return;
140
+  }
141
+  
142
+  // resetTo
143
+  if ([performAction isEqualToString:@"resetTo"])
144
+  {
145
+    NSString *component = actionParams[@"component"];
146
+    if (!component) return;
147
+    
148
+    NSDictionary *passProps = actionParams[@"passProps"];
149
+    NSDictionary *navigatorStyle = actionParams[@"style"];
150
+    
151
+    RCCViewController *viewController = [[RCCViewController alloc] initWithComponent:component passProps:passProps navigatorStyle:navigatorStyle globalProps:nil bridge:bridge];
152
+    
153
+    [self processTitleView:viewController
154
+                     props:actionParams
155
+                     style:navigatorStyle];
156
+    NSArray *leftButtons = actionParams[@"leftButtons"];
157
+    if (leftButtons)
158
+    {
159
+      [self setButtons:leftButtons viewController:viewController side:@"left" animated:NO];
160
+    }
161
+    
162
+    NSArray *rightButtons = actionParams[@"rightButtons"];
163
+    if (rightButtons)
164
+    {
165
+      [self setButtons:rightButtons viewController:viewController side:@"right" animated:NO];
166
+    }
167
+    
168
+    BOOL animated = actionParams[@"animated"] ? [actionParams[@"animated"] boolValue] : YES;
169
+    
170
+    [self setViewControllers:@[viewController] animated:animated];
171
+    return;
172
+  }
173
+  
174
+  // setButtons
175
+  if ([performAction isEqualToString:@"setButtons"])
176
+  {
177
+    NSArray *buttons = actionParams[@"buttons"];
178
+    BOOL animated = actionParams[@"animated"] ? [actionParams[@"animated"] boolValue] : YES;
179
+    NSString *side = actionParams[@"side"] ? actionParams[@"side"] : @"left";
180
+    
181
+    [self setButtons:buttons viewController:self.topViewController side:side animated:animated];
182
+    return;
183
+  }
184
+  
185
+  // setTitle
186
+  if ([performAction isEqualToString:@"setTitle"] || [performAction isEqualToString:@"setTitleImage"])
187
+  {
188
+    NSDictionary *navigatorStyle = actionParams[@"style"];
189
+    [self processTitleView:self.topViewController
190
+                     props:actionParams
191
+                     style:navigatorStyle];
192
+    return;
193
+  }
194
+  
195
+  // toggleNavBar
196
+  if ([performAction isEqualToString:@"setHidden"]) {
197
+    NSNumber *animated = actionParams[@"animated"];
198
+    BOOL animatedBool = animated ? [animated boolValue] : YES;
199
+    
200
+    NSNumber *setHidden = actionParams[@"hidden"];
201
+    BOOL isHiddenBool = setHidden ? [setHidden boolValue] : NO;
202
+    
203
+    RCCViewController *topViewController = ((RCCViewController*)self.topViewController);
204
+    topViewController.navigatorStyle[@"navBarHidden"] = setHidden;
205
+    [topViewController setNavBarVisibilityChange:animatedBool];
206
+    
207
+  }
208
+}
209
+
210
+-(void)onButtonPress:(UIBarButtonItem*)barButtonItem
211
+{
212
+  NSString *callbackId = objc_getAssociatedObject(barButtonItem, &CALLBACK_ASSOCIATED_KEY);
213
+  if (!callbackId) return;
214
+  NSString *buttonId = objc_getAssociatedObject(barButtonItem, &CALLBACK_ASSOCIATED_ID);
215
+  [[[RCCManager sharedInstance] getBridge].eventDispatcher sendAppEventWithName:callbackId body:@
216
+   {
217
+     @"type": @"NavBarButtonPress",
218
+     @"id": buttonId ? buttonId : [NSNull null]
219
+   }];
220
+}
221
+
222
+-(void)setButtons:(NSArray*)buttons viewController:(UIViewController*)viewController side:(NSString*)side animated:(BOOL)animated
223
+{
224
+  NSMutableArray *barButtonItems = [NSMutableArray new];
225
+  for (NSDictionary *button in buttons)
226
+  {
227
+    NSString *title = button[@"title"];
228
+    UIImage *iconImage = nil;
229
+    id icon = button[@"icon"];
230
+    if (icon) iconImage = [RCTConvert UIImage:icon];
231
+    
232
+    UIBarButtonItem *barButtonItem;
233
+    if (iconImage)
234
+    {
235
+      barButtonItem = [[UIBarButtonItem alloc] initWithImage:iconImage style:UIBarButtonItemStylePlain target:self action:@selector(onButtonPress:)];
236
+    }
237
+    else if (title)
238
+    {
239
+      barButtonItem = [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStylePlain target:self action:@selector(onButtonPress:)];
240
+    }
241
+    else continue;
242
+    objc_setAssociatedObject(barButtonItem, &CALLBACK_ASSOCIATED_KEY, button[@"onPress"], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
243
+    [barButtonItems addObject:barButtonItem];
244
+    
245
+    NSString *buttonId = button[@"id"];
246
+    if (buttonId)
247
+    {
248
+      objc_setAssociatedObject(barButtonItem, &CALLBACK_ASSOCIATED_ID, buttonId, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
249
+    }
250
+    
251
+    NSNumber *disabled = button[@"disabled"];
252
+    BOOL disabledBool = disabled ? [disabled boolValue] : NO;
253
+    if (disabledBool) {
254
+      [barButtonItem setEnabled:NO];
255
+    }
256
+    
257
+    NSNumber *disableIconTintString = button[@"disableIconTint"];
258
+    BOOL disableIconTint = disableIconTintString ? [disableIconTintString boolValue] : NO;
259
+    if (disableIconTint) {
260
+      [barButtonItem setImage:[barButtonItem.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
261
+    }
262
+    
263
+    NSString *testID = button[@"testID"];
264
+    if (testID)
265
+    {
266
+      barButtonItem.accessibilityIdentifier = testID;
267
+    }
268
+  }
269
+  
270
+  if ([side isEqualToString:@"left"])
271
+  {
272
+    [viewController.navigationItem setLeftBarButtonItems:barButtonItems animated:animated];
273
+  }
274
+  
275
+  if ([side isEqualToString:@"right"])
276
+  {
277
+    [viewController.navigationItem setRightBarButtonItems:barButtonItems animated:animated];
278
+  }
279
+}
280
+
281
+
282
+-(void)processTitleView:(UIViewController*)viewController
283
+                  props:(NSDictionary*)props
284
+                  style:(NSDictionary*)style
285
+{
286
+  
287
+  RCCTitleViewHelper *titleViewHelper = [[RCCTitleViewHelper alloc] init:viewController
288
+                                                    navigationController:self
289
+                                                                   title:props[@"title"]
290
+                                                                subtitle:props[@"subtitle"]
291
+                                                          titleImageData:props[@"titleImage"]];
292
+  
293
+  [titleViewHelper setup:style];
294
+  
295
+}
296
+
297
+
298
+@end

+ 8
- 0
ios/RCCNotification.h View File

@@ -0,0 +1,8 @@
1
+
2
+#import <Foundation/Foundation.h>
3
+#import "RCCManager.h"
4
+
5
+@interface RCCNotification : NSObject
6
++(void)showWithParams:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
7
++(void)dismissWithParams:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
8
+@end

+ 462
- 0
ios/RCCNotification.m View File

@@ -0,0 +1,462 @@
1
+
2
+#import "RCCNotification.h"
3
+#import "RCTRootView.h"
4
+#import "RCTHelpers.h"
5
+
6
+@interface NotificationView : UIView
7
+@property (nonatomic, strong) RCTRootView *reactView;
8
+@property (nonatomic, strong) UIView *slideAnimGapView;
9
+@property (nonatomic, strong) NSDictionary *params;
10
+@property (nonatomic, strong) NSTimer *autoDismissTimer;
11
+@property (nonatomic)         BOOL yellowBoxRemoved;
12
+@end
13
+
14
+@implementation NotificationView
15
+
16
+-(id)initWithParams:(NSDictionary*)params
17
+{
18
+    self = [super initWithFrame:CGRectZero];
19
+    if (self)
20
+    {
21
+        self.params = params;
22
+        self.yellowBoxRemoved = NO;
23
+        
24
+        self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
25
+        
26
+        self.reactView = [[RCTRootView alloc] initWithBridge:[[RCCManager sharedInstance] getBridge] moduleName:params[@"component"] initialProperties:params[@"passProps"]];
27
+        self.reactView.backgroundColor = [UIColor clearColor];
28
+        self.reactView.sizeFlexibility = RCTRootViewSizeFlexibilityWidthAndHeight;
29
+        self.reactView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
30
+        [self addSubview:self.reactView];
31
+        
32
+        [self.reactView.contentView.layer addObserver:self forKeyPath:@"frame" options:0 context:nil];
33
+        [self.reactView.contentView.layer addObserver:self forKeyPath:@"bounds" options:0 context:NULL];
34
+        
35
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRNReload) name:RCTReloadNotification object:nil];
36
+        
37
+        if ([params[@"dismissWithSwipe"] boolValue])
38
+        {
39
+            UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(performDismiss)];
40
+            swipeGesture.direction = [self swipeDirection];
41
+            [self addGestureRecognizer:swipeGesture];
42
+        }
43
+        
44
+        if (params[@"shadowRadius"] != nil && [params[@"shadowRadius"] floatValue] > 0)
45
+        {
46
+            self.layer.shadowColor = [UIColor blackColor].CGColor;
47
+            self.layer.shadowOffset = CGSizeMake(0, 0);
48
+            self.layer.shadowRadius = [params[@"shadowRadius"] floatValue];
49
+            self.layer.shadowOpacity = 0.6;
50
+        }
51
+        
52
+        self.hidden = YES;
53
+    }
54
+    return self;
55
+}
56
+
57
+-(void)layoutSubviews
58
+{
59
+    [super layoutSubviews];
60
+    
61
+    if(!self.yellowBoxRemoved)
62
+    {
63
+        self.yellowBoxRemoved = [RCTHelpers removeYellowBox:self.reactView];
64
+    }
65
+}
66
+
67
+-(UISwipeGestureRecognizerDirection)swipeDirection
68
+{
69
+    UISwipeGestureRecognizerDirection direction = UISwipeGestureRecognizerDirectionUp;
70
+    
71
+    NSString *animationType = [self.params valueForKeyPath:@"animation.type"];
72
+    if ([animationType isEqualToString:@"swing"] || [animationType isEqualToString:@"slide-down"])
73
+        direction = UISwipeGestureRecognizerDirectionUp;
74
+    else if ([animationType isEqualToString:@"slide-left"])
75
+        direction = UISwipeGestureRecognizerDirectionRight;
76
+    else if ([animationType isEqualToString:@"slide-right"])
77
+        direction = UISwipeGestureRecognizerDirectionLeft;
78
+    
79
+    return direction;
80
+}
81
+
82
+-(void)killAutoDismissTimer
83
+{
84
+    if (self.autoDismissTimer != nil)
85
+    {
86
+        [self.autoDismissTimer invalidate];
87
+        self.autoDismissTimer = nil;
88
+    }
89
+}
90
+
91
+-(void)removeObservers
92
+{
93
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
94
+    [self.reactView.contentView.layer removeObserver:self forKeyPath:@"frame" context:nil];
95
+    [self.reactView.contentView.layer removeObserver:self forKeyPath:@"bounds" context:NULL];
96
+}
97
+
98
+-(void)cleanup
99
+{
100
+    [self removeObservers];
101
+    [self killAutoDismissTimer];
102
+}
103
+
104
+-(void)dealloc
105
+{
106
+    [self cleanup];
107
+}
108
+
109
+-(void)onRNReload
110
+{
111
+    [self cleanup];
112
+    [self removeFromSuperview];
113
+    self.reactView = nil;
114
+}
115
+
116
+-(UIColor*)reactViewAvgColor
117
+{
118
+    if (self.reactView.contentView.frame.size.width == 0 || self.reactView.contentView.frame.size.height == 0)
119
+    {
120
+        return [UIColor clearColor];
121
+    }
122
+    
123
+    UIGraphicsBeginImageContextWithOptions(CGSizeMake(1, 1), YES, 0);
124
+    [self.reactView.contentView drawViewHierarchyInRect:CGRectMake(0, 0, 1, 1) afterScreenUpdates:YES];
125
+    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
126
+    UIGraphicsEndImageContext();
127
+    
128
+    CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
129
+    const UInt8* data = CFDataGetBytePtr(pixelData);
130
+    CFRelease(pixelData);
131
+    
132
+    //after scale defaults to bgr
133
+    CGFloat red = data[2] / 255.0f,
134
+            green = data[1] / 255.0f,
135
+            blue = data[0] / 255.0f,
136
+            alpha = data[3] / 255.0f;
137
+    
138
+    UIColor *color = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
139
+    return color;
140
+}
141
+
142
+-(BOOL)shouldAddSlidingAnimGapView
143
+{
144
+    if (![[self.params valueForKeyPath:@"animation.animated"] boolValue])
145
+    {
146
+        return NO;
147
+    }
148
+    
149
+    NSString *animationType = [self.params valueForKeyPath:@"animation.type"];
150
+    if (![animationType isEqualToString:@"slide-down"])
151
+    {
152
+        return NO;
153
+    }
154
+    
155
+    if (![self.params valueForKeyPath:@"animation.damping"])
156
+    {
157
+        return NO;
158
+    }
159
+    
160
+    CGFloat damping = [[self.params valueForKeyPath:@"animation.damping"] floatValue];
161
+    if (damping >= 1)
162
+    {
163
+        return NO;
164
+    }
165
+    
166
+    return YES;
167
+}
168
+
169
+-(BOOL)isBottomPosition
170
+{
171
+    return ((self.params[@"position"] != nil) && ([self.params[@"position"] isEqualToString:@"bottom"]));
172
+}
173
+
174
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
175
+{
176
+    CGSize frameSize = CGSizeZero;
177
+    if ([object isKindOfClass:[CALayer class]])
178
+        frameSize = ((CALayer*)object).frame.size;
179
+    if ([object isKindOfClass:[UIView class]])
180
+        frameSize = ((UIView*)object).frame.size;
181
+    
182
+    if (!CGSizeEqualToSize(frameSize, self.reactView.frame.size))
183
+    {
184
+        BOOL isBottomPosition = [self isBottomPosition];
185
+        CGFloat yPos = isBottomPosition ? self.superview.bounds.size.height - frameSize.height : 0;
186
+        self.frame = CGRectMake((self.superview.frame.size.width - frameSize.width) / 2.0, yPos, frameSize.width, frameSize.height);
187
+        self.reactView.frame = CGRectMake(0, 0, frameSize.width, frameSize.height);
188
+        self.reactView.contentView.frame = CGRectMake(0, 0, frameSize.width, frameSize.height);
189
+    
190
+        //if necessary, add a view with the same color to cover the gap if there's a slide animation with spring
191
+        if ([self shouldAddSlidingAnimGapView])
192
+        {
193
+            if (self.slideAnimGapView == nil)
194
+            {
195
+                self.slideAnimGapView = [[UIView alloc] initWithFrame:CGRectZero];
196
+                [self.reactView addSubview:self.slideAnimGapView];
197
+            }
198
+            
199
+            CGFloat yPos = isBottomPosition ? frameSize.height : -20;
200
+            self.slideAnimGapView.frame = CGRectMake(0, yPos, self.superview.frame.size.width, 20);
201
+            
202
+            dispatch_async(dispatch_get_main_queue(), ^
203
+            {
204
+               self.slideAnimGapView.backgroundColor = [self reactViewAvgColor];
205
+            });
206
+        }
207
+        
208
+        if (self.params[@"shadowRadius"] != nil && [self.params[@"shadowRadius"] floatValue] > 0)
209
+        {
210
+            self.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
211
+        }
212
+    }
213
+}
214
+
215
+-(void)performDismiss
216
+{
217
+    [RCCNotification dismissWithParams:self.params resolver:nil rejecter:nil];
218
+}
219
+
220
+-(void)startAutoDismissTimerIfNecessary
221
+{
222
+    if (self.params[@"autoDismissTimerSec"])
223
+    {
224
+        [self killAutoDismissTimer];
225
+        
226
+        CGFloat interval = [self.params[@"autoDismissTimerSec"] floatValue];
227
+        interval = MAX(interval, 1);
228
+        self.autoDismissTimer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(performDismiss) userInfo:nil repeats:NO];
229
+    }
230
+}
231
+
232
+-(void)applyAnimations
233
+{
234
+    NSString *animationType = [self.params valueForKeyPath:@"animation.type"];
235
+    if ([animationType isEqualToString:@"swing"])
236
+    {
237
+        CATransform3D transform = CATransform3DIdentity;
238
+        transform.m34 = -0.002f;
239
+        transform.m24 = -0.007f;
240
+        if (self.layer.anchorPoint.x == 0.5 && self.layer.anchorPoint.y == 0.5)
241
+        {
242
+            CGPoint anchorPoint = CGPointMake(0.5, 0);
243
+            CGFloat yOffset = -self.layer.frame.size.height / 2.0;
244
+            if([self isBottomPosition])
245
+            {
246
+                anchorPoint = CGPointMake(0.5, 1);
247
+                yOffset = self.layer.frame.size.height / 2.0;
248
+            }
249
+            
250
+            self.layer.anchorPoint = anchorPoint;
251
+            self.layer.frame = CGRectOffset(self.layer.frame, 0, yOffset);
252
+        }
253
+        self.layer.zPosition = 1000;
254
+        self.layer.transform = CATransform3DRotate(transform, M_PI_2, 1, 0, 0);
255
+    }
256
+    else
257
+    {
258
+        int slideAnimationSign = [self isBottomPosition] ? 1 : -1;
259
+        CGAffineTransform transform = CGAffineTransformIdentity;
260
+        if ([animationType isEqualToString:@"slide-down"])
261
+            transform = CGAffineTransformMakeTranslation(0, slideAnimationSign * self.frame.size.height);
262
+        else if ([animationType isEqualToString:@"slide-left"])
263
+            transform = CGAffineTransformMakeTranslation(self.frame.size.width, 0);
264
+        else if ([animationType isEqualToString:@"slide-right"])
265
+            transform = CGAffineTransformMakeTranslation(-self.frame.size.width, 0);
266
+        
267
+        self.transform = transform;
268
+    }
269
+    
270
+    if ( [[self.params valueForKeyPath:@"animation.fade"] boolValue])
271
+    {
272
+        self.alpha = 0;
273
+    }
274
+}
275
+
276
+#pragma mark - show/dismiss
277
+
278
+-(void)showAnimationEnded:(void (^)(void))completion
279
+{
280
+    self.alpha = 1;
281
+    
282
+    if (completion)
283
+    {
284
+        completion();
285
+    }
286
+    
287
+    [self startAutoDismissTimerIfNecessary];
288
+}
289
+
290
+-(void)dismissAnimationEnded:(void (^)(void))completion
291
+{
292
+    if (completion)
293
+    {
294
+        completion();
295
+    }
296
+    
297
+    [self removeFromSuperview];
298
+}
299
+
300
+-(void)performShowWithCompletion:(void (^)(void))completion
301
+{
302
+    self.hidden = NO;
303
+    
304
+    if ([[self.params valueForKeyPath:@"animation.animated"] boolValue])
305
+    {
306
+        CGFloat duration = [[self.params valueForKeyPath:@"animation.duration"] floatValue];
307
+        CGFloat delay = [[self.params valueForKeyPath:@"animation.delay"] floatValue];
308
+        
309
+        CGFloat damping = 1;
310
+        if ([self.params valueForKeyPath:@"animation.damping"] != nil)
311
+        {
312
+            damping = [[self.params valueForKeyPath:@"animation.damping"] floatValue];
313
+            damping = MAX(damping, 0);
314
+            damping = MIN(damping, 1);
315
+        }
316
+        
317
+        [self applyAnimations];
318
+        
319
+        [UIView animateWithDuration:duration delay:delay usingSpringWithDamping:damping initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseOut animations:^()
320
+         {
321
+             self.alpha = 1;
322
+             self.transform = CGAffineTransformIdentity;
323
+             self.layer.transform = CATransform3DIdentity;
324
+         }
325
+                         completion:^(BOOL finished)
326
+         {
327
+             [self showAnimationEnded:completion];
328
+         }];
329
+    }
330
+    else
331
+    {
332
+        [self showAnimationEnded:completion];
333
+    }
334
+}
335
+
336
+-(void)showWithCompletion:(void (^)(void))completion
337
+{
338
+    if (self.frame.size.height == 0 || self.frame.size.width == 0)
339
+    {
340
+        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)),
341
+                       dispatch_get_main_queue(),
342
+                       ^{
343
+                           [self showWithCompletion:completion];
344
+                       });
345
+    }
346
+    else
347
+    {
348
+        [self performShowWithCompletion:completion];
349
+    }
350
+}
351
+
352
+-(void)dismissWithCompletion:(void (^)(void))completion
353
+{
354
+    [self killAutoDismissTimer];
355
+    [self.reactView cancelTouches];
356
+    
357
+    if ([[self.params valueForKeyPath:@"animation.animated"] boolValue])
358
+    {
359
+        CGFloat duration = [[self.params valueForKeyPath:@"animation.duration"] floatValue] * 0.75;
360
+        [UIView animateWithDuration:duration delay:0 usingSpringWithDamping:1 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseIn
361
+                         animations:^()
362
+         {
363
+             [self applyAnimations];
364
+         }
365
+                         completion:^(BOOL finished)
366
+         {
367
+             [self dismissAnimationEnded:completion];
368
+         }];
369
+    }
370
+    else
371
+    {
372
+        [self dismissAnimationEnded:completion];
373
+    }
374
+}
375
+
376
+@end
377
+
378
+@interface PendingNotification : NSObject
379
+@property (nonatomic, copy) void (^resolve)(id result);
380
+@property (nonatomic, copy) void (^reject)(NSString *code, NSString *message, NSError *error);
381
+@property (nonatomic, strong) NSDictionary *params;
382
+@end
383
+
384
+@implementation PendingNotification
385
+@end
386
+
387
+@implementation RCCNotification
388
+
389
+static NSTimeInterval gLastShownTime = NSTimeIntervalSince1970;
390
+static NSMutableArray *gPendingNotifications = nil;
391
+static NSMutableArray *gShownNotificationViews = nil;
392
+
393
++(void)showWithParams:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject
394
+{
395
+    if(gPendingNotifications == nil)
396
+        gPendingNotifications = [NSMutableArray array];
397
+    
398
+    if(gShownNotificationViews == nil)
399
+        gShownNotificationViews = [NSMutableArray array];
400
+    
401
+    if ([gShownNotificationViews count] > 0)
402
+    {
403
+        for (NotificationView *notificationView in gShownNotificationViews)
404
+        {
405
+            [notificationView killAutoDismissTimer];
406
+        }
407
+        
408
+        //limit the amount of consecutive notifications per second. If they arrive too fast, the last one will be remembered as pending
409
+        if(CFAbsoluteTimeGetCurrent() - gLastShownTime < 1)
410
+        {
411
+            PendingNotification *pendingNotification = [PendingNotification new];
412
+            pendingNotification.params = params;
413
+            pendingNotification.resolve = resolve;
414
+            pendingNotification.reject = reject;
415
+            [gPendingNotifications addObject:pendingNotification];
416
+            return;
417
+        }
418
+    }
419
+    
420
+    gLastShownTime = CFAbsoluteTimeGetCurrent();
421
+    
422
+    UIWindow *window = [[RCCManager sharedInstance] getAppWindow];
423
+    NotificationView *notificationView = [[NotificationView alloc] initWithParams:params];
424
+    [window addSubview:notificationView];
425
+    [gShownNotificationViews addObject:notificationView];
426
+    [notificationView showWithCompletion:^()
427
+     {
428
+         if (resolve)
429
+         {
430
+             resolve(nil);
431
+         }
432
+     }];
433
+}
434
+
435
++(void)dismissWithParams:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject
436
+{
437
+    int count = [gShownNotificationViews count];
438
+    for (int i = count - 1 ; i >= 0; i--)
439
+    {
440
+        NotificationView *notificationView = [gShownNotificationViews objectAtIndex:i];
441
+        [gShownNotificationViews removeObject:notificationView];
442
+        [notificationView dismissWithCompletion:^()
443
+         {
444
+             if (i == (count - 1))
445
+             {
446
+                 if(resolve)
447
+                 {
448
+                     resolve(nil);
449
+                 }
450
+                 
451
+                 if ([gPendingNotifications count] > 0)
452
+                 {
453
+                     PendingNotification *pendingNotification = [gPendingNotifications lastObject];
454
+                     [self showWithParams:pendingNotification.params resolver:pendingNotification.resolve rejecter:pendingNotification.reject];
455
+                     [gPendingNotifications removeLastObject];
456
+                 }
457
+             }
458
+         }];
459
+    }
460
+}
461
+
462
+@end

+ 9
- 0
ios/RCCTabBarController.h View File

@@ -0,0 +1,9 @@
1
+#import <UIKit/UIKit.h>
2
+#import "RCTBridge.h"
3
+
4
+@interface RCCTabBarController : UITabBarController
5
+
6
+- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary*)globalProps bridge:(RCTBridge *)bridge;
7
+- (void)performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams bridge:(RCTBridge *)bridge completion:(void (^)(void))completion;
8
+
9
+@end

+ 220
- 0
ios/RCCTabBarController.m View File

@@ -0,0 +1,220 @@
1
+#import "RCCTabBarController.h"
2
+#import "RCCViewController.h"
3
+#import "RCTConvert.h"
4
+#import "RCCManager.h"
5
+
6
+@implementation RCCTabBarController
7
+
8
+- (UIImage *)image:(UIImage*)image withColor:(UIColor *)color1
9
+{
10
+  UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
11
+  CGContextRef context = UIGraphicsGetCurrentContext();
12
+  CGContextTranslateCTM(context, 0, image.size.height);
13
+  CGContextScaleCTM(context, 1.0, -1.0);
14
+  CGContextSetBlendMode(context, kCGBlendModeNormal);
15
+  CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
16
+  CGContextClipToMask(context, rect, image.CGImage);
17
+  [color1 setFill];
18
+  CGContextFillRect(context, rect);
19
+  UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
20
+  UIGraphicsEndImageContext();
21
+  return newImage;
22
+}
23
+
24
+- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary*)globalProps bridge:(RCTBridge *)bridge
25
+{
26
+  self = [super init];
27
+  if (!self) return nil;
28
+  
29
+  self.tabBar.translucent = YES; // default
30
+  
31
+  UIColor *buttonColor = nil;
32
+  UIColor *selectedButtonColor = nil;
33
+  NSDictionary *tabsStyle = props[@"style"];
34
+  if (tabsStyle)
35
+  {
36
+    NSString *tabBarButtonColor = tabsStyle[@"tabBarButtonColor"];
37
+    if (tabBarButtonColor)
38
+    {
39
+      UIColor *color = tabBarButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarButtonColor] : nil;
40
+      self.tabBar.tintColor = color;
41
+      buttonColor = color;
42
+      selectedButtonColor = color;
43
+    }
44
+    
45
+    NSString *tabBarSelectedButtonColor = tabsStyle[@"tabBarSelectedButtonColor"];
46
+    if (tabBarSelectedButtonColor)
47
+    {
48
+      UIColor *color = tabBarSelectedButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarSelectedButtonColor] : nil;
49
+      self.tabBar.tintColor = color;
50
+      selectedButtonColor = color;
51
+    }
52
+    
53
+    NSString *tabBarBackgroundColor = tabsStyle[@"tabBarBackgroundColor"];
54
+    if (tabBarBackgroundColor)
55
+    {
56
+      UIColor *color = tabBarBackgroundColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarBackgroundColor] : nil;
57
+      self.tabBar.barTintColor = color;
58
+    }
59
+  }
60
+
61
+  NSMutableArray *viewControllers = [NSMutableArray array];
62
+
63
+  // go over all the tab bar items
64
+  for (NSDictionary *tabItemLayout in children)
65
+  {
66
+    // make sure the layout is valid
67
+    if (![tabItemLayout[@"type"] isEqualToString:@"TabBarControllerIOS.Item"]) continue;
68
+    if (!tabItemLayout[@"props"]) continue;
69
+
70
+    // get the view controller inside
71
+    if (!tabItemLayout[@"children"]) continue;
72
+    if (![tabItemLayout[@"children"] isKindOfClass:[NSArray class]]) continue;
73
+    if ([tabItemLayout[@"children"] count] < 1) continue;
74
+    NSDictionary *childLayout = tabItemLayout[@"children"][0];
75
+    UIViewController *viewController = [RCCViewController controllerWithLayout:childLayout globalProps:globalProps bridge:bridge];
76
+    if (!viewController) continue;
77
+
78
+    // create the tab icon and title
79
+    NSString *title = tabItemLayout[@"props"][@"title"];
80
+    UIImage *iconImage = nil;
81
+    id icon = tabItemLayout[@"props"][@"icon"];
82
+    if (icon)
83
+    {
84
+      iconImage = [RCTConvert UIImage:icon];
85
+      if (buttonColor)
86
+      {
87
+        iconImage = [[self image:iconImage withColor:buttonColor] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
88
+      }
89
+    }
90
+    UIImage *iconImageSelected = nil;
91
+    id selectedIcon = tabItemLayout[@"props"][@"selectedIcon"];
92
+    if (selectedIcon) iconImageSelected = [RCTConvert UIImage:selectedIcon];
93
+
94
+    viewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:title image:iconImage tag:0];
95
+    viewController.tabBarItem.accessibilityIdentifier = tabItemLayout[@"props"][@"testID"];
96
+    viewController.tabBarItem.selectedImage = iconImageSelected;
97
+    
98
+    if (buttonColor)
99
+    {
100
+      [viewController.tabBarItem setTitleTextAttributes:
101
+       @{NSForegroundColorAttributeName : buttonColor} forState:UIControlStateNormal];
102
+    }
103
+    
104
+    if (selectedButtonColor)
105
+    {
106
+      [viewController.tabBarItem setTitleTextAttributes:
107
+       @{NSForegroundColorAttributeName : selectedButtonColor} forState:UIControlStateSelected];
108
+    }
109
+    
110
+    // create badge
111
+    NSObject *badge = tabItemLayout[@"props"][@"badge"];
112
+    if (badge == nil || [badge isEqual:[NSNull null]])
113
+    {
114
+      viewController.tabBarItem.badgeValue = nil;
115
+    }
116
+    else
117
+    {
118
+      viewController.tabBarItem.badgeValue = [NSString stringWithFormat:@"%@", badge];
119
+    }
120
+
121
+    [viewControllers addObject:viewController];
122
+  }
123
+
124
+  // replace the tabs
125
+  self.viewControllers = viewControllers;
126
+
127
+  return self;
128
+}
129
+
130
+- (void)performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams bridge:(RCTBridge *)bridge completion:(void (^)(void))completion
131
+{
132
+    if ([performAction isEqualToString:@"setBadge"])
133
+    {
134
+      UIViewController *viewController = nil;
135
+      NSNumber *tabIndex = actionParams[@"tabIndex"];
136
+      if (tabIndex)
137
+      {
138
+        int i = (int)[tabIndex integerValue];
139
+      
140
+        if ([self.viewControllers count] > i)
141
+        {
142
+          viewController = [self.viewControllers objectAtIndex:i];
143
+        }
144
+      }
145
+      NSString *contentId = actionParams[@"contentId"];
146
+      NSString *contentType = actionParams[@"contentType"];
147
+      if (contentId && contentType)
148
+      {
149
+        viewController = [[RCCManager sharedInstance] getControllerWithId:contentId componentType:contentType];
150
+      }
151
+      
152
+      if (viewController)
153
+      {
154
+        NSObject *badge = actionParams[@"badge"];
155
+        
156
+        if (badge == nil || [badge isEqual:[NSNull null]])
157
+        {
158
+          viewController.tabBarItem.badgeValue = nil;
159
+        }
160
+        else
161
+        {
162
+          viewController.tabBarItem.badgeValue = [NSString stringWithFormat:@"%@", badge];
163
+        }
164
+      }
165
+    }
166
+  
167
+    if ([performAction isEqualToString:@"switchTo"])
168
+    {
169
+      UIViewController *viewController = nil;
170
+      NSNumber *tabIndex = actionParams[@"tabIndex"];
171
+      if (tabIndex)
172
+      {
173
+        int i = (int)[tabIndex integerValue];
174
+      
175
+        if ([self.viewControllers count] > i)
176
+        {
177
+          viewController = [self.viewControllers objectAtIndex:i];
178
+        }
179
+      }
180
+      NSString *contentId = actionParams[@"contentId"];
181
+      NSString *contentType = actionParams[@"contentType"];
182
+      if (contentId && contentType)
183
+      {
184
+        viewController = [[RCCManager sharedInstance] getControllerWithId:contentId componentType:contentType];
185
+      }
186
+    
187
+      if (viewController)
188
+      {
189
+        [self setSelectedViewController:viewController];
190
+      }
191
+    }
192
+
193
+    if ([performAction isEqualToString:@"setTabBarHidden"])
194
+    {
195
+        BOOL hidden = [actionParams[@"hidden"] boolValue];
196
+        [UIView animateWithDuration: ([actionParams[@"animated"] boolValue] ? 0.45 : 0)
197
+                              delay: 0
198
+             usingSpringWithDamping: 0.75
199
+              initialSpringVelocity: 0
200
+                            options: (hidden ? UIViewAnimationOptionCurveEaseIn : UIViewAnimationOptionCurveEaseOut)
201
+                         animations:^()
202
+         {
203
+             self.tabBar.transform = hidden ? CGAffineTransformMakeTranslation(0, self.tabBar.frame.size.height) : CGAffineTransformIdentity;
204
+         }
205
+                         completion:^(BOOL finished)
206
+        {
207
+            if (completion != nil)
208
+            {
209
+                completion();
210
+            }
211
+        }];
212
+        return;
213
+    }
214
+    else if (completion != nil)
215
+    {
216
+      completion();
217
+    }
218
+}
219
+
220
+@end

+ 14
- 0
ios/RCCToolBar/RCCToolBar.h View File

@@ -0,0 +1,14 @@
1
+//
2
+//  RCCToolBar.h
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Ran Greenberg on 09/05/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import <UIKit/UIKit.h>
10
+#import "RCTViewManager.h"
11
+
12
+@interface RCCToolBar : RCTViewManager
13
+
14
+@end

+ 57
- 0
ios/RCCToolBar/RCCToolBar.m View File

@@ -0,0 +1,57 @@
1
+//
2
+//  RCCToolBar.m
3
+//  ReactNativeControllers
4
+//
5
+//  Created by Ran Greenberg on 09/05/2016.
6
+//  Copyright © 2016 artal. All rights reserved.
7
+//
8
+
9
+#import "RCCToolBar.h"
10
+
11
+@interface RCCToolBarView : UIToolbar
12
+
13
+@property (nonatomic) BOOL toolBarTranslucent;
14
+
15
+@end
16
+
17
+
18
+@implementation RCCToolBarView
19
+
20
+-(instancetype)init
21
+{
22
+    self = [super init];
23
+    if (self)
24
+    {
25
+        self.toolBarTranslucent = self.translucent;
26
+    }
27
+    return self;
28
+}
29
+
30
+
31
+-(void)didMoveToWindow
32
+{
33
+    [super didMoveToWindow];
34
+    self.translucent = self.toolBarTranslucent;
35
+}
36
+
37
+@end
38
+
39
+
40
+@implementation RCCToolBar
41
+
42
+
43
+RCT_EXPORT_MODULE()
44
+
45
+- (UIView *)view
46
+{
47
+    return [[RCCToolBarView alloc] init];
48
+}
49
+
50
+
51
+RCT_CUSTOM_VIEW_PROPERTY(translucent, BOOL, RCCToolBarView)
52
+{
53
+    view.toolBarTranslucent = [RCTConvert BOOL:json];
54
+}
55
+
56
+
57
+@end

+ 23
- 0
ios/RCCViewController.h View File

@@ -0,0 +1,23 @@
1
+#import <UIKit/UIKit.h>
2
+#import "RCTBridge.h"
3
+
4
+extern NSString* const RCCViewControllerCancelReactTouchesNotification;
5
+
6
+@interface RCCViewController : UIViewController
7
+
8
+@property (nonatomic) NSMutableDictionary *navigatorStyle;
9
+@property (nonatomic) BOOL navBarHidden;
10
+
11
++ (UIViewController*)controllerWithLayout:(NSDictionary *)layout globalProps:(NSDictionary *)globalProps bridge:(RCTBridge *)bridge;
12
+
13
+- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary *)globalProps bridge:(RCTBridge *)bridge;
14
+- (instancetype)initWithComponent:(NSString *)component passProps:(NSDictionary *)passProps navigatorStyle:(NSDictionary*)navigatorStyle globalProps:(NSDictionary *)globalProps bridge:(RCTBridge *)bridge;
15
+- (void)setStyleOnAppear;
16
+- (void)setStyleOnInit;
17
+- (void)setNavBarVisibilityChange:(BOOL)animated;
18
+
19
+@end
20
+
21
+@protocol RCCViewControllerDelegate <NSObject>
22
+-(void)setStyleOnAppearForViewController:(UIViewController*)viewController;
23
+@end

+ 559
- 0
ios/RCCViewController.m View File

@@ -0,0 +1,559 @@
1
+#import "RCCViewController.h"
2
+#import "RCCNavigationController.h"
3
+#import "RCCTabBarController.h"
4
+#import "RCCDrawerController.h"
5
+#import "RCCTheSideBarManagerViewController.h"
6
+#import "RCTRootView.h"
7
+#import "RCCManager.h"
8
+#import "RCTConvert.h"
9
+#import "RCCExternalViewControllerProtocol.h"
10
+
11
+NSString* const RCCViewControllerCancelReactTouchesNotification = @"RCCViewControllerCancelReactTouchesNotification";
12
+
13
+const NSInteger BLUR_STATUS_TAG = 78264801;
14
+const NSInteger BLUR_NAVBAR_TAG = 78264802;
15
+const NSInteger TRANSPARENT_NAVBAR_TAG = 78264803;
16
+
17
+@interface RCCViewController() <UIGestureRecognizerDelegate>
18
+@property (nonatomic) BOOL _hidesBottomBarWhenPushed;
19
+@property (nonatomic) BOOL _statusBarHideWithNavBar;
20
+@property (nonatomic) BOOL _statusBarHidden;
21
+@property (nonatomic) BOOL _statusBarTextColorSchemeLight;
22
+@property (nonatomic, strong) NSDictionary *originalNavBarImages;
23
+@property (nonatomic, strong) UIImageView *navBarHairlineImageView;
24
+@property (nonatomic, weak) id <UIGestureRecognizerDelegate> originalInteractivePopGestureDelegate;
25
+@end
26
+
27
+@implementation RCCViewController
28
+
29
+-(UIImageView *)navBarHairlineImageView {
30
+    if (!_navBarHairlineImageView) {
31
+        _navBarHairlineImageView = [self findHairlineImageViewUnder:self.navigationController.navigationBar];
32
+    }
33
+    return _navBarHairlineImageView;
34
+}
35
+
36
++ (UIViewController*)controllerWithLayout:(NSDictionary *)layout globalProps:(NSDictionary *)globalProps bridge:(RCTBridge *)bridge
37
+{
38
+    UIViewController* controller = nil;
39
+    if (!layout) return nil;
40
+    
41
+    // get props
42
+    if (!layout[@"props"]) return nil;
43
+    if (![layout[@"props"] isKindOfClass:[NSDictionary class]]) return nil;
44
+    NSDictionary *props = layout[@"props"];
45
+    
46
+    // get children
47
+    if (!layout[@"children"]) return nil;
48
+    if (![layout[@"children"] isKindOfClass:[NSArray class]]) return nil;
49
+    NSArray *children = layout[@"children"];
50
+    
51
+    // create according to type
52
+    NSString *type = layout[@"type"];
53
+    if (!type) return nil;
54
+    
55
+    // regular view controller
56
+    if ([type isEqualToString:@"ViewControllerIOS"])
57
+    {
58
+        controller = [[RCCViewController alloc] initWithProps:props children:children globalProps:globalProps bridge:bridge];
59
+    }
60
+    
61
+    // navigation controller
62
+    if ([type isEqualToString:@"NavigationControllerIOS"])
63
+    {
64
+        controller = [[RCCNavigationController alloc] initWithProps:props children:children globalProps:globalProps bridge:bridge];
65
+    }
66
+    
67
+    // tab bar controller
68
+    if ([type isEqualToString:@"TabBarControllerIOS"])
69
+    {
70
+        controller = [[RCCTabBarController alloc] initWithProps:props children:children globalProps:globalProps bridge:bridge];
71
+    }
72
+    
73
+    // side menu controller
74
+    if ([type isEqualToString:@"DrawerControllerIOS"])
75
+    {
76
+        NSString *drawerType = props[@"type"];
77
+        
78
+        if ([drawerType isEqualToString:@"TheSideBar"]) {
79
+            
80
+            controller = [[RCCTheSideBarManagerViewController alloc] initWithProps:props children:children globalProps:globalProps bridge:bridge];
81
+        }
82
+        else {
83
+            controller = [[RCCDrawerController alloc] initWithProps:props children:children globalProps:globalProps bridge:bridge];
84
+        }
85
+    }
86
+    
87
+    // register the controller if we have an id
88
+    NSString *componentId = props[@"id"];
89
+    if (controller && componentId)
90
+    {
91
+        [[RCCManager sharedInstance] registerController:controller componentId:componentId componentType:type];
92
+    }
93
+    
94
+    return controller;
95
+}
96
+
97
+- (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary *)globalProps bridge:(RCTBridge *)bridge
98
+{
99
+  NSString *component = props[@"component"];
100
+  if (!component) return nil;
101
+
102
+  NSDictionary *passProps = props[@"passProps"];
103
+  NSDictionary *navigatorStyle = props[@"style"];
104
+
105
+  NSMutableDictionary *mergedProps = [NSMutableDictionary dictionaryWithDictionary:globalProps];
106
+  [mergedProps addEntriesFromDictionary:passProps];
107
+  
108
+  RCTRootView *reactView = [[RCTRootView alloc] initWithBridge:bridge moduleName:component initialProperties:mergedProps];
109
+  if (!reactView) return nil;
110
+
111
+  self = [super init];
112
+  if (!self) return nil;
113
+
114
+  [self commonInit:reactView navigatorStyle:navigatorStyle props:props];
115
+
116
+  return self;
117
+}
118
+
119
+- (instancetype)initWithComponent:(NSString *)component passProps:(NSDictionary *)passProps navigatorStyle:(NSDictionary*)navigatorStyle globalProps:(NSDictionary *)globalProps bridge:(RCTBridge *)bridge
120
+{
121
+  NSMutableDictionary *mergedProps = [NSMutableDictionary dictionaryWithDictionary:globalProps];
122
+  [mergedProps addEntriesFromDictionary:passProps];
123
+  
124
+  RCTRootView *reactView = [[RCTRootView alloc] initWithBridge:bridge moduleName:component initialProperties:mergedProps];
125
+  if (!reactView) return nil;
126
+
127
+  self = [super init];
128
+  if (!self) return nil;
129
+
130
+  [self commonInit:reactView navigatorStyle:navigatorStyle props:passProps];
131
+
132
+  return self;
133
+}
134
+
135
+- (void)commonInit:(RCTRootView*)reactView navigatorStyle:(NSDictionary*)navigatorStyle props:(NSDictionary*)props
136
+{
137
+  self.view = reactView;
138
+  
139
+  self.edgesForExtendedLayout = UIRectEdgeNone; // default
140
+  self.automaticallyAdjustsScrollViewInsets = NO; // default
141
+  
142
+  self.navigatorStyle = [NSMutableDictionary dictionaryWithDictionary:navigatorStyle];
143
+  
144
+  [self setStyleOnInit];
145
+  
146
+  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onRNReload) name:RCTReloadNotification object:nil];
147
+  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onCancelReactTouches) name:RCCViewControllerCancelReactTouchesNotification object:nil];
148
+  
149
+  // In order to support 3rd party native ViewControllers, we support passing a class name as a prop mamed `ExternalNativeScreenClass`
150
+  // In this case, we create an instance and add it as a child ViewController which preserves the VC lifecycle.
151
+  // In case some props are necessary in the native ViewController, the ExternalNativeScreenProps can be used to pass them
152
+  [self addExternalVCIfNecessary:props];
153
+}
154
+
155
+- (void)dealloc
156
+{
157
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
158
+    self.view = nil;
159
+}
160
+
161
+-(void)onRNReload
162
+{
163
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
164
+    self.view = nil;
165
+}
166
+
167
+-(void)onCancelReactTouches
168
+{
169
+  if ([self.view isKindOfClass:[RCTRootView class]]){
170
+    [(RCTRootView*)self.view cancelTouches];
171
+  }
172
+}
173
+
174
+- (void)viewWillAppear:(BOOL)animated
175
+{
176
+    [super viewWillAppear:animated];
177
+    
178
+    [self setStyleOnAppear];
179
+}
180
+
181
+- (void)viewWillDisappear:(BOOL)animated
182
+{
183
+    [super viewWillDisappear:animated];
184
+    
185
+    [self setStyleOnDisappear];
186
+}
187
+
188
+// most styles should be set here since when we pop a view controller that changed them
189
+// we want to reset the style to what we expect (so we need to reset on every willAppear)
190
+- (void)setStyleOnAppear
191
+{
192
+  [self setStyleOnAppearForViewController:self];
193
+}
194
+
195
+-(void)setStyleOnAppearForViewController:(UIViewController*)viewController
196
+{
197
+    NSString *navBarBackgroundColor = self.navigatorStyle[@"navBarBackgroundColor"];
198
+    if (navBarBackgroundColor)
199
+    {
200
+        UIColor *color = navBarBackgroundColor != (id)[NSNull null] ? [RCTConvert UIColor:navBarBackgroundColor] : nil;
201
+        viewController.navigationController.navigationBar.barTintColor = color;
202
+    }
203
+    else
204
+    {
205
+        viewController.navigationController.navigationBar.barTintColor = nil;
206
+    }
207
+    
208
+    NSString *navBarTextColor = self.navigatorStyle[@"navBarTextColor"];
209
+    if (navBarTextColor)
210
+    {
211
+        UIColor *color = navBarTextColor != (id)[NSNull null] ? [RCTConvert UIColor:navBarTextColor] : nil;
212
+        [viewController.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : color}];
213
+    }
214
+    else
215
+    {
216
+        [viewController.navigationController.navigationBar setTitleTextAttributes:nil];
217
+    }
218
+    
219
+    NSString *navBarButtonColor = self.navigatorStyle[@"navBarButtonColor"];
220
+    if (navBarButtonColor)
221
+    {
222
+        UIColor *color = navBarButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:navBarButtonColor] : nil;
223
+        viewController.navigationController.navigationBar.tintColor = color;
224
+    }
225
+    else
226
+    {
227
+        viewController.navigationController.navigationBar.tintColor = nil;
228
+    }
229
+    
230
+    NSString *statusBarTextColorScheme = self.navigatorStyle[@"statusBarTextColorScheme"];
231
+    if (statusBarTextColorScheme && [statusBarTextColorScheme isEqualToString:@"light"])
232
+    {
233
+        viewController.navigationController.navigationBar.barStyle = UIBarStyleBlack;
234
+        self._statusBarTextColorSchemeLight = YES;
235
+    }
236
+    else
237
+    {
238
+        viewController.navigationController.navigationBar.barStyle = UIBarStyleDefault;
239
+        self._statusBarTextColorSchemeLight = NO;
240
+    }
241
+    
242
+    NSNumber *navBarHidden = self.navigatorStyle[@"navBarHidden"];
243
+    BOOL navBarHiddenBool = navBarHidden ? [navBarHidden boolValue] : NO;
244
+    if (viewController.navigationController.navigationBarHidden != navBarHiddenBool)
245
+    {
246
+        [viewController.navigationController setNavigationBarHidden:navBarHiddenBool animated:YES];
247
+    }
248
+    
249
+    NSNumber *navBarHideOnScroll = self.navigatorStyle[@"navBarHideOnScroll"];
250
+    BOOL navBarHideOnScrollBool = navBarHideOnScroll ? [navBarHideOnScroll boolValue] : NO;
251
+    if (navBarHideOnScrollBool)
252
+    {
253
+        viewController.navigationController.hidesBarsOnSwipe = YES;
254
+    }
255
+    else
256
+    {
257
+        viewController.navigationController.hidesBarsOnSwipe = NO;
258
+    }
259
+    
260
+    NSNumber *statusBarBlur = self.navigatorStyle[@"statusBarBlur"];
261
+    BOOL statusBarBlurBool = statusBarBlur ? [statusBarBlur boolValue] : NO;
262
+    if (statusBarBlurBool)
263
+    {
264
+        if (![viewController.view viewWithTag:BLUR_STATUS_TAG])
265
+        {
266
+            UIVisualEffectView *blur = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
267
+            blur.frame = [[UIApplication sharedApplication] statusBarFrame];
268
+            blur.tag = BLUR_STATUS_TAG;
269
+            [viewController.view addSubview:blur];
270
+        }
271
+    }
272
+    
273
+    NSNumber *navBarBlur = self.navigatorStyle[@"navBarBlur"];
274
+    BOOL navBarBlurBool = navBarBlur ? [navBarBlur boolValue] : NO;
275
+    if (navBarBlurBool)
276
+    {
277
+        if (![viewController.navigationController.navigationBar viewWithTag:BLUR_NAVBAR_TAG])
278
+        {
279
+            [self storeOriginalNavBarImages];
280
+            
281
+            [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
282
+            self.navigationController.navigationBar.shadowImage = [UIImage new];
283
+            UIVisualEffectView *blur = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
284
+            CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
285
+            blur.frame = CGRectMake(0, -1 * statusBarFrame.size.height, self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height + statusBarFrame.size.height);
286
+            blur.userInteractionEnabled = NO;
287
+            blur.tag = BLUR_NAVBAR_TAG;
288
+            [self.navigationController.navigationBar insertSubview:blur atIndex:0];
289
+        }
290
+    }
291
+    else
292
+    {
293
+        UIView *blur = [viewController.navigationController.navigationBar viewWithTag:BLUR_NAVBAR_TAG];
294
+        if (blur)
295
+        {
296
+            [blur removeFromSuperview];
297
+            [viewController.navigationController.navigationBar setBackgroundImage:self.originalNavBarImages[@"bgImage"] forBarMetrics:UIBarMetricsDefault];
298
+            viewController.navigationController.navigationBar.shadowImage = self.originalNavBarImages[@"shadowImage"];
299
+            self.originalNavBarImages = nil;
300
+        }
301
+    }
302
+    
303
+    NSNumber *navBarTransparent = self.navigatorStyle[@"navBarTransparent"];
304
+    BOOL navBarTransparentBool = navBarTransparent ? [navBarTransparent boolValue] : NO;
305
+    if (navBarTransparentBool)
306
+    {
307
+        if (![viewController.navigationController.navigationBar viewWithTag:TRANSPARENT_NAVBAR_TAG])
308
+        {
309
+            [self storeOriginalNavBarImages];
310
+            
311
+            [viewController.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
312
+            viewController.navigationController.navigationBar.shadowImage = [UIImage new];
313
+            UIView *transparentView = [[UIView alloc] initWithFrame:CGRectZero];
314
+            transparentView.tag = TRANSPARENT_NAVBAR_TAG;
315
+            [viewController.navigationController.navigationBar insertSubview:transparentView atIndex:0];
316
+        }
317
+    }
318
+    else
319
+    {
320
+        UIView *transparentView = [viewController.navigationController.navigationBar viewWithTag:TRANSPARENT_NAVBAR_TAG];
321
+        if (transparentView)
322
+        {
323
+            [transparentView removeFromSuperview];
324
+            [viewController.navigationController.navigationBar setBackgroundImage:self.originalNavBarImages[@"bgImage"] forBarMetrics:UIBarMetricsDefault];
325
+            viewController.navigationController.navigationBar.shadowImage = self.originalNavBarImages[@"shadowImage"];
326
+            self.originalNavBarImages = nil;
327
+        }
328
+    }
329
+    
330
+    NSNumber *navBarTranslucent = self.navigatorStyle[@"navBarTranslucent"];
331
+    BOOL navBarTranslucentBool = navBarTranslucent ? [navBarTranslucent boolValue] : NO;
332
+    if (navBarTranslucentBool || navBarBlurBool)
333
+    {
334
+        viewController.navigationController.navigationBar.translucent = YES;
335
+    }
336
+    else
337
+    {
338
+        viewController.navigationController.navigationBar.translucent = NO;
339
+    }
340
+    
341
+    NSNumber *drawUnderNavBar = self.navigatorStyle[@"drawUnderNavBar"];
342
+    BOOL drawUnderNavBarBool = drawUnderNavBar ? [drawUnderNavBar boolValue] : NO;
343
+    if (drawUnderNavBarBool)
344
+    {
345
+        viewController.edgesForExtendedLayout |= UIRectEdgeTop;
346
+    }
347
+    else
348
+    {
349
+        viewController.edgesForExtendedLayout &= ~UIRectEdgeTop;
350
+    }
351
+    
352
+    NSNumber *drawUnderTabBar = self.navigatorStyle[@"drawUnderTabBar"];
353
+    BOOL drawUnderTabBarBool = drawUnderTabBar ? [drawUnderTabBar boolValue] : NO;
354
+    if (drawUnderTabBarBool)
355
+    {
356
+        viewController.edgesForExtendedLayout |= UIRectEdgeBottom;
357
+    }
358
+    else
359
+    {
360
+        viewController.edgesForExtendedLayout &= ~UIRectEdgeBottom;
361
+    }
362
+    
363
+    NSNumber *removeNavBarBorder = self.navigatorStyle[@"navBarNoBorder"];
364
+    BOOL removeNavBarBorderBool = removeNavBarBorder ? [removeNavBarBorder boolValue] : NO;
365
+    if(removeNavBarBorderBool)
366
+    {
367
+        self.navBarHairlineImageView.hidden = YES;
368
+    }
369
+    else
370
+    {
371
+        self.navBarHairlineImageView.hidden = NO;
372
+    }
373
+  
374
+    //Bug fix: in case there is a interactivePopGestureRecognizer, it prevents react-native from getting touch events on the left screen area that the gesture handles
375
+    //overriding the delegate of the gesture prevents this from happening while keeping the gesture intact (another option was to disable it completely by demand)
376
+    self.originalInteractivePopGestureDelegate = nil;
377
+    if (self.navigationController != nil && self.navigationController.interactivePopGestureRecognizer != nil)
378
+    {
379
+      id <UIGestureRecognizerDelegate> interactivePopGestureRecognizer = self.navigationController.interactivePopGestureRecognizer.delegate;
380
+      if (interactivePopGestureRecognizer != nil)
381
+      {
382
+        self.originalInteractivePopGestureDelegate = interactivePopGestureRecognizer;
383
+        self.navigationController.interactivePopGestureRecognizer.delegate = self;
384
+      }
385
+    }
386
+}
387
+
388
+-(void)storeOriginalNavBarImages {
389
+    NSMutableDictionary *originalNavBarImages = [@{} mutableCopy];
390
+    UIImage *bgImage = [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault];
391
+    if (bgImage != nil)
392
+    {
393
+        originalNavBarImages[@"bgImage"] = bgImage;
394
+    }
395
+    UIImage *shadowImage = self.navigationController.navigationBar.shadowImage;
396
+    if (shadowImage != nil)
397
+    {
398
+        originalNavBarImages[@"shadowImage"] = shadowImage;
399
+    }
400
+    self.originalNavBarImages = originalNavBarImages;
401
+    
402
+}
403
+
404
+-(void)setStyleOnDisappear
405
+{
406
+    self.navBarHairlineImageView.hidden = NO;
407
+  
408
+    if (self.navigationController != nil && self.navigationController.interactivePopGestureRecognizer != nil && self.originalInteractivePopGestureDelegate != nil)
409
+    {
410
+      self.navigationController.interactivePopGestureRecognizer.delegate = self.originalInteractivePopGestureDelegate;
411
+      self.originalInteractivePopGestureDelegate = nil;
412
+    }
413
+}
414
+
415
+// only styles that can't be set on willAppear should be set here
416
+- (void)setStyleOnInit
417
+{
418
+    NSNumber *tabBarHidden = self.navigatorStyle[@"tabBarHidden"];
419
+    BOOL tabBarHiddenBool = tabBarHidden ? [tabBarHidden boolValue] : NO;
420
+    if (tabBarHiddenBool)
421
+    {
422
+        self._hidesBottomBarWhenPushed = YES;
423
+    }
424
+    else
425
+    {
426
+        self._hidesBottomBarWhenPushed = NO;
427
+    }
428
+    
429
+    NSNumber *statusBarHideWithNavBar = self.navigatorStyle[@"statusBarHideWithNavBar"];
430
+    BOOL statusBarHideWithNavBarBool = statusBarHideWithNavBar ? [statusBarHideWithNavBar boolValue] : NO;
431
+    if (statusBarHideWithNavBarBool)
432
+    {
433
+        self._statusBarHideWithNavBar = YES;
434
+    }
435
+    else
436
+    {
437
+        self._statusBarHideWithNavBar = NO;
438
+    }
439
+    
440
+    NSNumber *statusBarHidden = self.navigatorStyle[@"statusBarHidden"];
441
+    BOOL statusBarHiddenBool = statusBarHidden ? [statusBarHidden boolValue] : NO;
442
+    if (statusBarHiddenBool)
443
+    {
444
+        self._statusBarHidden = YES;
445
+    }
446
+    else
447
+    {
448
+        self._statusBarHidden = NO;
449
+    }
450
+}
451
+
452
+- (BOOL)hidesBottomBarWhenPushed
453
+{
454
+    if (!self._hidesBottomBarWhenPushed) return NO;
455
+    return (self.navigationController.topViewController == self);
456
+}
457
+
458
+- (BOOL)prefersStatusBarHidden
459
+{
460
+    if (self._statusBarHidden)
461
+    {
462
+        return YES;
463
+    }
464
+    if (self._statusBarHideWithNavBar)
465
+    {
466
+        return self.navigationController.isNavigationBarHidden;
467
+    }
468
+    else
469
+    {
470
+        return NO;
471
+    }
472
+}
473
+
474
+- (void)setNavBarVisibilityChange:(BOOL)animated {
475
+    [self.navigationController setNavigationBarHidden:[self.navigatorStyle[@"navBarHidden"] boolValue] animated:animated];
476
+}
477
+
478
+
479
+- (UIStatusBarStyle)preferredStatusBarStyle
480
+{
481
+    if (self._statusBarTextColorSchemeLight)
482
+    {
483
+        return UIStatusBarStyleLightContent;
484
+    }
485
+    else
486
+    {
487
+        return UIStatusBarStyleDefault;
488
+    }
489
+}
490
+
491
+- (UIImageView *)findHairlineImageViewUnder:(UIView *)view {
492
+    if ([view isKindOfClass:UIImageView.class] && view.bounds.size.height <= 1.0) {
493
+        return (UIImageView *)view;
494
+    }
495
+    for (UIView *subview in view.subviews) {
496
+        UIImageView *imageView = [self findHairlineImageViewUnder:subview];
497
+        if (imageView) {
498
+            return imageView;
499
+        }
500
+    }
501
+    return nil;
502
+}
503
+
504
+-(void)addExternalVCIfNecessary:(NSDictionary*)props
505
+{
506
+  NSString *externalScreenClass = props[@"externalNativeScreenClass"];
507
+  if (externalScreenClass != nil)
508
+  {
509
+    Class class = NSClassFromString(externalScreenClass);
510
+    if (class != NULL)
511
+    {
512
+      id obj = [[class alloc] init];
513
+      if (obj != nil && [obj isKindOfClass:[UIViewController class]] && [obj conformsToProtocol:@protocol(RCCExternalViewControllerProtocol)])
514
+      {
515
+        ((id <RCCExternalViewControllerProtocol>)obj).controllerDelegate = self;
516
+        [obj setProps:props[@"externalNativeScreenProps"]];
517
+        
518
+        UIViewController *viewController = (UIViewController*)obj;
519
+        [self addChildViewController:viewController];
520
+        viewController.view.frame = self.view.bounds;
521
+        [self.view addSubview:viewController.view];
522
+        [viewController didMoveToParentViewController:self];
523
+      }
524
+      else
525
+      {
526
+        NSLog(@"addExternalVCIfNecessary: could not create instance. Make sure that your class is a UIViewController whihc confirms to RCCExternalViewControllerProtocol");
527
+      }
528
+    }
529
+    else
530
+    {
531
+      NSLog(@"addExternalVCIfNecessary: could not create class from string. Check that the proper class name wass passed in ExternalNativeScreenClass");
532
+    }
533
+  }
534
+}
535
+
536
+#pragma mark - NewRelic
537
+
538
+- (NSString*) customNewRelicInteractionName
539
+{
540
+  NSString *interactionName = nil;
541
+  
542
+  if (self.view != nil && [self.view isKindOfClass:[RCTRootView class]])
543
+  {
544
+    NSString *moduleName = ((RCTRootView*)self.view).moduleName;
545
+    if(moduleName != nil)
546
+    {
547
+      interactionName = [NSString stringWithFormat:@"RCCViewController: %@", moduleName];
548
+    }
549
+  }
550
+  
551
+  if (interactionName == nil)
552
+  {
553
+    interactionName = [NSString stringWithFormat:@"RCCViewController with title: %@", self.title];
554
+  }
555
+  
556
+  return interactionName;
557
+}
558
+
559
+@end

+ 464
- 0
ios/ReactNativeControllers.xcodeproj/project.pbxproj View File

@@ -0,0 +1,464 @@
1
+// !$*UTF8*$!
2
+{
3
+	archiveVersion = 1;
4
+	classes = {
5
+	};
6
+	objectVersion = 46;
7
+	objects = {
8
+
9
+/* Begin PBXBuildFile section */
10
+		260804DB1CE0D9D20094DBA1 /* RCCToolBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 260804DA1CE0D9D20094DBA1 /* RCCToolBar.m */; };
11
+		26AFF3F51D7EEE2400CBA211 /* RCCTitleViewHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 26AFF3F41D7EEE2400CBA211 /* RCCTitleViewHelper.m */; };
12
+		CC84A19E1C1A0C4E00B3A6A2 /* RCCManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CC84A1941C1A0C4E00B3A6A2 /* RCCManager.m */; };
13
+		CC84A19F1C1A0C4E00B3A6A2 /* RCCManagerModule.m in Sources */ = {isa = PBXBuildFile; fileRef = CC84A1961C1A0C4E00B3A6A2 /* RCCManagerModule.m */; };
14
+		CC84A1A01C1A0C4E00B3A6A2 /* RCCNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = CC84A1981C1A0C4E00B3A6A2 /* RCCNavigationController.m */; };
15
+		CC84A1A11C1A0C4E00B3A6A2 /* RCCTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = CC84A19A1C1A0C4E00B3A6A2 /* RCCTabBarController.m */; };
16
+		CC84A1A21C1A0C4E00B3A6A2 /* RCCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CC84A19C1C1A0C4E00B3A6A2 /* RCCViewController.m */; };
17
+		D83514F61D29719A00D53758 /* RCCNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = D83514F51D29719A00D53758 /* RCCNotification.m */; };
18
+		D84813191C8C5EB700051BAF /* RCCLightBox.m in Sources */ = {isa = PBXBuildFile; fileRef = D84813181C8C5EB700051BAF /* RCCLightBox.m */; };
19
+		D85082E11CBCF54200FDB961 /* RCCDrawerHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082CB1CBCF54200FDB961 /* RCCDrawerHelper.m */; };
20
+		D85082E21CBCF54200FDB961 /* RCCTheSideBarManagerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082CE1CBCF54200FDB961 /* RCCTheSideBarManagerViewController.m */; };
21
+		D85082E31CBCF54200FDB961 /* SidebarAirbnbAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082D21CBCF54200FDB961 /* SidebarAirbnbAnimation.m */; };
22
+		D85082E41CBCF54200FDB961 /* SidebarAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082D41CBCF54200FDB961 /* SidebarAnimation.m */; };
23
+		D85082E51CBCF54200FDB961 /* SidebarFacebookAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082D61CBCF54200FDB961 /* SidebarFacebookAnimation.m */; };
24
+		D85082E61CBCF54200FDB961 /* SidebarFeedlyAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082D81CBCF54200FDB961 /* SidebarFeedlyAnimation.m */; };
25
+		D85082E71CBCF54200FDB961 /* SidebarFlipboardAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082DA1CBCF54200FDB961 /* SidebarFlipboardAnimation.m */; };
26
+		D85082E81CBCF54200FDB961 /* SidebarLuvocracyAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082DC1CBCF54200FDB961 /* SidebarLuvocracyAnimation.m */; };
27
+		D85082E91CBCF54200FDB961 /* SidebarWunderlistAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082DE1CBCF54200FDB961 /* SidebarWunderlistAnimation.m */; };
28
+		D85082EA1CBCF54200FDB961 /* TheSidebarController.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082E01CBCF54200FDB961 /* TheSidebarController.m */; };
29
+		D85082FC1CBCF8A800FDB961 /* MMDrawerBarButtonItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082BE1CBCF42400FDB961 /* MMDrawerBarButtonItem.m */; };
30
+		D85082FD1CBCF8A800FDB961 /* MMDrawerController.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082C11CBCF42400FDB961 /* MMDrawerController.m */; };
31
+		D85082FE1CBCF8A800FDB961 /* MMDrawerVisualState.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082C31CBCF42400FDB961 /* MMDrawerVisualState.m */; };
32
+		D85082FF1CBCF8A800FDB961 /* MMExampleDrawerVisualStateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082C51CBCF42400FDB961 /* MMExampleDrawerVisualStateManager.m */; };
33
+		D85083001CBCF8A800FDB961 /* UIViewController+MMDrawerController.m in Sources */ = {isa = PBXBuildFile; fileRef = D85082C71CBCF42400FDB961 /* UIViewController+MMDrawerController.m */; };
34
+		D8D779981D04B7180050CFEA /* RCTHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = D8D779971D04B7180050CFEA /* RCTHelpers.m */; };
35
+		D8E11C571CBD1F670018B644 /* RCCDrawerController.m in Sources */ = {isa = PBXBuildFile; fileRef = D8E11C561CBD1F670018B644 /* RCCDrawerController.m */; };
36
+/* End PBXBuildFile section */
37
+
38
+/* Begin PBXCopyFilesBuildPhase section */
39
+		D8AFADBB1BEE6F3F00A4592D /* CopyFiles */ = {
40
+			isa = PBXCopyFilesBuildPhase;
41
+			buildActionMask = 2147483647;
42
+			dstPath = "include/$(PRODUCT_NAME)";
43
+			dstSubfolderSpec = 16;
44
+			files = (
45
+			);
46
+			runOnlyForDeploymentPostprocessing = 0;
47
+		};
48
+/* End PBXCopyFilesBuildPhase section */
49
+
50
+/* Begin PBXFileReference section */
51
+		260804D91CE0D9D20094DBA1 /* RCCToolBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCToolBar.h; sourceTree = "<group>"; };
52
+		260804DA1CE0D9D20094DBA1 /* RCCToolBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCToolBar.m; sourceTree = "<group>"; };
53
+		26AFF3F31D7EEE2400CBA211 /* RCCTitleViewHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCTitleViewHelper.h; sourceTree = "<group>"; };
54
+		26AFF3F41D7EEE2400CBA211 /* RCCTitleViewHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCTitleViewHelper.m; sourceTree = "<group>"; };
55
+		CC84A1931C1A0C4E00B3A6A2 /* RCCManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCManager.h; sourceTree = "<group>"; };
56
+		CC84A1941C1A0C4E00B3A6A2 /* RCCManager.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = RCCManager.m; sourceTree = "<group>"; tabWidth = 2; };
57
+		CC84A1951C1A0C4E00B3A6A2 /* RCCManagerModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCManagerModule.h; sourceTree = "<group>"; };
58
+		CC84A1961C1A0C4E00B3A6A2 /* RCCManagerModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCManagerModule.m; sourceTree = "<group>"; };
59
+		CC84A1971C1A0C4E00B3A6A2 /* RCCNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCNavigationController.h; sourceTree = "<group>"; };
60
+		CC84A1981C1A0C4E00B3A6A2 /* RCCNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = RCCNavigationController.m; sourceTree = "<group>"; tabWidth = 2; };
61
+		CC84A1991C1A0C4E00B3A6A2 /* RCCTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCTabBarController.h; sourceTree = "<group>"; };
62
+		CC84A19A1C1A0C4E00B3A6A2 /* RCCTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = RCCTabBarController.m; sourceTree = "<group>"; tabWidth = 2; };
63
+		CC84A19B1C1A0C4E00B3A6A2 /* RCCViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCViewController.h; sourceTree = "<group>"; };
64
+		CC84A19C1C1A0C4E00B3A6A2 /* RCCViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = RCCViewController.m; sourceTree = "<group>"; tabWidth = 2; };
65
+		D800E8171CFED1DB004A187F /* RCCExternalViewControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCExternalViewControllerProtocol.h; sourceTree = "<group>"; };
66
+		D83514F41D29719A00D53758 /* RCCNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCNotification.h; sourceTree = "<group>"; };
67
+		D83514F51D29719A00D53758 /* RCCNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCNotification.m; sourceTree = "<group>"; };
68
+		D84813171C8C5EB700051BAF /* RCCLightBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCLightBox.h; sourceTree = "<group>"; };
69
+		D84813181C8C5EB700051BAF /* RCCLightBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCLightBox.m; sourceTree = "<group>"; };
70
+		D85082BD1CBCF42400FDB961 /* MMDrawerBarButtonItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMDrawerBarButtonItem.h; sourceTree = "<group>"; };
71
+		D85082BE1CBCF42400FDB961 /* MMDrawerBarButtonItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MMDrawerBarButtonItem.m; sourceTree = "<group>"; };
72
+		D85082BF1CBCF42400FDB961 /* MMDrawerController+Subclass.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MMDrawerController+Subclass.h"; sourceTree = "<group>"; };
73
+		D85082C01CBCF42400FDB961 /* MMDrawerController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMDrawerController.h; sourceTree = "<group>"; };
74
+		D85082C11CBCF42400FDB961 /* MMDrawerController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MMDrawerController.m; sourceTree = "<group>"; };
75
+		D85082C21CBCF42400FDB961 /* MMDrawerVisualState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMDrawerVisualState.h; sourceTree = "<group>"; };
76
+		D85082C31CBCF42400FDB961 /* MMDrawerVisualState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MMDrawerVisualState.m; sourceTree = "<group>"; };
77
+		D85082C41CBCF42400FDB961 /* MMExampleDrawerVisualStateManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMExampleDrawerVisualStateManager.h; sourceTree = "<group>"; };
78
+		D85082C51CBCF42400FDB961 /* MMExampleDrawerVisualStateManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MMExampleDrawerVisualStateManager.m; sourceTree = "<group>"; };
79
+		D85082C61CBCF42400FDB961 /* UIViewController+MMDrawerController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+MMDrawerController.h"; sourceTree = "<group>"; };
80
+		D85082C71CBCF42400FDB961 /* UIViewController+MMDrawerController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+MMDrawerController.m"; sourceTree = "<group>"; };
81
+		D85082C81CBCF42400FDB961 /* RCCDrawerController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCCDrawerController.h; sourceTree = "<group>"; };
82
+		D85082CA1CBCF54200FDB961 /* RCCDrawerHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCDrawerHelper.h; sourceTree = "<group>"; };
83
+		D85082CB1CBCF54200FDB961 /* RCCDrawerHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCDrawerHelper.m; sourceTree = "<group>"; };
84
+		D85082CC1CBCF54200FDB961 /* RCCDrawerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCDrawerProtocol.h; sourceTree = "<group>"; };
85
+		D85082CD1CBCF54200FDB961 /* RCCTheSideBarManagerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCTheSideBarManagerViewController.h; sourceTree = "<group>"; };
86
+		D85082CE1CBCF54200FDB961 /* RCCTheSideBarManagerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCTheSideBarManagerViewController.m; sourceTree = "<group>"; };
87
+		D85082D11CBCF54200FDB961 /* SidebarAirbnbAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SidebarAirbnbAnimation.h; sourceTree = "<group>"; };
88
+		D85082D21CBCF54200FDB961 /* SidebarAirbnbAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SidebarAirbnbAnimation.m; sourceTree = "<group>"; };
89
+		D85082D31CBCF54200FDB961 /* SidebarAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SidebarAnimation.h; sourceTree = "<group>"; };
90
+		D85082D41CBCF54200FDB961 /* SidebarAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SidebarAnimation.m; sourceTree = "<group>"; };
91
+		D85082D51CBCF54200FDB961 /* SidebarFacebookAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SidebarFacebookAnimation.h; sourceTree = "<group>"; };
92
+		D85082D61CBCF54200FDB961 /* SidebarFacebookAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SidebarFacebookAnimation.m; sourceTree = "<group>"; };
93
+		D85082D71CBCF54200FDB961 /* SidebarFeedlyAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SidebarFeedlyAnimation.h; sourceTree = "<group>"; };
94
+		D85082D81CBCF54200FDB961 /* SidebarFeedlyAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SidebarFeedlyAnimation.m; sourceTree = "<group>"; };
95
+		D85082D91CBCF54200FDB961 /* SidebarFlipboardAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SidebarFlipboardAnimation.h; sourceTree = "<group>"; };
96
+		D85082DA1CBCF54200FDB961 /* SidebarFlipboardAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SidebarFlipboardAnimation.m; sourceTree = "<group>"; };
97
+		D85082DB1CBCF54200FDB961 /* SidebarLuvocracyAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SidebarLuvocracyAnimation.h; sourceTree = "<group>"; };
98
+		D85082DC1CBCF54200FDB961 /* SidebarLuvocracyAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SidebarLuvocracyAnimation.m; sourceTree = "<group>"; };
99
+		D85082DD1CBCF54200FDB961 /* SidebarWunderlistAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SidebarWunderlistAnimation.h; sourceTree = "<group>"; };
100
+		D85082DE1CBCF54200FDB961 /* SidebarWunderlistAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SidebarWunderlistAnimation.m; sourceTree = "<group>"; };
101
+		D85082DF1CBCF54200FDB961 /* TheSidebarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TheSidebarController.h; sourceTree = "<group>"; };
102
+		D85082E01CBCF54200FDB961 /* TheSidebarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TheSidebarController.m; sourceTree = "<group>"; };
103
+		D8AFADBD1BEE6F3F00A4592D /* libReactNativeControllers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativeControllers.a; sourceTree = BUILT_PRODUCTS_DIR; };
104
+		D8D779961D04B7180050CFEA /* RCTHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTHelpers.h; sourceTree = "<group>"; };
105
+		D8D779971D04B7180050CFEA /* RCTHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTHelpers.m; sourceTree = "<group>"; };
106
+		D8E11C561CBD1F670018B644 /* RCCDrawerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCDrawerController.m; sourceTree = "<group>"; };
107
+/* End PBXFileReference section */
108
+
109
+/* Begin PBXFrameworksBuildPhase section */
110
+		D8AFADBA1BEE6F3F00A4592D /* Frameworks */ = {
111
+			isa = PBXFrameworksBuildPhase;
112
+			buildActionMask = 2147483647;
113
+			files = (
114
+			);
115
+			runOnlyForDeploymentPostprocessing = 0;
116
+		};
117
+/* End PBXFrameworksBuildPhase section */
118
+
119
+/* Begin PBXGroup section */
120
+		260804D51CE0D7090094DBA1 /* RCCToolBar */ = {
121
+			isa = PBXGroup;
122
+			children = (
123
+				260804D91CE0D9D20094DBA1 /* RCCToolBar.h */,
124
+				260804DA1CE0D9D20094DBA1 /* RCCToolBar.m */,
125
+			);
126
+			path = RCCToolBar;
127
+			sourceTree = "<group>";
128
+		};
129
+		D85082BB1CBCF42400FDB961 /* RCCDrawerController */ = {
130
+			isa = PBXGroup;
131
+			children = (
132
+				D85082CF1CBCF54200FDB961 /* TheSidebarController */,
133
+				D85082BC1CBCF42400FDB961 /* MMDrawerController */,
134
+				D85082CA1CBCF54200FDB961 /* RCCDrawerHelper.h */,
135
+				D85082CB1CBCF54200FDB961 /* RCCDrawerHelper.m */,
136
+				D85082CC1CBCF54200FDB961 /* RCCDrawerProtocol.h */,
137
+				D85082CD1CBCF54200FDB961 /* RCCTheSideBarManagerViewController.h */,
138
+				D85082CE1CBCF54200FDB961 /* RCCTheSideBarManagerViewController.m */,
139
+				D85082C81CBCF42400FDB961 /* RCCDrawerController.h */,
140
+				D8E11C561CBD1F670018B644 /* RCCDrawerController.m */,
141
+			);
142
+			path = RCCDrawerController;
143
+			sourceTree = "<group>";
144
+		};
145
+		D85082BC1CBCF42400FDB961 /* MMDrawerController */ = {
146
+			isa = PBXGroup;
147
+			children = (
148
+				D85082BD1CBCF42400FDB961 /* MMDrawerBarButtonItem.h */,
149
+				D85082BE1CBCF42400FDB961 /* MMDrawerBarButtonItem.m */,
150
+				D85082BF1CBCF42400FDB961 /* MMDrawerController+Subclass.h */,
151
+				D85082C01CBCF42400FDB961 /* MMDrawerController.h */,
152
+				D85082C11CBCF42400FDB961 /* MMDrawerController.m */,
153
+				D85082C21CBCF42400FDB961 /* MMDrawerVisualState.h */,
154
+				D85082C31CBCF42400FDB961 /* MMDrawerVisualState.m */,
155
+				D85082C41CBCF42400FDB961 /* MMExampleDrawerVisualStateManager.h */,
156
+				D85082C51CBCF42400FDB961 /* MMExampleDrawerVisualStateManager.m */,
157
+				D85082C61CBCF42400FDB961 /* UIViewController+MMDrawerController.h */,
158
+				D85082C71CBCF42400FDB961 /* UIViewController+MMDrawerController.m */,
159
+			);
160
+			path = MMDrawerController;
161
+			sourceTree = "<group>";
162
+		};
163
+		D85082CF1CBCF54200FDB961 /* TheSidebarController */ = {
164
+			isa = PBXGroup;
165
+			children = (
166
+				D85082D01CBCF54200FDB961 /* Animations */,
167
+				D85082DF1CBCF54200FDB961 /* TheSidebarController.h */,
168
+				D85082E01CBCF54200FDB961 /* TheSidebarController.m */,
169
+			);
170
+			path = TheSidebarController;
171
+			sourceTree = "<group>";
172
+		};
173
+		D85082D01CBCF54200FDB961 /* Animations */ = {
174
+			isa = PBXGroup;
175
+			children = (
176
+				D85082D11CBCF54200FDB961 /* SidebarAirbnbAnimation.h */,
177
+				D85082D21CBCF54200FDB961 /* SidebarAirbnbAnimation.m */,
178
+				D85082D31CBCF54200FDB961 /* SidebarAnimation.h */,
179
+				D85082D41CBCF54200FDB961 /* SidebarAnimation.m */,
180
+				D85082D51CBCF54200FDB961 /* SidebarFacebookAnimation.h */,
181
+				D85082D61CBCF54200FDB961 /* SidebarFacebookAnimation.m */,
182
+				D85082D71CBCF54200FDB961 /* SidebarFeedlyAnimation.h */,
183
+				D85082D81CBCF54200FDB961 /* SidebarFeedlyAnimation.m */,
184
+				D85082D91CBCF54200FDB961 /* SidebarFlipboardAnimation.h */,
185
+				D85082DA1CBCF54200FDB961 /* SidebarFlipboardAnimation.m */,
186
+				D85082DB1CBCF54200FDB961 /* SidebarLuvocracyAnimation.h */,
187
+				D85082DC1CBCF54200FDB961 /* SidebarLuvocracyAnimation.m */,
188
+				D85082DD1CBCF54200FDB961 /* SidebarWunderlistAnimation.h */,
189
+				D85082DE1CBCF54200FDB961 /* SidebarWunderlistAnimation.m */,
190
+			);
191
+			path = Animations;
192
+			sourceTree = "<group>";
193
+		};
194
+		D8AFADB41BEE6F3F00A4592D = {
195
+			isa = PBXGroup;
196
+			children = (
197
+				D8D779951D04B7180050CFEA /* Helpers */,
198
+				260804D51CE0D7090094DBA1 /* RCCToolBar */,
199
+				D85082BB1CBCF42400FDB961 /* RCCDrawerController */,
200
+				CC84A1931C1A0C4E00B3A6A2 /* RCCManager.h */,
201
+				CC84A1941C1A0C4E00B3A6A2 /* RCCManager.m */,
202
+				CC84A1951C1A0C4E00B3A6A2 /* RCCManagerModule.h */,
203
+				CC84A1961C1A0C4E00B3A6A2 /* RCCManagerModule.m */,
204
+				CC84A1971C1A0C4E00B3A6A2 /* RCCNavigationController.h */,
205
+				CC84A1981C1A0C4E00B3A6A2 /* RCCNavigationController.m */,
206
+				CC84A1991C1A0C4E00B3A6A2 /* RCCTabBarController.h */,
207
+				CC84A19A1C1A0C4E00B3A6A2 /* RCCTabBarController.m */,
208
+				CC84A19B1C1A0C4E00B3A6A2 /* RCCViewController.h */,
209
+				CC84A19C1C1A0C4E00B3A6A2 /* RCCViewController.m */,
210
+				D84813171C8C5EB700051BAF /* RCCLightBox.h */,
211
+				D84813181C8C5EB700051BAF /* RCCLightBox.m */,
212
+				D800E8171CFED1DB004A187F /* RCCExternalViewControllerProtocol.h */,
213
+				D83514F41D29719A00D53758 /* RCCNotification.h */,
214
+				D83514F51D29719A00D53758 /* RCCNotification.m */,
215
+				D8AFADBE1BEE6F3F00A4592D /* Products */,
216
+			);
217
+			sourceTree = "<group>";
218
+		};
219
+		D8AFADBE1BEE6F3F00A4592D /* Products */ = {
220
+			isa = PBXGroup;
221
+			children = (
222
+				D8AFADBD1BEE6F3F00A4592D /* libReactNativeControllers.a */,
223
+			);
224
+			name = Products;
225
+			sourceTree = "<group>";
226
+		};
227
+		D8D779951D04B7180050CFEA /* Helpers */ = {
228
+			isa = PBXGroup;
229
+			children = (
230
+				D8D779961D04B7180050CFEA /* RCTHelpers.h */,
231
+				D8D779971D04B7180050CFEA /* RCTHelpers.m */,
232
+				26AFF3F31D7EEE2400CBA211 /* RCCTitleViewHelper.h */,
233
+				26AFF3F41D7EEE2400CBA211 /* RCCTitleViewHelper.m */,
234
+			);
235
+			path = Helpers;
236
+			sourceTree = "<group>";
237
+		};
238
+/* End PBXGroup section */
239
+
240
+/* Begin PBXNativeTarget section */
241
+		D8AFADBC1BEE6F3F00A4592D /* ReactNativeControllers */ = {
242
+			isa = PBXNativeTarget;
243
+			buildConfigurationList = D8AFADC61BEE6F3F00A4592D /* Build configuration list for PBXNativeTarget "ReactNativeControllers" */;
244
+			buildPhases = (
245
+				D8AFADB91BEE6F3F00A4592D /* Sources */,
246
+				D8AFADBA1BEE6F3F00A4592D /* Frameworks */,
247
+				D8AFADBB1BEE6F3F00A4592D /* CopyFiles */,
248
+			);
249
+			buildRules = (
250
+			);
251
+			dependencies = (
252
+			);
253
+			name = ReactNativeControllers;
254
+			productName = libReactContacts;
255
+			productReference = D8AFADBD1BEE6F3F00A4592D /* libReactNativeControllers.a */;
256
+			productType = "com.apple.product-type.library.static";
257
+		};
258
+/* End PBXNativeTarget section */
259
+
260
+/* Begin PBXProject section */
261
+		D8AFADB51BEE6F3F00A4592D /* Project object */ = {
262
+			isa = PBXProject;
263
+			attributes = {
264
+				LastUpgradeCheck = 0710;
265
+				ORGANIZATIONNAME = artal;
266
+				TargetAttributes = {
267
+					D8AFADBC1BEE6F3F00A4592D = {
268
+						CreatedOnToolsVersion = 7.1;
269
+					};
270
+				};
271
+			};
272
+			buildConfigurationList = D8AFADB81BEE6F3F00A4592D /* Build configuration list for PBXProject "ReactNativeControllers" */;
273
+			compatibilityVersion = "Xcode 3.2";
274
+			developmentRegion = English;
275
+			hasScannedForEncodings = 0;
276
+			knownRegions = (
277
+				en,
278
+			);
279
+			mainGroup = D8AFADB41BEE6F3F00A4592D;
280
+			productRefGroup = D8AFADBE1BEE6F3F00A4592D /* Products */;
281
+			projectDirPath = "";
282
+			projectRoot = "";
283
+			targets = (
284
+				D8AFADBC1BEE6F3F00A4592D /* ReactNativeControllers */,
285
+			);
286
+		};
287
+/* End PBXProject section */
288
+
289
+/* Begin PBXSourcesBuildPhase section */
290
+		D8AFADB91BEE6F3F00A4592D /* Sources */ = {
291
+			isa = PBXSourcesBuildPhase;
292
+			buildActionMask = 2147483647;
293
+			files = (
294
+				D85082EA1CBCF54200FDB961 /* TheSidebarController.m in Sources */,
295
+				CC84A1A01C1A0C4E00B3A6A2 /* RCCNavigationController.m in Sources */,
296
+				D83514F61D29719A00D53758 /* RCCNotification.m in Sources */,
297
+				CC84A19F1C1A0C4E00B3A6A2 /* RCCManagerModule.m in Sources */,
298
+				26AFF3F51D7EEE2400CBA211 /* RCCTitleViewHelper.m in Sources */,
299
+				D8D779981D04B7180050CFEA /* RCTHelpers.m in Sources */,
300
+				D85082E81CBCF54200FDB961 /* SidebarLuvocracyAnimation.m in Sources */,
301
+				D85082E31CBCF54200FDB961 /* SidebarAirbnbAnimation.m in Sources */,
302
+				D84813191C8C5EB700051BAF /* RCCLightBox.m in Sources */,
303
+				CC84A19E1C1A0C4E00B3A6A2 /* RCCManager.m in Sources */,
304
+				D85082E21CBCF54200FDB961 /* RCCTheSideBarManagerViewController.m in Sources */,
305
+				D85082FC1CBCF8A800FDB961 /* MMDrawerBarButtonItem.m in Sources */,
306
+				D85083001CBCF8A800FDB961 /* UIViewController+MMDrawerController.m in Sources */,
307
+				D85082FF1CBCF8A800FDB961 /* MMExampleDrawerVisualStateManager.m in Sources */,
308
+				D85082E61CBCF54200FDB961 /* SidebarFeedlyAnimation.m in Sources */,
309
+				CC84A1A11C1A0C4E00B3A6A2 /* RCCTabBarController.m in Sources */,
310
+				D85082E71CBCF54200FDB961 /* SidebarFlipboardAnimation.m in Sources */,
311
+				D85082E51CBCF54200FDB961 /* SidebarFacebookAnimation.m in Sources */,
312
+				CC84A1A21C1A0C4E00B3A6A2 /* RCCViewController.m in Sources */,
313
+				D85082E91CBCF54200FDB961 /* SidebarWunderlistAnimation.m in Sources */,
314
+				D85082E11CBCF54200FDB961 /* RCCDrawerHelper.m in Sources */,
315
+				D85082FE1CBCF8A800FDB961 /* MMDrawerVisualState.m in Sources */,
316
+				D85082FD1CBCF8A800FDB961 /* MMDrawerController.m in Sources */,
317
+				D85082E41CBCF54200FDB961 /* SidebarAnimation.m in Sources */,
318
+				D8E11C571CBD1F670018B644 /* RCCDrawerController.m in Sources */,
319
+				260804DB1CE0D9D20094DBA1 /* RCCToolBar.m in Sources */,
320
+			);
321
+			runOnlyForDeploymentPostprocessing = 0;
322
+		};
323
+/* End PBXSourcesBuildPhase section */
324
+
325
+/* Begin XCBuildConfiguration section */
326
+		D8AFADC41BEE6F3F00A4592D /* Debug */ = {
327
+			isa = XCBuildConfiguration;
328
+			buildSettings = {
329
+				ALWAYS_SEARCH_USER_PATHS = NO;
330
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
331
+				CLANG_CXX_LIBRARY = "libc++";
332
+				CLANG_ENABLE_MODULES = YES;
333
+				CLANG_ENABLE_OBJC_ARC = YES;
334
+				CLANG_WARN_BOOL_CONVERSION = YES;
335
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
336
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
337
+				CLANG_WARN_EMPTY_BODY = YES;
338
+				CLANG_WARN_ENUM_CONVERSION = YES;
339
+				CLANG_WARN_INT_CONVERSION = YES;
340
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
341
+				CLANG_WARN_UNREACHABLE_CODE = YES;
342
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
343
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
344
+				COPY_PHASE_STRIP = NO;
345
+				DEBUG_INFORMATION_FORMAT = dwarf;
346
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
347
+				ENABLE_TESTABILITY = YES;
348
+				GCC_C_LANGUAGE_STANDARD = gnu99;
349
+				GCC_DYNAMIC_NO_PIC = NO;
350
+				GCC_NO_COMMON_BLOCKS = YES;
351
+				GCC_OPTIMIZATION_LEVEL = 0;
352
+				GCC_PREPROCESSOR_DEFINITIONS = (
353
+					"DEBUG=1",
354
+					"$(inherited)",
355
+				);
356
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
357
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
358
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
359
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
360
+				GCC_WARN_UNUSED_FUNCTION = YES;
361
+				GCC_WARN_UNUSED_VARIABLE = YES;
362
+				HEADER_SEARCH_PATHS = (
363
+					"$(inherited)",
364
+					"$(SRCROOT)/../../react-native/React/**",
365
+				);
366
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
367
+				MTL_ENABLE_DEBUG_INFO = YES;
368
+				ONLY_ACTIVE_ARCH = YES;
369
+				SDKROOT = iphoneos;
370
+			};
371
+			name = Debug;
372
+		};
373
+		D8AFADC51BEE6F3F00A4592D /* Release */ = {
374
+			isa = XCBuildConfiguration;
375
+			buildSettings = {
376
+				ALWAYS_SEARCH_USER_PATHS = NO;
377
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
378
+				CLANG_CXX_LIBRARY = "libc++";
379
+				CLANG_ENABLE_MODULES = YES;
380
+				CLANG_ENABLE_OBJC_ARC = YES;
381
+				CLANG_WARN_BOOL_CONVERSION = YES;
382
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
383
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
384
+				CLANG_WARN_EMPTY_BODY = YES;
385
+				CLANG_WARN_ENUM_CONVERSION = YES;
386
+				CLANG_WARN_INT_CONVERSION = YES;
387
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
388
+				CLANG_WARN_UNREACHABLE_CODE = YES;
389
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
390
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
391
+				COPY_PHASE_STRIP = NO;
392
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
393
+				ENABLE_NS_ASSERTIONS = NO;
394
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
395
+				GCC_C_LANGUAGE_STANDARD = gnu99;
396
+				GCC_NO_COMMON_BLOCKS = YES;
397
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
398
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
399
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
400
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
401
+				GCC_WARN_UNUSED_FUNCTION = YES;
402
+				GCC_WARN_UNUSED_VARIABLE = YES;
403
+				HEADER_SEARCH_PATHS = (
404
+					"$(inherited)",
405
+					"$(SRCROOT)/../../react-native/React/**",
406
+				);
407
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
408
+				MTL_ENABLE_DEBUG_INFO = NO;
409
+				SDKROOT = iphoneos;
410
+				VALIDATE_PRODUCT = YES;
411
+			};
412
+			name = Release;
413
+		};
414
+		D8AFADC71BEE6F3F00A4592D /* Debug */ = {
415
+			isa = XCBuildConfiguration;
416
+			buildSettings = {
417
+				HEADER_SEARCH_PATHS = (
418
+					"$(inherited)",
419
+					"$(SRCROOT)/../../react-native/React/**",
420
+				);
421
+				OTHER_LDFLAGS = "-ObjC";
422
+				PRODUCT_NAME = "$(TARGET_NAME)";
423
+				SKIP_INSTALL = YES;
424
+			};
425
+			name = Debug;
426
+		};
427
+		D8AFADC81BEE6F3F00A4592D /* Release */ = {
428
+			isa = XCBuildConfiguration;
429
+			buildSettings = {
430
+				HEADER_SEARCH_PATHS = (
431
+					"$(inherited)",
432
+					"$(SRCROOT)/../../react-native/React/**",
433
+				);
434
+				OTHER_LDFLAGS = "-ObjC";
435
+				PRODUCT_NAME = "$(TARGET_NAME)";
436
+				SKIP_INSTALL = YES;
437
+			};
438
+			name = Release;
439
+		};
440
+/* End XCBuildConfiguration section */
441
+
442
+/* Begin XCConfigurationList section */
443
+		D8AFADB81BEE6F3F00A4592D /* Build configuration list for PBXProject "ReactNativeControllers" */ = {
444
+			isa = XCConfigurationList;
445
+			buildConfigurations = (
446
+				D8AFADC41BEE6F3F00A4592D /* Debug */,
447
+				D8AFADC51BEE6F3F00A4592D /* Release */,
448
+			);
449
+			defaultConfigurationIsVisible = 0;
450
+			defaultConfigurationName = Release;
451
+		};
452
+		D8AFADC61BEE6F3F00A4592D /* Build configuration list for PBXNativeTarget "ReactNativeControllers" */ = {
453
+			isa = XCConfigurationList;
454
+			buildConfigurations = (
455
+				D8AFADC71BEE6F3F00A4592D /* Debug */,
456
+				D8AFADC81BEE6F3F00A4592D /* Release */,
457
+			);
458
+			defaultConfigurationIsVisible = 0;
459
+			defaultConfigurationName = Release;
460
+		};
461
+/* End XCConfigurationList section */
462
+	};
463
+	rootObject = D8AFADB51BEE6F3F00A4592D /* Project object */;
464
+}

+ 80
- 0
ios/ReactNativeControllers.xcodeproj/xcshareddata/xcschemes/ReactNativeControllers.xcscheme View File

@@ -0,0 +1,80 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "0710"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "YES"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForTesting = "YES"
11
+            buildForRunning = "YES"
12
+            buildForProfiling = "YES"
13
+            buildForArchiving = "YES"
14
+            buildForAnalyzing = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "D8AFADBC1BEE6F3F00A4592D"
18
+               BuildableName = "libReactNativeControllers.a"
19
+               BlueprintName = "ReactNativeControllers"
20
+               ReferencedContainer = "container:ReactNativeControllers.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+      </BuildActionEntries>
24
+   </BuildAction>
25
+   <TestAction
26
+      buildConfiguration = "Debug"
27
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29
+      shouldUseLaunchSchemeArgsEnv = "YES">
30
+      <Testables>
31
+      </Testables>
32
+      <AdditionalOptions>
33
+      </AdditionalOptions>
34
+   </TestAction>
35
+   <LaunchAction
36
+      buildConfiguration = "Debug"
37
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
38
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
39
+      launchStyle = "0"
40
+      useCustomWorkingDirectory = "NO"
41
+      ignoresPersistentStateOnLaunch = "NO"
42
+      debugDocumentVersioning = "YES"
43
+      debugServiceExtension = "internal"
44
+      allowLocationSimulation = "YES">
45
+      <MacroExpansion>
46
+         <BuildableReference
47
+            BuildableIdentifier = "primary"
48
+            BlueprintIdentifier = "D8AFADBC1BEE6F3F00A4592D"
49
+            BuildableName = "libReactNativeControllers.a"
50
+            BlueprintName = "ReactNativeControllers"
51
+            ReferencedContainer = "container:ReactNativeControllers.xcodeproj">
52
+         </BuildableReference>
53
+      </MacroExpansion>
54
+      <AdditionalOptions>
55
+      </AdditionalOptions>
56
+   </LaunchAction>
57
+   <ProfileAction
58
+      buildConfiguration = "Release"
59
+      shouldUseLaunchSchemeArgsEnv = "YES"
60
+      savedToolIdentifier = ""
61
+      useCustomWorkingDirectory = "NO"
62
+      debugDocumentVersioning = "YES">
63
+      <MacroExpansion>
64
+         <BuildableReference
65
+            BuildableIdentifier = "primary"
66
+            BlueprintIdentifier = "D8AFADBC1BEE6F3F00A4592D"
67
+            BuildableName = "libReactNativeControllers.a"
68
+            BlueprintName = "ReactNativeControllers"
69
+            ReferencedContainer = "container:ReactNativeControllers.xcodeproj">
70
+         </BuildableReference>
71
+      </MacroExpansion>
72
+   </ProfileAction>
73
+   <AnalyzeAction
74
+      buildConfiguration = "Debug">
75
+   </AnalyzeAction>
76
+   <ArchiveAction
77
+      buildConfiguration = "Release"
78
+      revealArchiveInOrganizer = "YES">
79
+   </ArchiveAction>
80
+</Scheme>