Browse Source

Initial support for null as color (#5393)

This commit adds initial support for passing null as a valid value for color properties.
When a color property is applied, if it wasn't specified then the default color is applied. Now, when null is passed, no color will be applied
leaving the last color applied as is.

This is useful when showing an Overlay and you'd like to keep the current StatusBar color unaffected. Another usecase would be when you'd like to avoid coloring an icon in BottomTabs.
Guy Carmeli 4 years ago
parent
commit
3519837cc2
No account linked to committer's email address
40 changed files with 305 additions and 126 deletions
  1. 27
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/params/DontApplyColour.java
  2. 4
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/params/Param.java
  3. 5
    1
      lib/android/app/src/main/java/com/reactnativenavigation/parse/parsers/ColorParser.java
  4. 2
    2
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/BottomTabPresenter.java
  5. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/Presenter.java
  6. 20
    0
      lib/android/app/src/test/java/com/reactnativenavigation/parse/parsers/ColorParseTest.java
  7. 17
    0
      lib/ios/Color.m
  8. 5
    1
      lib/ios/ColorParser.m
  9. 5
    0
      lib/ios/NoColor.h
  10. 22
    0
      lib/ios/NoColor.m
  11. 3
    1
      lib/ios/RNNBasePresenter.h
  12. 35
    32
      lib/ios/RNNBasePresenter.m
  13. 16
    17
      lib/ios/RNNControllerFactory.m
  14. 6
    4
      lib/ios/RNNDotIndicatorPresenter.h
  15. 7
    0
      lib/ios/RNNDotIndicatorPresenter.m
  16. 2
    2
      lib/ios/RNNNavigationControllerPresenter.h
  17. 4
    4
      lib/ios/RNNNavigationControllerPresenter.m
  18. 1
    1
      lib/ios/RNNNavigationOptions.m
  19. 1
    1
      lib/ios/RNNOptions.m
  20. 1
    1
      lib/ios/RNNRootViewController.m
  21. 7
    2
      lib/ios/RNNSideMenuPresenter.m
  22. 7
    2
      lib/ios/RNNSplitViewControllerPresenter.m
  23. 7
    2
      lib/ios/RNNTabBarPresenter.m
  24. 1
    1
      lib/ios/RNNViewControllerPresenter.h
  25. 6
    6
      lib/ios/RNNViewControllerPresenter.m
  26. 8
    0
      lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj
  27. 18
    18
      lib/ios/ReactNativeNavigationTests/RNNBasePresenterTest.m
  28. 26
    1
      lib/ios/ReactNativeNavigationTests/RNNNavigationOptionsTest.m
  29. 5
    0
      lib/ios/ReactNativeNavigationTests/RNNOptionsTest.h
  30. 1
    1
      lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m
  31. 1
    1
      lib/ios/ReactNativeNavigationTests/RNNTabBarControllerTest.m
  32. 1
    2
      lib/ios/ReactNativeNavigationTests/RNNViewControllerPresenterTest.m
  33. 21
    0
      lib/ios/ReactNativeNavigationTests/UIViewController+LayoutProtocolTest.m
  34. 5
    8
      lib/ios/ReactNativeNavigationTests/UIViewController+RNNOptionsTest.m
  35. 0
    2
      lib/ios/UIViewController+LayoutProtocol.h
  36. 2
    7
      lib/ios/UIViewController+LayoutProtocol.m
  37. 1
    1
      lib/ios/UIViewController+RNNOptions.h
  38. 1
    2
      lib/ios/UIViewController+RNNOptions.m
  39. 2
    2
      lib/src/commands/OptionsProcessor.ts
  40. 1
    0
      playground/src/app.js

+ 27
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/params/DontApplyColour.java View File

@@ -0,0 +1,27 @@
1
+package com.reactnativenavigation.parse.params;
2
+
3
+import android.graphics.Color;
4
+
5
+import javax.annotation.Nonnull;
6
+
7
+public class DontApplyColour extends Colour {
8
+    public DontApplyColour() {
9
+        super(Color.TRANSPARENT);
10
+    }
11
+
12
+    @Override
13
+    public boolean hasValue() {
14
+        return true;
15
+    }
16
+
17
+    @Override
18
+    public boolean canApplyValue() {
19
+        return false;
20
+    }
21
+
22
+    @Nonnull
23
+    @Override
24
+    public String toString() {
25
+        return "NoColor";
26
+    }
27
+}

+ 4
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/params/Param.java View File

@@ -24,6 +24,10 @@ public abstract class Param<T> {
24 24
         return value != null;
25 25
     }
26 26
 
27
+    public boolean canApplyValue() {
28
+        return true;
29
+    }
30
+
27 31
     public boolean equals(Param other) {
28 32
         return value == other.value || equalsNotNull(value, other.value);
29 33
     }

+ 5
- 1
lib/android/app/src/main/java/com/reactnativenavigation/parse/parsers/ColorParser.java View File

@@ -1,12 +1,16 @@
1 1
 package com.reactnativenavigation.parse.parsers;
2 2
 
3 3
 import com.reactnativenavigation.parse.params.Colour;
4
+import com.reactnativenavigation.parse.params.DontApplyColour;
4 5
 import com.reactnativenavigation.parse.params.NullColor;
5 6
 
6 7
 import org.json.JSONObject;
7 8
 
8 9
 public class ColorParser {
9 10
     public static Colour parse(JSONObject json, String color) {
10
-        return json.has(color) ? new Colour(json.optInt(color)) : new NullColor();
11
+        if (json.has(color)) {
12
+            return json.opt(color) instanceof Integer ? new Colour(json.optInt(color)) : new DontApplyColour();
13
+        }
14
+        return new NullColor();
11 15
     }
12 16
 }

+ 2
- 2
lib/android/app/src/main/java/com/reactnativenavigation/presentation/BottomTabPresenter.java View File

@@ -52,8 +52,8 @@ public class BottomTabPresenter {
52 52
             for (int i = 0; i < tabs.size(); i++) {
53 53
                 BottomTabOptions tab = tabs.get(i).resolveCurrentOptions(defaultOptions).bottomTabOptions;
54 54
                 bottomTabs.setTitleTypeface(i, tab.fontFamily);
55
-                bottomTabs.setIconActiveColor(i, tab.selectedIconColor.get(null));
56
-                bottomTabs.setIconInactiveColor(i, tab.iconColor.get(null));
55
+                if (tab.selectedIconColor.canApplyValue()) bottomTabs.setIconActiveColor(i, tab.selectedIconColor.get(null));
56
+                if (tab.iconColor.canApplyValue()) bottomTabs.setIconInactiveColor(i, tab.iconColor.get(null));
57 57
                 bottomTabs.setTitleActiveColor(i, tab.selectedTextColor.get(null));
58 58
                 bottomTabs.setTitleInactiveColor(i, tab.textColor.get(null));
59 59
                 bottomTabs.setTitleInactiveTextSizeInSp(i, tab.fontSize.hasValue() ? Float.valueOf(tab.fontSize.get()) : null);

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/presentation/Presenter.java View File

@@ -111,7 +111,7 @@ public class Presenter {
111 111
     }
112 112
 
113 113
     private void setStatusBarBackgroundColor(StatusBarOptions statusBar) {
114
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
114
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && statusBar.backgroundColor.canApplyValue()) {
115 115
             int defaultColor = statusBar.visible.isTrueOrUndefined() ? Color.BLACK : Color.TRANSPARENT;
116 116
             activity.getWindow().setStatusBarColor(statusBar.backgroundColor.get(defaultColor));
117 117
         }

+ 20
- 0
lib/android/app/src/test/java/com/reactnativenavigation/parse/parsers/ColorParseTest.java View File

@@ -0,0 +1,20 @@
1
+package com.reactnativenavigation.parse.parsers;
2
+
3
+import com.reactnativenavigation.BaseTest;
4
+import com.reactnativenavigation.parse.params.DontApplyColour;
5
+
6
+import org.json.JSONException;
7
+import org.json.JSONObject;
8
+import org.junit.Test;
9
+
10
+import static org.assertj.core.api.Java6Assertions.assertThat;
11
+
12
+public class ColorParseTest extends BaseTest {
13
+
14
+    @Test
15
+    public void nullIsParsedAsNoColor() throws JSONException {
16
+        JSONObject json = new JSONObject();
17
+        json.put("color", "NoColor");
18
+        assertThat(ColorParser.parse(json, "color")).isInstanceOf(DontApplyColour.class);
19
+    }
20
+}

+ 17
- 0
lib/ios/Color.m View File

@@ -20,4 +20,21 @@
20 20
 	return [super getWithDefaultValue:defaultValue];
21 21
 }
22 22
 
23
+-(NSString *)description {
24
+	return [self hexStringFromColor:[self getWithDefaultValue:nil]];
25
+}
26
+
27
+- (NSString *)hexStringFromColor:(UIColor *)color {
28
+    const CGFloat *components = CGColorGetComponents(color.CGColor);
29
+
30
+    CGFloat r = components[0];
31
+    CGFloat g = components[1];
32
+    CGFloat b = components[2];
33
+
34
+    return [NSString stringWithFormat:@"#%02lX%02lX%02lX",
35
+                                      lroundf(r * 255),
36
+                                      lroundf(g * 255),
37
+                                      lroundf(b * 255)];
38
+}
39
+
23 40
 @end

+ 5
- 1
lib/ios/ColorParser.m View File

@@ -1,11 +1,15 @@
1 1
 #import "ColorParser.h"
2 2
 #import "NullColor.h"
3
+#import "NoColor.h"
3 4
 #import <React/RCTConvert.h>
4 5
 
5 6
 @implementation ColorParser
6 7
 
7 8
 + (Color *)parse:(NSDictionary *)json key:(NSString *)key {
8
-	return json[key] ? [[Color alloc] initWithValue:[RCTConvert UIColor:json[key]]] : [NullColor new];
9
+	if (json[key]) {
10
+		return [json[key] isKindOfClass:[NSNumber class]] ? [[Color alloc] initWithValue:[RCTConvert UIColor:json[key]]] : [NoColor new];
11
+	}
12
+	return [NullColor new];
9 13
 }
10 14
 
11 15
 @end

+ 5
- 0
lib/ios/NoColor.h View File

@@ -0,0 +1,5 @@
1
+#import "Color.h"
2
+
3
+@interface NoColor : Color
4
+
5
+@end

+ 22
- 0
lib/ios/NoColor.m View File

@@ -0,0 +1,22 @@
1
+#import "NoColor.h"
2
+#import "Color.h"
3
+
4
+
5
+@implementation NoColor
6
+
7
+- (BOOL)hasValue {
8
+    return YES;
9
+}
10
+
11
+- (UIColor *)get {
12
+//    return nil;
13
+    return UIColor.cyanColor;
14
+}
15
+
16
+- (UIColor *)getWithDefaultValue:(id)defaultValue {
17
+    return UIColor.cyanColor;
18
+//    return nil;
19
+}
20
+
21
+
22
+@end

+ 3
- 1
lib/ios/RNNBasePresenter.h View File

@@ -8,6 +8,8 @@ typedef void (^RNNReactViewReadyCompletionBlock)(void);
8 8
 
9 9
 @property(nonatomic, strong) NSString *boundComponentId;
10 10
 
11
+- (instancetype)initWithDefaultOptions:(RNNNavigationOptions *)defaultOptions;
12
+
11 13
 - (void)bindViewController:(UIViewController *)boundViewController;
12 14
 
13 15
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions;
@@ -20,7 +22,7 @@ typedef void (^RNNReactViewReadyCompletionBlock)(void);
20 22
 
21 23
 - (void)applyDotIndicator:(UIViewController *)child;
22 24
 
23
-- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions defaultOptions:(RNNNavigationOptions *)defaultOptions;
25
+- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions;
24 26
 
25 27
 - (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock;
26 28
 

+ 35
- 32
lib/ios/RNNBasePresenter.m View File

@@ -8,13 +8,14 @@
8 8
 
9 9
 @interface RNNBasePresenter ()
10 10
 @property(nonatomic, strong) RNNDotIndicatorPresenter* dotIndicatorPresenter;
11
+@property(nonatomic, strong) RNNNavigationOptions* defaultOptions;
11 12
 @end
12
-
13 13
 @implementation RNNBasePresenter
14 14
 
15
--(instancetype)init {
15
+-(instancetype)initWithDefaultOptions:(RNNNavigationOptions *)defaultOptions {
16 16
     self = [super init];
17
-    self.dotIndicatorPresenter = [RNNDotIndicatorPresenter new];
17
+    _defaultOptions = defaultOptions;
18
+    self.dotIndicatorPresenter = [[RNNDotIndicatorPresenter alloc] initWithDefaultOptions:_defaultOptions];
18 19
     return self;
19 20
 }
20 21
 
@@ -33,64 +34,66 @@
33 34
 
34 35
 - (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options {
35 36
     UIViewController *viewController = self.boundViewController;
37
+    RNNNavigationOptions * withDefault = [options withDefault:_defaultOptions];
36 38
 
37
-    if (options.bottomTab.text.hasValue) {
38
-        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:options.bottomTab];
39
+    if (withDefault.bottomTab.text.hasValue) {
40
+        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:withDefault.bottomTab];
39 41
         viewController.tabBarItem = tabItem;
40 42
     }
41 43
 
42
-    if (options.bottomTab.icon.hasValue) {
43
-        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:options.bottomTab];
44
+    if (withDefault.bottomTab.icon.hasValue) {
45
+        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:withDefault.bottomTab];
44 46
         viewController.tabBarItem = tabItem;
45 47
     }
46 48
 
47
-    if (options.bottomTab.selectedIcon.hasValue) {
48
-        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:options.bottomTab];
49
+    if (withDefault.bottomTab.selectedIcon.hasValue) {
50
+        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:withDefault.bottomTab];
49 51
         viewController.tabBarItem = tabItem;
50 52
     }
51 53
 
52
-    if (options.bottomTab.badgeColor.hasValue) {
53
-        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:options.bottomTab];
54
+    if (withDefault.bottomTab.badgeColor.hasValue) {
55
+        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:withDefault.bottomTab];
54 56
         viewController.tabBarItem = tabItem;
55 57
     }
56 58
 
57
-    if (options.bottomTab.textColor.hasValue) {
58
-        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:options.bottomTab];
59
+    if (withDefault.bottomTab.textColor.hasValue) {
60
+        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:withDefault.bottomTab];
59 61
         viewController.tabBarItem = tabItem;
60 62
     }
61 63
 
62
-    if (options.bottomTab.iconColor.hasValue) {
63
-        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:options.bottomTab];
64
+    if (withDefault.bottomTab.iconColor.hasValue) {
65
+        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:withDefault.bottomTab];
64 66
         viewController.tabBarItem = tabItem;
65 67
     }
66 68
 
67
-    if (options.bottomTab.selectedTextColor.hasValue) {
68
-        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:options.bottomTab];
69
+    if (withDefault.bottomTab.selectedTextColor.hasValue) {
70
+        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:withDefault.bottomTab];
69 71
         viewController.tabBarItem = tabItem;
70 72
     }
71 73
 
72
-    if (options.bottomTab.selectedIconColor.hasValue) {
73
-        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:options.bottomTab];
74
+    if (withDefault.bottomTab.selectedIconColor.hasValue) {
75
+        UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:withDefault.bottomTab];
74 76
         viewController.tabBarItem = tabItem;
75 77
     }
76 78
 }
77 79
 
78 80
 - (void)applyOptions:(RNNNavigationOptions *)options {
79 81
     UIViewController *viewController = self.boundViewController;
82
+    RNNNavigationOptions * withDefault = [options withDefault:_defaultOptions];
80 83
 
81
-    if (options.bottomTab.badge.hasValue && [viewController.parentViewController isKindOfClass:[UITabBarController class]]) {
82
-        [viewController rnn_setTabBarItemBadge:options.bottomTab];
84
+    if (withDefault.bottomTab.badge.hasValue && [viewController.parentViewController isKindOfClass:[UITabBarController class]]) {
85
+        [viewController rnn_setTabBarItemBadge:withDefault.bottomTab.badge.get];
83 86
     }
84 87
 
85
-    if (options.bottomTab.badgeColor.hasValue && [viewController.parentViewController isKindOfClass:[UITabBarController class]]) {
86
-        [viewController rnn_setTabBarItemBadgeColor:options.bottomTab.badgeColor.get];
88
+    if (withDefault.bottomTab.badgeColor.hasValue && [viewController.parentViewController isKindOfClass:[UITabBarController class]]) {
89
+        [viewController rnn_setTabBarItemBadgeColor:withDefault.bottomTab.badgeColor.get];
87 90
     }
88 91
 }
89 92
 
90
-- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions defaultOptions:(RNNNavigationOptions *)defaultOptions {
93
+- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions {
91 94
     UIViewController *viewController = self.boundViewController;
92 95
     if (newOptions.bottomTab.badge.hasValue && [viewController.parentViewController isKindOfClass:[UITabBarController class]]) {
93
-        [viewController rnn_setTabBarItemBadge:newOptions.bottomTab];
96
+        [viewController rnn_setTabBarItemBadge:newOptions.bottomTab.badge.get];
94 97
     }
95 98
 
96 99
     if (newOptions.bottomTab.badgeColor.hasValue && [viewController.parentViewController isKindOfClass:[UITabBarController class]]) {
@@ -102,43 +105,43 @@
102 105
     }
103 106
 
104 107
     if (newOptions.bottomTab.text.hasValue) {
105
-        RNNNavigationOptions *buttonsResolvedOptions = [(RNNNavigationOptions *) [currentOptions overrideOptions:newOptions] withDefault:defaultOptions];
108
+        RNNNavigationOptions *buttonsResolvedOptions = (RNNNavigationOptions *) [currentOptions overrideOptions:newOptions];
106 109
         UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:buttonsResolvedOptions.bottomTab];
107 110
         viewController.tabBarItem = tabItem;
108 111
     }
109 112
 
110 113
     if (newOptions.bottomTab.icon.hasValue) {
111
-        RNNNavigationOptions *buttonsResolvedOptions = [(RNNNavigationOptions *) [currentOptions overrideOptions:newOptions] withDefault:defaultOptions];
114
+        RNNNavigationOptions *buttonsResolvedOptions = (RNNNavigationOptions *) [currentOptions overrideOptions:newOptions];
112 115
         UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:buttonsResolvedOptions.bottomTab];
113 116
         viewController.tabBarItem = tabItem;
114 117
     }
115 118
 
116 119
     if (newOptions.bottomTab.selectedIcon.hasValue) {
117
-        RNNNavigationOptions *buttonsResolvedOptions = [(RNNNavigationOptions *) [currentOptions overrideOptions:newOptions] withDefault:defaultOptions];
120
+        RNNNavigationOptions *buttonsResolvedOptions = (RNNNavigationOptions *) [currentOptions overrideOptions:newOptions];
118 121
         UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:buttonsResolvedOptions.bottomTab];
119 122
         viewController.tabBarItem = tabItem;
120 123
     }
121 124
 
122 125
     if (newOptions.bottomTab.textColor.hasValue) {
123
-        RNNNavigationOptions *buttonsResolvedOptions = [(RNNNavigationOptions *) [currentOptions overrideOptions:newOptions] withDefault:defaultOptions];
126
+        RNNNavigationOptions *buttonsResolvedOptions = (RNNNavigationOptions *) [currentOptions overrideOptions:newOptions];
124 127
         UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:buttonsResolvedOptions.bottomTab];
125 128
         viewController.tabBarItem = tabItem;
126 129
     }
127 130
 
128 131
     if (newOptions.bottomTab.selectedTextColor.hasValue) {
129
-        RNNNavigationOptions *buttonsResolvedOptions = [(RNNNavigationOptions *) [currentOptions overrideOptions:newOptions] withDefault:defaultOptions];
132
+        RNNNavigationOptions *buttonsResolvedOptions = (RNNNavigationOptions *) [currentOptions overrideOptions:newOptions];
130 133
         UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:buttonsResolvedOptions.bottomTab];
131 134
         viewController.tabBarItem = tabItem;
132 135
     }
133 136
 
134 137
     if (newOptions.bottomTab.iconColor.hasValue) {
135
-        RNNNavigationOptions *buttonsResolvedOptions = [(RNNNavigationOptions *) [currentOptions overrideOptions:newOptions] withDefault:defaultOptions];
138
+        RNNNavigationOptions *buttonsResolvedOptions = (RNNNavigationOptions *) [currentOptions overrideOptions:newOptions];
136 139
         UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:buttonsResolvedOptions.bottomTab];
137 140
         viewController.tabBarItem = tabItem;
138 141
     }
139 142
 
140 143
     if (newOptions.bottomTab.selectedIconColor.hasValue) {
141
-        RNNNavigationOptions *buttonsResolvedOptions = [(RNNNavigationOptions *) [currentOptions overrideOptions:newOptions] withDefault:defaultOptions];
144
+        RNNNavigationOptions *buttonsResolvedOptions = (RNNNavigationOptions *) [currentOptions overrideOptions:newOptions];
142 145
         UITabBarItem *tabItem = [RNNTabBarItemCreator updateTabBarItem:viewController.tabBarItem bottomTabOptions:buttonsResolvedOptions.bottomTab];
143 146
         viewController.tabBarItem = tabItem;
144 147
     }

+ 16
- 17
lib/ios/RNNControllerFactory.m View File

@@ -29,7 +29,7 @@
29 29
 	_bridge = bridge;
30 30
 	_store = store;
31 31
 	_componentRegistry = componentRegistry;
32
-	
32
+
33 33
 	return self;
34 34
 }
35 35
 
@@ -103,7 +103,7 @@
103 103
 - (UIViewController *)createComponent:(RNNLayoutNode*)node {
104 104
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
105 105
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
106
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithComponentRegistry:_componentRegistry];
106
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithComponentRegistry:_componentRegistry:_defaultOptions];
107 107
 	
108 108
 	RNNRootViewController* component = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:_creator eventEmitter:_eventEmitter presenter:presenter options:options defaultOptions:_defaultOptions];
109 109
 	
@@ -112,8 +112,8 @@
112 112
 
113 113
 - (UIViewController *)createExternalComponent:(RNNLayoutNode*)node {
114 114
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
115
-	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
116
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
115
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];
116
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithDefaultOptions:_defaultOptions];
117 117
 	
118 118
 	UIViewController* externalVC = [_store getExternalComponent:layoutInfo bridge:_bridge];
119 119
 	
@@ -123,11 +123,10 @@
123 123
 	return component;
124 124
 }
125 125
 
126
-
127 126
 - (UIViewController *)createStack:(RNNLayoutNode*)node {
128
-	RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] initWithComponentRegistry:_componentRegistry];
127
+	RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] initWithComponentRegistry:_componentRegistry :_defaultOptions];
129 128
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
130
-	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
129
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];
131 130
 	
132 131
 	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
133 132
 	
@@ -138,8 +137,8 @@
138 137
 
139 138
 -(UIViewController *)createBottomTabs:(RNNLayoutNode*)node {
140 139
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
141
-	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
142
-	RNNTabBarPresenter* presenter = [RNNTabBarPresenter new];
140
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];
141
+	RNNTabBarPresenter* presenter = [[RNNTabBarPresenter alloc] initWithDefaultOptions:_defaultOptions];
143 142
 
144 143
 	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
145 144
 	
@@ -157,8 +156,8 @@
157 156
 
158 157
 - (UIViewController *)createTopTabs:(RNNLayoutNode*)node {
159 158
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
160
-	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
161
-	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
159
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];
160
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithDefaultOptions :_defaultOptions];
162 161
 
163 162
 	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
164 163
 	
@@ -169,8 +168,8 @@
169 168
 
170 169
 - (UIViewController *)createSideMenu:(RNNLayoutNode*)node {
171 170
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
172
-	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
173
-	RNNSideMenuPresenter* presenter = [[RNNSideMenuPresenter alloc] init];
171
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];
172
+	RNNSideMenuPresenter* presenter = [[RNNSideMenuPresenter alloc] initWithDefaultOptions:_defaultOptions];
174 173
 
175 174
 	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
176 175
 	
@@ -183,17 +182,17 @@
183 182
 - (UIViewController *)createSideMenuChild:(RNNLayoutNode*)node type:(RNNSideMenuChildType)type {
184 183
 	UIViewController* childVc = [self fromTree:node.children[0]];
185 184
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
186
-	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
185
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];
187 186
 
188
-	RNNSideMenuChildVC *sideMenuChild = [[RNNSideMenuChildVC alloc] initWithLayoutInfo:layoutInfo creator:_creator options:options defaultOptions:_defaultOptions presenter:[[RNNViewControllerPresenter alloc] initWithComponentRegistry:_componentRegistry] eventEmitter:_eventEmitter childViewController:childVc type:type];
187
+	RNNSideMenuChildVC *sideMenuChild = [[RNNSideMenuChildVC alloc] initWithLayoutInfo:layoutInfo creator:_creator options:options defaultOptions:_defaultOptions presenter:[[RNNViewControllerPresenter alloc] initWithComponentRegistry:_componentRegistry:_defaultOptions] eventEmitter:_eventEmitter childViewController:childVc type:type];
189 188
 	
190 189
 	return sideMenuChild;
191 190
 }
192 191
 
193 192
 - (UIViewController *)createSplitView:(RNNLayoutNode*)node {
194 193
 	RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
195
-	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;
196
-	RNNSplitViewControllerPresenter* presenter = [[RNNSplitViewControllerPresenter alloc] init];
194
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];
195
+	RNNSplitViewControllerPresenter* presenter = [[RNNSplitViewControllerPresenter alloc] initWithDefaultOptions:_defaultOptions];
197 196
 
198 197
 	NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];
199 198
 

+ 6
- 4
lib/ios/RNNDotIndicatorPresenter.h View File

@@ -1,9 +1,11 @@
1 1
 #import <Foundation/Foundation.h>
2
+#import "DotIndicatorOptions.h"
3
+#import "RNNNavigationOptions.h"
2 4
 
3
-@class UIViewController;
4
-@class DotIndicatorOptions;
5
+@interface RNNDotIndicatorPresenter : NSObject
6
+@property(nonatomic, strong) RNNNavigationOptions* defaultOptions;
5 7
 
8
+- (instancetype)initWithDefaultOptions:(RNNNavigationOptions *)defaultOptions;
6 9
 
7
-@interface RNNDotIndicatorPresenter : NSObject
8 10
 - (void)apply:(UIViewController *)child :(DotIndicatorOptions *)options;
9
-@end
11
+@end

+ 7
- 0
lib/ios/RNNDotIndicatorPresenter.m View File

@@ -3,9 +3,16 @@
3 3
 #import "UIViewController+LayoutProtocol.h"
4 4
 #import "DotIndicatorOptions.h"
5 5
 #import "UITabBarController+RNNUtils.h"
6
+#import "RNNNavigationOptions.h"
6 7
 
7 8
 @implementation RNNDotIndicatorPresenter
8 9
 
10
+-(instancetype)initWithDefaultOptions:(RNNNavigationOptions *)defaultOptions {
11
+    self = [super init];
12
+    _defaultOptions = defaultOptions;
13
+    return self;
14
+}
15
+
9 16
 - (void)apply:(UIViewController *)child :(DotIndicatorOptions *)options {
10 17
     if (![options hasValue]) return;
11 18
 

+ 2
- 2
lib/ios/RNNNavigationControllerPresenter.h View File

@@ -5,9 +5,9 @@
5 5
 
6 6
 @interface RNNNavigationControllerPresenter : RNNBasePresenter
7 7
 
8
-@property (nonatomic, strong) InteractivePopGestureDelegate *interactivePopGestureDelegate;
8
+@property(nonatomic, strong) InteractivePopGestureDelegate *interactivePopGestureDelegate;
9 9
 
10
-- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry;
10
+- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry :(RNNNavigationOptions *)defaultOptions;
11 11
 
12 12
 - (void)applyOptionsBeforePopping:(RNNNavigationOptions *)options;
13 13
 

+ 4
- 4
lib/ios/RNNNavigationControllerPresenter.m View File

@@ -15,8 +15,8 @@
15 15
 @end
16 16
 @implementation RNNNavigationControllerPresenter
17 17
 
18
-- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry {
19
-	self = [super init];
18
+- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry:(RNNNavigationOptions *)defaultOptions {
19
+	self = [super initWithDefaultOptions:defaultOptions];
20 20
 	_componentRegistry = componentRegistry;
21 21
 	return self;
22 22
 }
@@ -65,8 +65,8 @@
65 65
 	[navigationController rnn_setNavigationBarLargeTitleVisible:[options.topBar.largeTitle.visible getWithDefaultValue:NO]];
66 66
 }
67 67
 
68
-- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions defaultOptions:(RNNNavigationOptions *)defaultOptions {
69
-	[super mergeOptions:newOptions currentOptions:currentOptions defaultOptions:defaultOptions];
68
+- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions {
69
+	[super mergeOptions:newOptions currentOptions:currentOptions];
70 70
 	
71 71
 	RNNNavigationController* navigationController = self.boundViewController;
72 72
 	

+ 1
- 1
lib/ios/RNNNavigationOptions.m View File

@@ -45,7 +45,7 @@
45 45
 	return self;
46 46
 }
47 47
 
48
-- (RNNOptions *)copy {
48
+- (RNNNavigationOptions *)copy {
49 49
 	RNNNavigationOptions* newOptions = [[RNNNavigationOptions alloc] initWithDict:@{}];
50 50
 	[newOptions overrideOptions:self];
51 51
 	

+ 1
- 1
lib/ios/RNNOptions.m View File

@@ -46,7 +46,7 @@
46 46
 	RNNOptions* newOptions = [[[self class] alloc] initWithDict:@{}];
47 47
 	[newOptions mergeOptions:defaultOptions overrideOptions:YES];
48 48
 	[newOptions mergeOptions:self overrideOptions:YES];
49
-	
49
+
50 50
 	return newOptions;
51 51
 }
52 52
 

+ 1
- 1
lib/ios/RNNRootViewController.m View File

@@ -28,7 +28,7 @@
28 28
 }
29 29
 
30 30
 - (void)mergeOptions:(RNNNavigationOptions *)options {
31
-	[_presenter mergeOptions:options currentOptions:self.options defaultOptions:self.defaultOptions];
31
+	[_presenter mergeOptions:options currentOptions:self.options];
32 32
 	[self.parentViewController mergeOptions:options];
33 33
 }
34 34
 

+ 7
- 2
lib/ios/RNNSideMenuPresenter.m View File

@@ -3,6 +3,11 @@
3 3
 
4 4
 @implementation RNNSideMenuPresenter
5 5
 
6
+-(instancetype)initWithDefaultOptions:(RNNNavigationOptions *)defaultOptions {
7
+	self = [super initWithDefaultOptions:defaultOptions];
8
+	return self;
9
+}
10
+
6 11
 - (void)applyOptions:(RNNNavigationOptions *)options {
7 12
 	[super applyOptions:options];
8 13
 		
@@ -53,8 +58,8 @@
53 58
 		[sideMenuController setOpenDrawerGestureModeMask:[[initialOptions.sideMenu.openGestureMode getWithDefaultValue:@(MMOpenDrawerGestureModeAll)] integerValue]];
54 59
 }
55 60
 
56
-- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions defaultOptions:(RNNNavigationOptions *)defaultOptions {
57
-	[super mergeOptions:newOptions currentOptions:currentOptions defaultOptions:defaultOptions];
61
+- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions {
62
+	[super mergeOptions:newOptions currentOptions:currentOptions];
58 63
 	
59 64
 	RNNSideMenuController* sideMenuController = self.boundViewController;
60 65
 	

+ 7
- 2
lib/ios/RNNSplitViewControllerPresenter.m View File

@@ -5,6 +5,11 @@
5 5
 
6 6
 @implementation RNNSplitViewControllerPresenter
7 7
 
8
+-(instancetype)initWithDefaultOptions:(RNNNavigationOptions *)defaultOptions {
9
+	self = [super initWithDefaultOptions:defaultOptions];
10
+	return self;
11
+}
12
+
8 13
 - (void)applyOptions:(RNNNavigationOptions *)options {
9 14
 	[super applyOptions:options];
10 15
 	
@@ -26,8 +31,8 @@
26 31
 	[splitViewController rnn_setMaxWidth:initialOptions.splitView.maxWidth];
27 32
 }
28 33
 
29
-- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions defaultOptions:(RNNNavigationOptions *)defaultOptions {
30
-	[super mergeOptions:newOptions currentOptions:currentOptions defaultOptions:defaultOptions];
34
+- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions {
35
+	[super mergeOptions:newOptions currentOptions:currentOptions];
31 36
 	
32 37
 	UISplitViewController* splitViewController = self.boundViewController;
33 38
 

+ 7
- 2
lib/ios/RNNTabBarPresenter.m View File

@@ -5,6 +5,11 @@
5 5
 
6 6
 @implementation RNNTabBarPresenter
7 7
 
8
+-(instancetype)initWithDefaultOptions:(RNNNavigationOptions *)defaultOptions {
9
+    self = [super initWithDefaultOptions:defaultOptions];
10
+    return self;
11
+}
12
+
8 13
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)options {
9 14
     UITabBarController *tabBarController = self.boundViewController;
10 15
     [tabBarController rnn_setCurrentTabIndex:[options.bottomTabs.currentTabIndex getWithDefaultValue:0]];
@@ -21,8 +26,8 @@
21 26
     [tabBarController rnn_setTabBarVisible:[options.bottomTabs.visible getWithDefaultValue:YES] animated:[options.bottomTabs.animate getWithDefaultValue:NO]];
22 27
 }
23 28
 
24
-- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions defaultOptions:(RNNNavigationOptions *)defaultOptions {
25
-    [super mergeOptions:newOptions currentOptions:currentOptions defaultOptions:defaultOptions];
29
+- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions {
30
+    [super mergeOptions:newOptions currentOptions:currentOptions];
26 31
 
27 32
     UITabBarController *tabBarController = self.boundViewController;
28 33
 

+ 1
- 1
lib/ios/RNNViewControllerPresenter.h View File

@@ -4,7 +4,7 @@
4 4
 
5 5
 @interface RNNViewControllerPresenter : RNNBasePresenter
6 6
 
7
-- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry;
7
+- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry:(RNNNavigationOptions *)defaultOptions;
8 8
 
9 9
 - (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock;
10 10
 

+ 6
- 6
lib/ios/RNNViewControllerPresenter.m View File

@@ -17,8 +17,8 @@
17 17
 
18 18
 @implementation RNNViewControllerPresenter
19 19
 
20
-- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry {
21
-	self = [self init];
20
+- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry:(RNNNavigationOptions *)defaultOptions {
21
+	self = [self initWithDefaultOptions:defaultOptions];
22 22
 	_componentRegistry = componentRegistry;
23 23
 	return self;
24 24
 }
@@ -76,8 +76,8 @@
76 76
 	}
77 77
 }
78 78
 
79
-- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions defaultOptions:(RNNNavigationOptions *)defaultOptions {
80
-	[super mergeOptions:newOptions currentOptions:currentOptions defaultOptions:defaultOptions];
79
+- (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions {
80
+	[super mergeOptions:newOptions currentOptions:currentOptions];
81 81
 	
82 82
 	UIViewController* viewController = self.boundViewController;
83 83
 	
@@ -142,7 +142,7 @@
142 142
 	}
143 143
 	
144 144
 	if (newOptions.topBar.leftButtons || newOptions.topBar.rightButtons) {
145
-		RNNNavigationOptions* buttonsResolvedOptions = [(RNNNavigationOptions *)[currentOptions overrideOptions:newOptions] withDefault:defaultOptions];
145
+		RNNNavigationOptions* buttonsResolvedOptions = (RNNNavigationOptions *)[currentOptions overrideOptions:newOptions];
146 146
 		[_navigationButtons applyLeftButtons:newOptions.topBar.leftButtons rightButtons:newOptions.topBar.rightButtons defaultLeftButtonStyle:buttonsResolvedOptions.topBar.leftButtonStyle defaultRightButtonStyle:buttonsResolvedOptions.topBar.rightButtonStyle];
147 147
 	}
148 148
 	
@@ -151,7 +151,7 @@
151 151
 		rootView.passThroughTouches = !newOptions.overlay.interceptTouchOutside.get;
152 152
 	}
153 153
 	
154
-	[self setTitleViewWithSubtitle:(RNNNavigationOptions *)[[currentOptions overrideOptions:newOptions] mergeOptions:defaultOptions]];
154
+	[self setTitleViewWithSubtitle:(RNNNavigationOptions *)[currentOptions overrideOptions:newOptions]];
155 155
 	
156 156
 	if (newOptions.topBar.title.component.name.hasValue) {
157 157
 		[self setCustomNavigationTitleView:newOptions perform:nil];

+ 8
- 0
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj View File

@@ -34,11 +34,13 @@
34 34
 		26916C991E4B9E7700D13680 /* RNNReactRootViewCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = 26916C971E4B9E7700D13680 /* RNNReactRootViewCreator.m */; };
35 35
 		2DCD9195200014A900EDC75D /* RNNBridgeManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DCD9193200014A900EDC75D /* RNNBridgeManager.h */; };
36 36
 		2DCD9196200014A900EDC75D /* RNNBridgeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DCD9194200014A900EDC75D /* RNNBridgeManager.m */; };
37
+		3098702E6833E5CC16D91CE3 /* NoColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 309874C5B132A51A03DAA3BF /* NoColor.h */; };
37 38
 		3098730BC3B4DE41104D9CC4 /* RNNDotIndicatorPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 309878B02F15ECDD1A286722 /* RNNDotIndicatorPresenter.h */; };
38 39
 		309874B40D202C9718F15CBD /* UIView+Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 309877F25920CFE113FADEE0 /* UIView+Utils.h */; };
39 40
 		30987680135A8C78E62D5B8E /* DotIndicatorOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30987122507D8CBF16624F93 /* DotIndicatorOptions.h */; };
40 41
 		309877B0B5AAA7788F56F3D9 /* UIViewController+Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 30987CF6993B89E85C0BCEE4 /* UIViewController+Utils.h */; };
41 42
 		309877F473AECC05FB3B9362 /* UITabBarController+RNNUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 30987FED6F982D322416CAF2 /* UITabBarController+RNNUtils.h */; };
43
+		309878CC9D33CE1CF991EBD1 /* NoColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 309877ADF638DF25FF0DA8A1 /* NoColor.m */; };
42 44
 		30987AB5137F264FA06DA289 /* DotIndicatorOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 309876223177761614786DCC /* DotIndicatorOptions.m */; };
43 45
 		30987B23F288EB3A78B7F27C /* RNNDotIndicatorPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 30987E66AA7AB38E7370F8C8 /* RNNDotIndicatorPresenter.m */; };
44 46
 		30987CA5048A48D6CE76B06C /* DotIndicatorParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 309871FBA64AD937CEF3E191 /* DotIndicatorParser.h */; };
@@ -378,9 +380,11 @@
378 380
 		30987122507D8CBF16624F93 /* DotIndicatorOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DotIndicatorOptions.h; sourceTree = "<group>"; };
379 381
 		309871FBA64AD937CEF3E191 /* DotIndicatorParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DotIndicatorParser.h; sourceTree = "<group>"; };
380 382
 		3098727A36771B4902A14FEA /* RNNTestBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNTestBase.m; sourceTree = "<group>"; };
383
+		309874C5B132A51A03DAA3BF /* NoColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoColor.h; sourceTree = "<group>"; };
381 384
 		309874E37C7E9764C7B694E5 /* DotIndicatorParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DotIndicatorParser.m; sourceTree = "<group>"; };
382 385
 		309876223177761614786DCC /* DotIndicatorOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DotIndicatorOptions.m; sourceTree = "<group>"; };
383 386
 		30987758777622B7D6CCD695 /* RNNDotIndicatorPresenterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNDotIndicatorPresenterTest.m; sourceTree = "<group>"; };
387
+		309877ADF638DF25FF0DA8A1 /* NoColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoColor.m; sourceTree = "<group>"; };
384 388
 		309877F25920CFE113FADEE0 /* UIView+Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Utils.h"; sourceTree = "<group>"; };
385 389
 		309878B02F15ECDD1A286722 /* RNNDotIndicatorPresenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNDotIndicatorPresenter.h; sourceTree = "<group>"; };
386 390
 		30987CF6993B89E85C0BCEE4 /* UIViewController+Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Utils.h"; sourceTree = "<group>"; };
@@ -840,6 +844,8 @@
840 844
 				5039558E217482FE00B0A663 /* NullIntNumber.m */,
841 845
 				503955952174864E00B0A663 /* NullDouble.h */,
842 846
 				503955962174864E00B0A663 /* NullDouble.m */,
847
+				309877ADF638DF25FF0DA8A1 /* NoColor.m */,
848
+				309874C5B132A51A03DAA3BF /* NoColor.h */,
843 849
 			);
844 850
 			name = Params;
845 851
 			sourceTree = "<group>";
@@ -1352,6 +1358,7 @@
1352 1358
 				30987CA5048A48D6CE76B06C /* DotIndicatorParser.h in Headers */,
1353 1359
 				3098730BC3B4DE41104D9CC4 /* RNNDotIndicatorPresenter.h in Headers */,
1354 1360
 				309877F473AECC05FB3B9362 /* UITabBarController+RNNUtils.h in Headers */,
1361
+				3098702E6833E5CC16D91CE3 /* NoColor.h in Headers */,
1355 1362
 			);
1356 1363
 			runOnlyForDeploymentPostprocessing = 0;
1357 1364
 		};
@@ -1618,6 +1625,7 @@
1618 1625
 				30987AB5137F264FA06DA289 /* DotIndicatorOptions.m in Sources */,
1619 1626
 				30987D71FB4FEEAC8D8978E8 /* DotIndicatorParser.m in Sources */,
1620 1627
 				30987B23F288EB3A78B7F27C /* RNNDotIndicatorPresenter.m in Sources */,
1628
+				309878CC9D33CE1CF991EBD1 /* NoColor.m in Sources */,
1621 1629
 			);
1622 1630
 			runOnlyForDeploymentPostprocessing = 0;
1623 1631
 		};

+ 18
- 18
lib/ios/ReactNativeNavigationTests/RNNBasePresenterTest.m View File

@@ -8,8 +8,8 @@
8 8
 
9 9
 @property(nonatomic, strong) RNNBasePresenter *uut;
10 10
 @property(nonatomic, strong) RNNNavigationOptions *options;
11
-@property(nonatomic, strong) RNNRootViewController *bindedViewController;
12
-@property(nonatomic, strong) id mockBindedViewController;
11
+@property(nonatomic, strong) RNNRootViewController *boundViewController;
12
+@property(nonatomic, strong) id mockBoundViewController;
13 13
 
14 14
 @end
15 15
 
@@ -18,46 +18,46 @@
18 18
 - (void)setUp {
19 19
     [super setUp];
20 20
     self.uut = [[RNNBasePresenter alloc] init];
21
-    self.bindedViewController = [RNNRootViewController new];
22
-    self.mockBindedViewController = [OCMockObject partialMockForObject:self.bindedViewController];
23
-    [self.uut bindViewController:self.mockBindedViewController];
21
+    self.boundViewController = [RNNRootViewController new];
22
+    self.mockBoundViewController = [OCMockObject partialMockForObject:self.boundViewController];
23
+    [self.uut bindViewController:self.mockBoundViewController];
24 24
     self.options = [[RNNNavigationOptions alloc] initEmptyOptions];
25 25
 }
26 26
 
27 27
 - (void)tearDown {
28 28
     [super tearDown];
29
-    [self.mockBindedViewController stopMocking];
30
-    self.bindedViewController = nil;
29
+    [self.mockBoundViewController stopMocking];
30
+    self.boundViewController = nil;
31 31
 }
32 32
 
33 33
 - (void)testApplyOptions_shouldSetTabBarItemBadgeOnlyWhenParentIsUITabBarController {
34
-    [[self.mockBindedViewController reject] rnn_setTabBarItemBadge:[OCMArg any]];
34
+    [[self.mockBoundViewController reject] rnn_setTabBarItemBadge:[OCMArg any]];
35 35
     [self.uut applyOptions:self.options];
36
-    [self.mockBindedViewController verify];
36
+    [self.mockBoundViewController verify];
37 37
 }
38 38
 
39 39
 - (void)testApplyOptions_shouldSetTabBarItemBadgeWithValue {
40
-    OCMStub([self.mockBindedViewController parentViewController]).andReturn([UITabBarController new]);
40
+    OCMStub([self.mockBoundViewController parentViewController]).andReturn([UITabBarController new]);
41 41
     self.options.bottomTab.badge = [[Text alloc] initWithValue:@"badge"];
42
-    [[self.mockBindedViewController expect] rnn_setTabBarItemBadge:self.options.bottomTab];
42
+    [[self.mockBoundViewController expect] rnn_setTabBarItemBadge:self.options.bottomTab.badge.get];
43 43
     [self.uut applyOptions:self.options];
44
-    [self.mockBindedViewController verify];
44
+    [self.mockBoundViewController verify];
45 45
 }
46 46
 
47 47
 - (void)testApplyOptions_setTabBarItemBadgeShouldNotCalledOnUITabBarController {
48
-    [self.uut bindViewController:self.mockBindedViewController];
48
+    [self.uut bindViewController:self.mockBoundViewController];
49 49
     self.options.bottomTab.badge = [[Text alloc] initWithValue:@"badge"];
50
-    [[self.mockBindedViewController reject] rnn_setTabBarItemBadge:[[RNNBottomTabOptions alloc] initWithDict:@{@"badge": @"badge"}]];
50
+    [[self.mockBoundViewController reject] rnn_setTabBarItemBadge:[[RNNBottomTabOptions alloc] initWithDict:@{@"badge": @"badge"}]];
51 51
     [self.uut applyOptions:self.options];
52
-    [self.mockBindedViewController verify];
52
+    [self.mockBoundViewController verify];
53 53
 }
54 54
 
55 55
 - (void)testApplyOptions_setTabBarItemBadgeShouldWhenNoValue {
56
-    [self.uut bindViewController:self.mockBindedViewController];
56
+    [self.uut bindViewController:self.mockBoundViewController];
57 57
     self.options.bottomTab.badge = nil;
58
-    [[self.mockBindedViewController reject] rnn_setTabBarItemBadge:[OCMArg any]];
58
+    [[self.mockBoundViewController reject] rnn_setTabBarItemBadge:[OCMArg any]];
59 59
     [self.uut applyOptions:self.options];
60
-    [self.mockBindedViewController verify];
60
+    [self.mockBoundViewController verify];
61 61
 }
62 62
 
63 63
 @end

+ 26
- 1
lib/ios/ReactNativeNavigationTests/RNNNavigationOptionsTest.m View File

@@ -25,7 +25,7 @@
25 25
 	NSDictionary* dynamicOptionsDict = @{@"topBar": @{@"textColor" : @(0xffff00ff), @"title" : @{@"text": @"hello"}}};
26 26
 	RNNNavigationOptions* dynamicOptions = [[RNNNavigationOptions alloc] initWithDict:dynamicOptionsDict];
27 27
 	[options overrideOptions:dynamicOptions];
28
-	
28
+
29 29
 	XCTAssertTrue([options.topBar.title.text.get isEqual:@"hello"]);
30 30
 }
31 31
 
@@ -35,6 +35,31 @@
35 35
 	RNNNavigationOptions* dynamicOptions = [[RNNNavigationOptions alloc] initWithDict:dynamicOptionsDict];
36 36
 	XCTAssertNoThrow([options overrideOptions:dynamicOptions]);
37 37
 }
38
+
39
+- (void)testWithDefault {
40
+	RNNNavigationOptions * options = [[RNNNavigationOptions alloc] initWithDict:@{
41
+			@"topBar": @{
42
+					@"subtitle" : @{@"text": @"hey"}
43
+			},
44
+			@"bottomTab": @{
45
+					@"selectedIconColor": @(0xff000000)
46
+			}
47
+	}];
48
+	RNNNavigationOptions * defaultOptions = [[RNNNavigationOptions alloc] initWithDict:@{
49
+	        @"topBar": @{
50
+                    @"subtitle": @{@"text": @"ho"},
51
+                    @"title": @{@"text": @"hello"}
52
+            },
53
+			@"bottomTab": @{
54
+	        		@"selectedIconColor": @(0xff0000ff)
55
+	        }
56
+	}];
57
+
58
+	RNNNavigationOptions * withDefault = [options withDefault:defaultOptions];
59
+	XCTAssertEqual(withDefault.topBar.subtitle.text.get, @"hey");
60
+	XCTAssertEqual(withDefault.bottomTab.selectedIconColor.get, options.bottomTab.selectedIconColor.get);
61
+}
62
+
38 63
 //
39 64
 //- (void)test_applyDefaultOptions {
40 65
 //	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initEmptyOptions];

+ 5
- 0
lib/ios/ReactNativeNavigationTests/RNNOptionsTest.h View File

@@ -0,0 +1,5 @@
1
+#import <Foundation/Foundation.h>
2
+
3
+
4
+@interface RNNOptionsTest : NSObject
5
+@end

+ 1
- 1
lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m View File

@@ -548,7 +548,7 @@
548 548
 
549 549
 - (void)testMergeOptionsShouldCallPresenterMergeOptions {
550 550
 	RNNNavigationOptions* newOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
551
-	[[(id)self.uut.presenter expect] mergeOptions:newOptions currentOptions:self.uut.options defaultOptions:self.uut.defaultOptions];
551
+	[[(id)self.uut.presenter expect] mergeOptions:newOptions currentOptions:self.uut.options];
552 552
 	[self.uut mergeOptions:newOptions];
553 553
 	[(id)self.uut.presenter verify];
554 554
 }

+ 1
- 1
lib/ios/ReactNativeNavigationTests/RNNTabBarControllerTest.m View File

@@ -90,7 +90,7 @@
90 90
 - (void)testMergeOptions_shouldInvokePresenterMergeOptions {
91 91
     RNNNavigationOptions *options = [[RNNNavigationOptions alloc] initWithDict:@{}];
92 92
 
93
-    [(RNNTabBarPresenter *) [self.mockTabBarPresenter expect] mergeOptions:options currentOptions:[self.uut options] defaultOptions:nil];
93
+    [(RNNTabBarPresenter *) [self.mockTabBarPresenter expect] mergeOptions:options currentOptions:[self.uut options]];
94 94
     [self.uut mergeOptions:options];
95 95
     [self.mockTabBarPresenter verify];
96 96
 }

+ 1
- 2
lib/ios/ReactNativeNavigationTests/RNNViewControllerPresenterTest.m View File

@@ -2,7 +2,6 @@
2 2
 #import <OCMock/OCMock.h>
3 3
 #import "RNNViewControllerPresenter.h"
4 4
 #import "UIViewController+RNNOptions.h"
5
-#import "RNNReactView.h"
6 5
 #import "RNNRootViewController.h"
7 6
 
8 7
 @interface RNNViewControllerPresenterTest : XCTestCase
@@ -19,7 +18,7 @@
19 18
 - (void)setUp {
20 19
     [super setUp];
21 20
 	self.componentRegistry = [OCMockObject partialMockForObject:[RNNReactComponentRegistry new]];
22
-	self.uut = [[RNNViewControllerPresenter alloc] initWithComponentRegistry:self.componentRegistry];
21
+	self.uut = [[RNNViewControllerPresenter alloc] initWithComponentRegistry:self.componentRegistry:[[RNNNavigationOptions alloc] initEmptyOptions]];
23 22
 	self.bindedViewController = [OCMockObject partialMockForObject:[RNNRootViewController new]];
24 23
 	[self.uut bindViewController:self.bindedViewController];
25 24
 	self.options = [[RNNNavigationOptions alloc] initEmptyOptions];

+ 21
- 0
lib/ios/ReactNativeNavigationTests/UIViewController+LayoutProtocolTest.m View File

@@ -4,6 +4,8 @@
4 4
 #import "UIViewController+RNNOptions.h"
5 5
 #import "RNNViewControllerPresenter.h"
6 6
 #import "RCTConvert+Modal.h"
7
+#import "RNNTabBarController.h"
8
+#import "RNNNavigationController.h"
7 9
 
8 10
 @interface UIViewController_LayoutProtocolTest : XCTestCase
9 11
 
@@ -78,4 +80,23 @@
78 80
 	XCTAssertEqual(title, uut.navigationItem.backBarButtonItem.title);
79 81
 }
80 82
 
83
+- (void)testResolveOptions {
84
+	RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];
85
+
86
+	RNNNavigationOptions* childOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
87
+	RNNNavigationOptions* parentOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
88
+		parentOptions.bottomTab.text =  [[Text alloc] initWithValue:@"text"];
89
+		parentOptions.bottomTab.selectedIconColor =  [[Color alloc] initWithValue:UIColor.redColor];
90
+	RNNNavigationOptions* defaultOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
91
+		defaultOptions.bottomTab.text = [[Text alloc] initWithValue:@"default text"];
92
+		defaultOptions.bottomTab.selectedIconColor = [[Color alloc] initWithValue:UIColor.blueColor];
93
+
94
+	UIViewController* child = [[UIViewController alloc] initWithLayoutInfo:nil creator:nil options:childOptions defaultOptions:defaultOptions presenter:presenter eventEmitter:nil childViewControllers:nil];
95
+    RNNNavigationController* parent = [[RNNNavigationController alloc] initWithLayoutInfo:nil creator:nil options:parentOptions defaultOptions:defaultOptions presenter:presenter eventEmitter:nil childViewControllers:@[child]];
96
+
97
+    XCTAssertEqual([parent getCurrentChild], child);
98
+	XCTAssertEqual([[parent resolveOptions].bottomTab.text get], @"text");
99
+	XCTAssertEqual([[parent resolveOptions].bottomTab.selectedIconColor get], UIColor.redColor);
100
+}
101
+
81 102
 @end

+ 5
- 8
lib/ios/ReactNativeNavigationTests/UIViewController+RNNOptionsTest.m View File

@@ -17,23 +17,20 @@
17 17
 }
18 18
 
19 19
 - (void)test_setTabBarItemBadge_shouldSetValidValue {
20
-    NSDictionary *dict = @{@"badge": @"badge"};
21
-    RNNBottomTabOptions * options = [[RNNBottomTabOptions alloc] initWithDict:dict];
22
-    [self.uut rnn_setTabBarItemBadge:options];
20
+    [self.uut rnn_setTabBarItemBadge:@"badge"];
23 21
     XCTAssertEqual([self.uut tabBarItem].badgeValue, @"badge");
24 22
 }
25 23
 
26 24
 - (void)test_setTabBarItemBadge_shouldResetWhenValueIsEmptyString {
27
-    [self.uut rnn_setTabBarItemBadge:[[RNNBottomTabOptions alloc] initWithDict:@{@"badge": @"badge"}]];
25
+    [self.uut rnn_setTabBarItemBadge:@"badge"];
28 26
 
29
-    RNNBottomTabOptions * optionsWithEmptyBadge = [[RNNBottomTabOptions alloc] initWithDict:@{@"badge": @""}];
30
-    [self.uut rnn_setTabBarItemBadge:optionsWithEmptyBadge];
27
+    [self.uut rnn_setTabBarItemBadge:@""];
31 28
     XCTAssertEqual([self.uut tabBarItem].badgeValue, nil);
32 29
 }
33 30
 
34 31
 - (void)test_setTabBarItemBadge_shouldResetWhenValueIsNullObject {
35
-    [self.uut rnn_setTabBarItemBadge:[[RNNBottomTabOptions alloc] initWithDict:@{@"badge": @"badge"}]];
36
-    [self.uut rnn_setTabBarItemBadge:[[RNNBottomTabOptions alloc] initWithDict:@{@"badge": [NSNull new]}]];
32
+    [self.uut rnn_setTabBarItemBadge:@"badge"];
33
+    [self.uut rnn_setTabBarItemBadge:(id) [NSNull new]];
37 34
     XCTAssertEqual([self.uut tabBarItem].badgeValue, nil);
38 35
 }
39 36
 

+ 0
- 2
lib/ios/UIViewController+LayoutProtocol.h View File

@@ -14,8 +14,6 @@ typedef void (^RNNReactViewReadyCompletionBlock)(void);
14 14
 
15 15
 - (RNNNavigationOptions *)resolveOptions;
16 16
 
17
-- (RNNNavigationOptions *)resolveChildOptions:(UIViewController *) child;
18
-
19 17
 - (void)setDefaultOptions:(RNNNavigationOptions *)defaultOptions;
20 18
 
21 19
 - (void)overrideOptions:(RNNNavigationOptions *)options;

+ 2
- 7
lib/ios/UIViewController+LayoutProtocol.m View File

@@ -24,21 +24,16 @@
24 24
 	self.presenter = presenter;
25 25
 	[self.presenter bindViewController:self];
26 26
 	[self.presenter applyOptionsOnInit:self.resolveOptions];
27
-	
28 27
 
29 28
 	return self;
30 29
 }
31 30
 
32 31
 - (RNNNavigationOptions *)resolveOptions {
33
-	return [(RNNNavigationOptions *)[self.options mergeInOptions:self.getCurrentChild.resolveOptions.copy] withDefault:self.defaultOptions];
34
-}
35
-
36
-- (RNNNavigationOptions *)resolveChildOptions:(UIViewController *) child {
37
-	return [(RNNNavigationOptions *)[self.options mergeInOptions:child.resolveOptions.copy] withDefault:self.defaultOptions];
32
+    return (RNNNavigationOptions *) [self.options mergeInOptions:self.getCurrentChild.resolveOptions.copy];
38 33
 }
39 34
 
40 35
 - (void)mergeOptions:(RNNNavigationOptions *)options {
41
-	[self.presenter mergeOptions:options currentOptions:self.options defaultOptions:self.defaultOptions];
36
+	[self.presenter mergeOptions:options currentOptions:self.options];
42 37
 	[self.parentViewController mergeOptions:options];
43 38
 }
44 39
 

+ 1
- 1
lib/ios/UIViewController+RNNOptions.h View File

@@ -20,7 +20,7 @@
20 20
 
21 21
 - (void)rnn_setTabBarItemBadgeColor:(UIColor *)badgeColor;
22 22
 
23
-- (void)rnn_setTabBarItemBadge:(RNNBottomTabOptions *)bottomTab;
23
+- (void)rnn_setTabBarItemBadge:(NSString *)badge;
24 24
 
25 25
 - (void)rnn_setTopBarPrefersLargeTitle:(BOOL)prefersLargeTitle;
26 26
 

+ 1
- 2
lib/ios/UIViewController+RNNOptions.m View File

@@ -81,10 +81,9 @@ const NSInteger BLUR_STATUS_TAG = 78264801;
81 81
 	}
82 82
 }
83 83
 
84
-- (void)rnn_setTabBarItemBadge:(RNNBottomTabOptions *)bottomTab {
84
+- (void)rnn_setTabBarItemBadge:(NSString *)badge {
85 85
     UITabBarItem *tabBarItem = self.tabBarItem;
86 86
 
87
-    NSString *badge = [bottomTab.badge get];
88 87
     if ([badge isKindOfClass:[NSNull class]] || [badge isEqualToString:@""]) {
89 88
         tabBarItem.badgeValue = nil;
90 89
     } else {

+ 2
- 2
lib/src/commands/OptionsProcessor.ts View File

@@ -20,12 +20,12 @@ export class OptionsProcessor {
20 20
 
21 21
   private processObject(objectToProcess: object) {
22 22
     _.forEach(objectToProcess, (value, key) => {
23
+      this.processColor(key, value, objectToProcess);
23 24
       if (!value) {
24 25
         return;
25 26
       }
26 27
 
27 28
       this.processComponent(key, value, objectToProcess);
28
-      this.processColor(key, value, objectToProcess);
29 29
       this.processImage(key, value, objectToProcess);
30 30
       this.processButtonsPassProps(key, value);
31 31
 
@@ -37,7 +37,7 @@ export class OptionsProcessor {
37 37
 
38 38
   private processColor(key: string, value: any, options: Record<string, any>) {
39 39
     if (_.isEqual(key, 'color') || _.endsWith(key, 'Color')) {
40
-      options[key] = this.colorService.toNativeColor(value);
40
+      options[key] = value === null ? 'NoColor' : this.colorService.toNativeColor(value);
41 41
     }
42 42
   }
43 43
 

+ 1
- 0
playground/src/app.js View File

@@ -49,6 +49,7 @@ function start() {
49 49
                   bottomTab: {
50 50
                     text: 'Layouts',
51 51
                     icon: require('../img/layouts.png'),
52
+                    fontSize: 10,
52 53
                     testID: testIDs.LAYOUTS_TAB
53 54
                   }
54 55
                 }