Browse Source

External component (#2846)

* External Component implementation

* Limit External component e2e to Android for now
Guy Carmeli 6 years ago
parent
commit
4c8742f7bd
No account linked to committer's email address
34 changed files with 441 additions and 84 deletions
  1. 3
    3
      e2e/ScreenStack.test.js
  2. 6
    11
      lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java
  3. 20
    0
      lib/android/app/src/main/java/com/reactnativenavigation/NavigationApplication.java
  4. 28
    9
      lib/android/app/src/main/java/com/reactnativenavigation/parse/ExternalComponent.java
  5. 20
    2
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java
  6. 1
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutNode.java
  7. 0
    5
      lib/android/app/src/main/java/com/reactnativenavigation/parse/Options.java
  8. 0
    1
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/FabOptionsPresenter.java
  9. 9
    6
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java
  10. 18
    6
      lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java
  11. 3
    3
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ParentController.java
  12. 2
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/SideMenuController.java
  13. 5
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java
  14. 3
    3
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java
  15. 2
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabFinder.java
  16. 2
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java
  17. 7
    0
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponent.java
  18. 9
    0
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentCreator.java
  19. 41
    0
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java
  20. 2
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java
  21. 42
    0
      lib/android/app/src/main/java/com/reactnativenavigation/views/ExternalComponentLayout.java
  22. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/views/StackLayout.java
  23. 2
    16
      lib/android/app/src/test/java/com/reactnativenavigation/parse/OptionsTest.java
  24. 61
    0
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ExternalComponentViewControllerTest.java
  25. 33
    0
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/externalcomponent/FragmentCreatorMock.java
  26. 8
    0
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/externalcomponent/SomeFragment.java
  27. 1
    1
      lib/src/commands/LayoutTreeParser.ts
  28. 49
    0
      playground/android/app/src/main/java/com/reactnativenavigation/playground/FragmentComponent.java
  29. 15
    0
      playground/android/app/src/main/java/com/reactnativenavigation/playground/FragmentCreator.java
  30. 19
    0
      playground/android/app/src/main/java/com/reactnativenavigation/playground/FragmentScreen.java
  31. 10
    4
      playground/android/app/src/main/java/com/reactnativenavigation/playground/MainApplication.java
  32. 13
    0
      playground/android/app/src/main/res/layout/fragment_screen.xml
  33. 5
    2
      playground/src/screens/WelcomeScreen.js
  34. 1
    1
      playground/src/testIDs.js

+ 3
- 3
e2e/ScreenStack.test.js View File

@@ -69,9 +69,9 @@ describe('screen stack', () => {
69 69
     await expect(elementByLabel('Screen 1')).toBeVisible();
70 70
   });
71 71
 
72
-  it(':ios: push native component with options', async () => {
73
-    await elementById(testIDs.PUSH_NATIVE_COMPONENT_BUTTON).tap();
74
-    await expect(elementById('TestLabel')).toBeVisible();
72
+  it(':android: push external component with options', async () => {
73
+    await elementById(testIDs.PUSH_EXTERNAL_COMPONENT_BUTTON).tap();
74
+    await expect(elementByLabel('This is an external component')).toBeVisible();
75 75
     await expect(elementById(testIDs.TOP_BAR_ELEMENT)).toBeVisible();
76 76
   });
77 77
 });

+ 6
- 11
lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java View File

@@ -1,13 +1,12 @@
1 1
 package com.reactnativenavigation;
2 2
 
3
-import android.os.*;
4
-import android.support.annotation.*;
5
-import android.support.v7.app.*;
6
-import android.view.*;
7
-import android.widget.*;
3
+import android.os.Bundle;
4
+import android.support.annotation.Nullable;
5
+import android.support.v7.app.AppCompatActivity;
6
+import android.view.KeyEvent;
8 7
 
9
-import com.facebook.react.modules.core.*;
10
-import com.reactnativenavigation.viewcontrollers.*;
8
+import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
9
+import com.reactnativenavigation.viewcontrollers.Navigator;
11 10
 
12 11
 public class NavigationActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
13 12
 	private Navigator navigator;
@@ -63,8 +62,4 @@ public class NavigationActivity extends AppCompatActivity implements DefaultHard
63 62
 	public Navigator getNavigator() {
64 63
 		return navigator;
65 64
 	}
66
-
67
-	public void toast(final String text) {
68
-		Toast.makeText(this, text, Toast.LENGTH_LONG).show();
69
-	}
70 65
 }

+ 20
- 0
lib/android/app/src/main/java/com/reactnativenavigation/NavigationApplication.java View File

@@ -7,13 +7,17 @@ import com.facebook.react.ReactApplication;
7 7
 import com.facebook.react.ReactNativeHost;
8 8
 import com.facebook.react.ReactPackage;
9 9
 import com.reactnativenavigation.react.ReactGateway;
10
+import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;
10 11
 
12
+import java.util.HashMap;
11 13
 import java.util.List;
14
+import java.util.Map;
12 15
 
13 16
 public abstract class NavigationApplication extends Application implements ReactApplication {
14 17
 
15 18
 	private ReactGateway reactGateway;
16 19
 	public static NavigationApplication instance;
20
+	final Map<String, ExternalComponentCreator> externalComponents = new HashMap<>();
17 21
 
18 22
 	@Override
19 23
 	public void onCreate() {
@@ -52,4 +56,20 @@ public abstract class NavigationApplication extends Application implements React
52 56
      */
53 57
 	@Nullable
54 58
 	public abstract List<ReactPackage> createAdditionalReactPackages();
59
+
60
+    /**
61
+     * Register a native View which can be displayed using the given {@code name}
62
+     * @param name Unique name used to register the native view
63
+     * @param creator Used to create the view at runtime
64
+     */
65
+    public void registerExternalComponent(String name, ExternalComponentCreator creator) {
66
+        if (externalComponents.containsKey(name)) {
67
+            throw new RuntimeException("A component has already been registered with this name: " + name);
68
+        }
69
+        externalComponents.put(name, creator);
70
+    }
71
+
72
+    public final Map<String, ExternalComponentCreator> getExternalComponents() {
73
+        return externalComponents;
74
+    }
55 75
 }

+ 28
- 9
lib/android/app/src/main/java/com/reactnativenavigation/parse/ExternalComponent.java View File

@@ -4,11 +4,13 @@ import com.reactnativenavigation.parse.params.NullText;
4 4
 import com.reactnativenavigation.parse.params.Text;
5 5
 import com.reactnativenavigation.parse.parsers.TextParser;
6 6
 
7
+import org.json.JSONException;
7 8
 import org.json.JSONObject;
8 9
 
9 10
 public class ExternalComponent {
10 11
 
11
-    public Text classCreator = new NullText();
12
+    public Text name = new NullText();
13
+    public JSONObject passProps = new JSONObject();
12 14
 
13 15
     public static ExternalComponent parse(JSONObject json) {
14 16
         ExternalComponent options = new ExternalComponent();
@@ -16,23 +18,40 @@ public class ExternalComponent {
16 18
             return options;
17 19
         }
18 20
 
19
-        options.classCreator = TextParser.parse(json, "classCreator");
20
-        if (!options.classCreator.hasValue()) {
21
-            throw new RuntimeException("ExternalClass must declare classCreator - a fully qualified method name");
21
+        options.name = TextParser.parse(json, "name");
22
+        if (!options.name.hasValue()) {
23
+            throw new RuntimeException("ExternalComponent must have a name");
22 24
         }
23
-
25
+        options.passProps = parsePassProps(json);
24 26
         return options;
25 27
     }
26 28
 
29
+    private static JSONObject parsePassProps(JSONObject json) {
30
+        if (json.has("passProps")) {
31
+            try {
32
+                return json.getJSONObject("passProps");
33
+            } catch (JSONException e) {
34
+                e.printStackTrace();
35
+            }
36
+        }
37
+        return new JSONObject();
38
+    }
39
+
27 40
     public void mergeWith(ExternalComponent other) {
28
-        if (other.classCreator.hasValue()) {
29
-            classCreator = other.classCreator;
41
+        if (other.name.hasValue()) {
42
+            name = other.name;
43
+        }
44
+        if (other.passProps.length() > 0) {
45
+            passProps = other.passProps;
30 46
         }
31 47
     }
32 48
 
33 49
     public void mergeWithDefault(ExternalComponent defaultOptions) {
34
-        if (!classCreator.hasValue()) {
35
-            classCreator = defaultOptions.classCreator;
50
+        if (!name.hasValue()) {
51
+            name = defaultOptions.name;
52
+        }
53
+        if (passProps.length() == 0) {
54
+            passProps = defaultOptions.passProps;
36 55
         }
37 56
     }
38 57
 }

+ 20
- 2
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java View File

@@ -6,28 +6,33 @@ import com.facebook.react.ReactInstanceManager;
6 6
 import com.reactnativenavigation.utils.ImageLoader;
7 7
 import com.reactnativenavigation.utils.NoOpPromise;
8 8
 import com.reactnativenavigation.utils.TypefaceLoader;
9
-import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
10 9
 import com.reactnativenavigation.viewcontrollers.ComponentViewController;
11 10
 import com.reactnativenavigation.viewcontrollers.SideMenuController;
12 11
 import com.reactnativenavigation.viewcontrollers.StackController;
13 12
 import com.reactnativenavigation.viewcontrollers.ViewController;
13
+import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
14
+import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;
15
+import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
14 16
 import com.reactnativenavigation.viewcontrollers.toptabs.TopTabsController;
15 17
 import com.reactnativenavigation.views.ComponentViewCreator;
16 18
 import com.reactnativenavigation.views.TopTabsLayoutCreator;
17 19
 
18 20
 import java.util.ArrayList;
19 21
 import java.util.List;
22
+import java.util.Map;
20 23
 
21 24
 public class LayoutFactory {
22 25
 
23 26
 	private final Activity activity;
24 27
 	private final ReactInstanceManager reactInstanceManager;
28
+    private Map<String, ExternalComponentCreator> externalComponentCreators;
25 29
     private Options defaultOptions;
26 30
     private final TypefaceLoader typefaceManager;
27 31
 
28
-    public LayoutFactory(Activity activity, final ReactInstanceManager reactInstanceManager, Options defaultOptions) {
32
+    public LayoutFactory(Activity activity, final ReactInstanceManager reactInstanceManager, Map<String, ExternalComponentCreator> externalComponentCreators, Options defaultOptions) {
29 33
 		this.activity = activity;
30 34
 		this.reactInstanceManager = reactInstanceManager;
35
+        this.externalComponentCreators = externalComponentCreators;
31 36
         this.defaultOptions = defaultOptions;
32 37
         typefaceManager = new TypefaceLoader(activity);
33 38
     }
@@ -36,6 +41,8 @@ public class LayoutFactory {
36 41
 		switch (node.type) {
37 42
 			case Component:
38 43
 				return createComponent(node);
44
+            case ExternalComponent:
45
+                return createExternalComponent(node);
39 46
 			case Stack:
40 47
 				return createStack(node);
41 48
 			case BottomTabs:
@@ -101,6 +108,17 @@ public class LayoutFactory {
101 108
         );
102 109
 	}
103 110
 
111
+    private ViewController createExternalComponent(LayoutNode node) {
112
+        final Options options = Options.parse(typefaceManager, node.getNavigationOptions(), defaultOptions);
113
+        ExternalComponent externalComponent = ExternalComponent.parse(node.data);
114
+        return new ExternalComponentViewController(activity,
115
+                node.id,
116
+                externalComponent,
117
+                externalComponentCreators.get(externalComponent.name.get()),
118
+                options
119
+        );
120
+    }
121
+
104 122
 	private ViewController createStack(LayoutNode node) {
105 123
         final Options options = Options.parse(typefaceManager, node.getNavigationOptions(), defaultOptions);
106 124
 		StackController stackController = new StackController(activity, node.id, options);

+ 1
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutNode.java View File

@@ -8,6 +8,7 @@ import java.util.List;
8 8
 public class LayoutNode {
9 9
 	public enum Type {
10 10
 		Component,
11
+        ExternalComponent,
11 12
 		Stack,
12 13
 		BottomTabs,
13 14
 		SideMenuRoot,

+ 0
- 5
lib/android/app/src/main/java/com/reactnativenavigation/parse/Options.java View File

@@ -29,7 +29,6 @@ public class Options implements DEFAULT_VALUES {
29 29
         result.fabOptions = FabOptions.parse(json.optJSONObject("fab"));
30 30
         result.animationsOptions = AnimationsOptions.parse(json.optJSONObject("animations"));
31 31
         result.sideMenuRootOptions = SideMenuRootOptions.parse(json.optJSONObject("sideMenu"));
32
-        result.externalComponent = ExternalComponent.parse(json.optJSONObject("externalComponent"));
33 32
 
34 33
         return result.withDefaultOptions(defaultOptions);
35 34
     }
@@ -44,7 +43,6 @@ public class Options implements DEFAULT_VALUES {
44 43
     @NonNull public FabOptions fabOptions = new FabOptions();
45 44
     @NonNull public AnimationsOptions animationsOptions = new AnimationsOptions();
46 45
     @NonNull public SideMenuRootOptions sideMenuRootOptions = new SideMenuRootOptions();
47
-    @NonNull public ExternalComponent externalComponent = new ExternalComponent();
48 46
 
49 47
     void setTopTabIndex(int i) {
50 48
         topTabOptions.tabIndex = i;
@@ -63,7 +61,6 @@ public class Options implements DEFAULT_VALUES {
63 61
         result.fabOptions.mergeWith(fabOptions);
64 62
         result.animationsOptions.mergeWith(animationsOptions);
65 63
         result.sideMenuRootOptions.mergeWith(sideMenuRootOptions);
66
-        result.externalComponent.mergeWith(externalComponent);
67 64
         return result;
68 65
     }
69 66
 
@@ -79,7 +76,6 @@ public class Options implements DEFAULT_VALUES {
79 76
         result.fabOptions.mergeWith(other.fabOptions);
80 77
         result.animationsOptions.mergeWith(other.animationsOptions);
81 78
         result.sideMenuRootOptions.mergeWith(other.sideMenuRootOptions);
82
-        result.externalComponent.mergeWith(other.externalComponent);
83 79
         return result;
84 80
     }
85 81
 
@@ -93,7 +89,6 @@ public class Options implements DEFAULT_VALUES {
93 89
         fabOptions.mergeWithDefault(other.fabOptions);
94 90
         animationsOptions.mergeWithDefault(other.animationsOptions);
95 91
         sideMenuRootOptions.mergeWithDefault(other.sideMenuRootOptions);
96
-        externalComponent.mergeWithDefault(other.externalComponent);
97 92
         return this;
98 93
     }
99 94
 

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

@@ -10,7 +10,6 @@ import android.widget.RelativeLayout;
10 10
 
11 11
 import com.reactnativenavigation.R;
12 12
 import com.reactnativenavigation.parse.FabOptions;
13
-import com.reactnativenavigation.parse.Options;
14 13
 import com.reactnativenavigation.views.Fab;
15 14
 import com.reactnativenavigation.views.FabMenu;
16 15
 import com.reactnativenavigation.views.ReactComponent;

+ 9
- 6
lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java View File

@@ -2,22 +2,23 @@ package com.reactnativenavigation.presentation;
2 2
 
3 3
 import android.app.Activity;
4 4
 
5
-import com.reactnativenavigation.parse.OrientationOptions;
6
-import com.reactnativenavigation.parse.params.Button;
7 5
 import com.reactnativenavigation.parse.Options;
6
+import com.reactnativenavigation.parse.OrientationOptions;
8 7
 import com.reactnativenavigation.parse.TopBarOptions;
9 8
 import com.reactnativenavigation.parse.TopTabOptions;
10 9
 import com.reactnativenavigation.parse.TopTabsOptions;
11
-import com.reactnativenavigation.views.ReactComponent;
10
+import com.reactnativenavigation.parse.params.Button;
11
+import com.reactnativenavigation.viewcontrollers.IReactView;
12
+import com.reactnativenavigation.views.Component;
12 13
 import com.reactnativenavigation.views.TopBar;
13 14
 
14 15
 import java.util.ArrayList;
15 16
 
16 17
 public class OptionsPresenter {
17 18
     private TopBar topBar;
18
-    private ReactComponent component;
19
+    private Component component;
19 20
 
20
-    public OptionsPresenter(TopBar topBar, ReactComponent component) {
21
+    public OptionsPresenter(TopBar topBar, Component component) {
21 22
         this.topBar = topBar;
22 23
         this.component = component;
23 24
     }
@@ -59,7 +60,9 @@ public class OptionsPresenter {
59 60
         }
60 61
 
61 62
         if (options.hideOnScroll.isTrue()) {
62
-            topBar.enableCollapse(component.getScrollEventListener());
63
+            if (component instanceof IReactView) {
64
+                topBar.enableCollapse(((IReactView) component).getScrollEventListener());
65
+            }
63 66
         } else if (options.hideOnScroll.isTrue()) {
64 67
             topBar.disableCollapse();
65 68
         }

+ 18
- 6
lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java View File

@@ -9,17 +9,21 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
9 9
 import com.facebook.react.bridge.ReactMethod;
10 10
 import com.facebook.react.bridge.ReadableMap;
11 11
 import com.reactnativenavigation.NavigationActivity;
12
+import com.reactnativenavigation.NavigationApplication;
12 13
 import com.reactnativenavigation.parse.LayoutFactory;
13 14
 import com.reactnativenavigation.parse.LayoutNode;
14
-import com.reactnativenavigation.parse.parsers.LayoutNodeParser;
15 15
 import com.reactnativenavigation.parse.Options;
16
+import com.reactnativenavigation.parse.parsers.LayoutNodeParser;
16 17
 import com.reactnativenavigation.utils.TypefaceLoader;
17 18
 import com.reactnativenavigation.utils.UiThread;
18 19
 import com.reactnativenavigation.viewcontrollers.Navigator;
19 20
 import com.reactnativenavigation.viewcontrollers.ViewController;
21
+import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;
20 22
 
21 23
 import org.json.JSONObject;
22 24
 
25
+import java.util.Map;
26
+
23 27
 public class NavigationModule extends ReactContextBaseJavaModule {
24 28
 	private static final String NAME = "RNNBridgeModule";
25 29
 	private final ReactInstanceManager reactInstanceManager;
@@ -113,21 +117,29 @@ public class NavigationModule extends ReactContextBaseJavaModule {
113 117
 		handle(() -> navigator().dismissOverlay(componentId));
114 118
 	}
115 119
 
116
-	private NavigationActivity activity() {
117
-		return (NavigationActivity) getCurrentActivity();
118
-	}
119
-
120 120
 	private Navigator navigator() {
121 121
 		return activity().getNavigator();
122 122
 	}
123 123
 
124 124
 	@NonNull
125 125
 	private LayoutFactory newLayoutFactory() {
126
-		return new LayoutFactory(activity(), reactInstanceManager, navigator().getDefaultOptions());
126
+		return new LayoutFactory(activity(),
127
+                reactInstanceManager,
128
+                externalComponentCreator(),
129
+                navigator().getDefaultOptions()
130
+        );
127 131
 	}
128 132
 
133
+	private Map<String, ExternalComponentCreator> externalComponentCreator() {
134
+        return ((NavigationApplication) activity().getApplication()).getExternalComponents();
135
+    }
136
+
129 137
 	private void handle(Runnable task) {
130 138
 		if (activity() == null || activity().isFinishing()) return;
131 139
 		UiThread.post(task);
132 140
 	}
141
+
142
+    private NavigationActivity activity() {
143
+        return (NavigationActivity) getCurrentActivity();
144
+    }
133 145
 }

+ 3
- 3
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ParentController.java View File

@@ -8,7 +8,7 @@ import android.support.v4.view.ViewPager;
8 8
 import android.view.ViewGroup;
9 9
 
10 10
 import com.reactnativenavigation.parse.Options;
11
-import com.reactnativenavigation.views.ReactComponent;
11
+import com.reactnativenavigation.views.Component;
12 12
 
13 13
 import java.util.Collection;
14 14
 
@@ -46,7 +46,7 @@ public abstract class ParentController<T extends ViewGroup> extends ViewControll
46 46
 	}
47 47
 
48 48
 	@Override
49
-    public boolean containsComponent(ReactComponent component) {
49
+    public boolean containsComponent(Component component) {
50 50
         if (super.containsComponent(component)) {
51 51
             return true;
52 52
         }
@@ -57,7 +57,7 @@ public abstract class ParentController<T extends ViewGroup> extends ViewControll
57 57
     }
58 58
 
59 59
     @CallSuper
60
-    public void applyOptions(Options options, ReactComponent childComponent) {
60
+    public void applyOptions(Options options, Component childComponent) {
61 61
         mergeChildOptions(options);
62 62
     }
63 63
 

+ 2
- 2
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/SideMenuController.java View File

@@ -9,7 +9,7 @@ import android.view.View;
9 9
 import com.reactnativenavigation.parse.Options;
10 10
 import com.reactnativenavigation.presentation.NavigationOptionsListener;
11 11
 import com.reactnativenavigation.presentation.SideMenuOptionsPresenter;
12
-import com.reactnativenavigation.views.ReactComponent;
12
+import com.reactnativenavigation.views.Component;
13 13
 
14 14
 import java.util.ArrayList;
15 15
 import java.util.Collection;
@@ -49,7 +49,7 @@ public class SideMenuController extends ParentController<DrawerLayout> implement
49 49
 	}
50 50
 
51 51
     @Override
52
-    public void applyOptions(Options options, ReactComponent childComponent) {
52
+    public void applyOptions(Options options, Component childComponent) {
53 53
         super.applyOptions(options, childComponent);
54 54
         applyOnParentController(parentController ->
55 55
                 ((ParentController) parentController).applyOptions(this.options, childComponent)

+ 5
- 2
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java View File

@@ -10,6 +10,7 @@ import com.facebook.react.bridge.Promise;
10 10
 import com.reactnativenavigation.anim.NavigationAnimator;
11 11
 import com.reactnativenavigation.parse.Options;
12 12
 import com.reactnativenavigation.utils.NoOpPromise;
13
+import com.reactnativenavigation.views.Component;
13 14
 import com.reactnativenavigation.views.ReactComponent;
14 15
 import com.reactnativenavigation.views.StackLayout;
15 16
 import com.reactnativenavigation.views.TopBar;
@@ -44,13 +45,15 @@ public class StackController extends ParentController <StackLayout> {
44 45
     }
45 46
 
46 47
     @Override
47
-    public void applyOptions(Options options, ReactComponent component) {
48
+    public void applyOptions(Options options, Component component) {
48 49
         super.applyOptions(options, component);
49 50
         getView().applyOptions(this.options, component);
50 51
         applyOnParentController(parentController ->
51 52
                 ((ParentController) parentController).applyOptions(this.options.copy().clearTopBarOptions(), component)
52 53
         );
53
-        fabOptionsPresenter.applyOptions(options.fabOptions, component, getView());
54
+        if (component instanceof ReactComponent) {
55
+            fabOptionsPresenter.applyOptions(options.fabOptions, (ReactComponent) component, getView());
56
+        }
54 57
         animator.setOptions(options.animationsOptions);
55 58
     }
56 59
 

+ 3
- 3
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java View File

@@ -15,7 +15,7 @@ import com.reactnativenavigation.presentation.FabOptionsPresenter;
15 15
 import com.reactnativenavigation.utils.CompatUtils;
16 16
 import com.reactnativenavigation.utils.StringUtils;
17 17
 import com.reactnativenavigation.utils.Task;
18
-import com.reactnativenavigation.views.ReactComponent;
18
+import com.reactnativenavigation.views.Component;
19 19
 
20 20
 public abstract class ViewController<T extends ViewGroup> implements ViewTreeObserver.OnGlobalLayoutListener {
21 21
 
@@ -132,7 +132,7 @@ public abstract class ViewController<T extends ViewGroup> implements ViewTreeObs
132 132
         return isSameId(id) ? this : null;
133 133
     }
134 134
 
135
-    public boolean containsComponent(ReactComponent component) {
135
+    public boolean containsComponent(Component component) {
136 136
         return getView().equals(component);
137 137
     }
138 138
 
@@ -153,7 +153,7 @@ public abstract class ViewController<T extends ViewGroup> implements ViewTreeObs
153 153
         applyOptions(options);
154 154
         applyOnParentController(parentController -> {
155 155
             parentController.clearOptions();
156
-            if (getView() instanceof ReactComponent) parentController.applyOptions(options, (ReactComponent) getView());
156
+            if (getView() instanceof Component) parentController.applyOptions(options, (Component) getView());
157 157
         });
158 158
     }
159 159
 

+ 2
- 2
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabFinder.java View File

@@ -3,7 +3,7 @@ package com.reactnativenavigation.viewcontrollers.bottomtabs;
3 3
 import android.support.annotation.IntRange;
4 4
 
5 5
 import com.reactnativenavigation.viewcontrollers.ViewController;
6
-import com.reactnativenavigation.views.ReactComponent;
6
+import com.reactnativenavigation.views.Component;
7 7
 
8 8
 import java.util.List;
9 9
 
@@ -11,7 +11,7 @@ public class BottomTabFinder {
11 11
     private List<ViewController> tabs;
12 12
 
13 13
     @IntRange(from = -1)
14
-    public int findByComponent(ReactComponent component) {
14
+    int findByComponent(Component component) {
15 15
         for (int i = 0; i < tabs.size(); i++) {
16 16
             if (tabs.get(i).containsComponent(component)) {
17 17
                 return i;

+ 2
- 2
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java View File

@@ -16,7 +16,7 @@ import com.reactnativenavigation.utils.ImageLoader;
16 16
 import com.reactnativenavigation.viewcontrollers.ParentController;
17 17
 import com.reactnativenavigation.viewcontrollers.ViewController;
18 18
 import com.reactnativenavigation.views.BottomTabs;
19
-import com.reactnativenavigation.views.ReactComponent;
19
+import com.reactnativenavigation.views.Component;
20 20
 
21 21
 import java.util.ArrayList;
22 22
 import java.util.Collection;
@@ -57,7 +57,7 @@ public class BottomTabsController extends ParentController implements AHBottomNa
57 57
     }
58 58
 
59 59
     @Override
60
-    public void applyOptions(Options options, ReactComponent childComponent) {
60
+    public void applyOptions(Options options, Component childComponent) {
61 61
         super.applyOptions(options, childComponent);
62 62
         int tabIndex = bottomTabFinder.findByComponent(childComponent);
63 63
         if (tabIndex >= 0) new BottomTabsOptionsPresenter(bottomTabs, bottomTabFinder).present(this.options, tabIndex);

+ 7
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponent.java View File

@@ -0,0 +1,7 @@
1
+package com.reactnativenavigation.viewcontrollers.externalcomponent;
2
+
3
+import android.view.View;
4
+
5
+public interface ExternalComponent {
6
+    View asView();
7
+}

+ 9
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentCreator.java View File

@@ -0,0 +1,9 @@
1
+package com.reactnativenavigation.viewcontrollers.externalcomponent;
2
+
3
+import android.support.v4.app.FragmentActivity;
4
+
5
+import org.json.JSONObject;
6
+
7
+public interface ExternalComponentCreator {
8
+    ExternalComponent create(FragmentActivity activity, JSONObject props);
9
+}

+ 41
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java View File

@@ -0,0 +1,41 @@
1
+package com.reactnativenavigation.viewcontrollers.externalcomponent;
2
+
3
+import android.app.Activity;
4
+import android.support.v4.app.FragmentActivity;
5
+
6
+import com.reactnativenavigation.parse.ExternalComponent;
7
+import com.reactnativenavigation.parse.Options;
8
+import com.reactnativenavigation.viewcontrollers.ViewController;
9
+import com.reactnativenavigation.views.ExternalComponentLayout;
10
+
11
+public class ExternalComponentViewController extends ViewController<ExternalComponentLayout> {
12
+    private final ExternalComponent externalComponent;
13
+    private final ExternalComponentCreator componentCreator;
14
+
15
+    public ExternalComponentViewController(Activity activity, String id, ExternalComponent externalComponent, ExternalComponentCreator componentCreator, Options initialOptions) {
16
+        super(activity, id, initialOptions);
17
+        this.externalComponent = externalComponent;
18
+        this.componentCreator = componentCreator;
19
+    }
20
+
21
+    @Override
22
+    public void applyOptions(Options options) {
23
+        getView().applyOptions(options);
24
+    }
25
+
26
+    @Override
27
+    protected ExternalComponentLayout createView() {
28
+        ExternalComponentLayout content = new ExternalComponentLayout(getActivity());
29
+        content.addView(componentCreator.create(getActivity(), externalComponent.passProps).asView());
30
+        return content;
31
+    }
32
+
33
+    @Override
34
+    public void sendOnNavigationButtonPressed(String buttonId) {
35
+
36
+    }
37
+
38
+    public FragmentActivity getActivity() {
39
+        return (FragmentActivity) super.getActivity();
40
+    }
41
+}

+ 2
- 2
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java View File

@@ -10,7 +10,7 @@ import com.reactnativenavigation.utils.Task;
10 10
 import com.reactnativenavigation.viewcontrollers.ParentController;
11 11
 import com.reactnativenavigation.viewcontrollers.ViewController;
12 12
 import com.reactnativenavigation.viewcontrollers.ViewVisibilityListenerAdapter;
13
-import com.reactnativenavigation.views.ReactComponent;
13
+import com.reactnativenavigation.views.Component;
14 14
 import com.reactnativenavigation.views.TopTabsLayoutCreator;
15 15
 import com.reactnativenavigation.views.TopTabsViewPager;
16 16
 
@@ -79,7 +79,7 @@ public class TopTabsController extends ParentController<TopTabsViewPager> implem
79 79
     }
80 80
 
81 81
     @Override
82
-    public void applyOptions(Options options, ReactComponent childComponent) {
82
+    public void applyOptions(Options options, Component childComponent) {
83 83
         super.applyOptions(options, childComponent);
84 84
         applyOnParentController(parentController -> {
85 85
                 Options opt = this.options.copy();

+ 42
- 0
lib/android/app/src/main/java/com/reactnativenavigation/views/ExternalComponentLayout.java View File

@@ -0,0 +1,42 @@
1
+package com.reactnativenavigation.views;
2
+
3
+import android.annotation.SuppressLint;
4
+import android.content.Context;
5
+import android.widget.FrameLayout;
6
+import android.widget.RelativeLayout;
7
+
8
+import com.reactnativenavigation.parse.Options;
9
+import com.reactnativenavigation.presentation.ComponentOptionsPresenter;
10
+
11
+import static android.widget.RelativeLayout.BELOW;
12
+
13
+@SuppressLint("ViewConstructor")
14
+public class ExternalComponentLayout extends FrameLayout implements Component {
15
+    public ExternalComponentLayout(Context context) {
16
+		super(context);
17
+        setContentDescription("ExternalComponentLayout");
18
+    }
19
+
20
+    @Override
21
+    public void applyOptions(Options options) {
22
+        new ComponentOptionsPresenter(this).present(options);
23
+    }
24
+
25
+    @Override
26
+    public void drawBehindTopBar() {
27
+        if (getParent() instanceof RelativeLayout) {
28
+            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
29
+            layoutParams.removeRule(BELOW);
30
+            setLayoutParams(layoutParams);
31
+        }
32
+    }
33
+
34
+    @Override
35
+    public void drawBelowTopBar(TopBar topBar) {
36
+        if (getParent() instanceof RelativeLayout) {
37
+            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
38
+            layoutParams.addRule(BELOW, topBar.getId());
39
+            setLayoutParams(layoutParams);
40
+        }
41
+    }
42
+}

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/views/StackLayout.java View File

@@ -33,7 +33,7 @@ public class StackLayout extends RelativeLayout {
33 33
         new OptionsPresenter(topBar).applyOrientation(options.orientationOptions);
34 34
     }
35 35
 
36
-    public void applyOptions(Options options, ReactComponent component) {
36
+    public void applyOptions(Options options, Component component) {
37 37
         new OptionsPresenter(topBar, component).applyOptions(options);
38 38
     }
39 39
 

+ 2
- 16
lib/android/app/src/test/java/com/reactnativenavigation/parse/OptionsTest.java View File

@@ -39,7 +39,6 @@ public class OptionsTest extends BaseTest {
39 39
     private static final String BOTTOM_TABS_BADGE = "3";
40 40
     private static final String BOTTOM_TABS_CURRENT_TAB_ID = "ComponentId";
41 41
     private static final Number BOTTOM_TABS_CURRENT_TAB_INDEX = new Number(1);
42
-    private static final String EXTERNAL_CLASS_CREATOR = "com.rnn.creators.Creator.createFragment";
43 42
     private TypefaceLoader mockLoader;
44 43
 
45 44
     @Override
@@ -58,7 +57,6 @@ public class OptionsTest extends BaseTest {
58 57
         JSONObject json = new JSONObject()
59 58
                 .put("topBar", createTopBar(TOP_BAR_VISIBLE.get()))
60 59
                 .put("fab", createFab())
61
-                .put("externalComponent", createExternalComponent())
62 60
                 .put("bottomTabs", createBottomTabs());
63 61
         Options result = Options.parse(mockLoader, json);
64 62
         assertResult(result);
@@ -85,7 +83,6 @@ public class OptionsTest extends BaseTest {
85 83
         assertThat(result.fabOptions.hideOnScroll.get()).isEqualTo(FAB_HIDE_ON_SCROLL);
86 84
         assertThat(result.fabOptions.alignVertically.get()).isEqualTo(FAB_ALIGN_VERTICALLY);
87 85
         assertThat(result.fabOptions.alignHorizontally.get()).isEqualTo(FAB_ALIGN_HORIZONTALLY);
88
-        assertThat(result.externalComponent.classCreator.get()).isEqualTo(EXTERNAL_CLASS_CREATOR);
89 86
     }
90 87
 
91 88
     @NonNull
@@ -123,11 +120,6 @@ public class OptionsTest extends BaseTest {
123 120
                 .put("visible", FAB_VISIBLE);
124 121
     }
125 122
 
126
-    private JSONObject createExternalComponent() throws JSONException {
127
-        return new JSONObject()
128
-                .put("classCreator", EXTERNAL_CLASS_CREATOR);
129
-    }
130
-
131 123
     @NonNull
132 124
     private JSONObject createOtherFab() throws JSONException {
133 125
         return new JSONObject()
@@ -162,10 +154,6 @@ public class OptionsTest extends BaseTest {
162 154
                 .put("tabBadge", BOTTOM_TABS_BADGE);
163 155
     }
164 156
 
165
-    private JSONObject createOtherExternalClass() {
166
-        return new JSONObject();
167
-    }
168
-
169 157
     @Test
170 158
     public void mergeDoesNotMutate() throws Exception {
171 159
         JSONObject json1 = new JSONObject();
@@ -189,8 +177,7 @@ public class OptionsTest extends BaseTest {
189 177
         JSONObject json = new JSONObject()
190 178
                 .put("topBar", createTopBar(TOP_BAR_VISIBLE.get()))
191 179
                 .put("fab", createFab())
192
-                .put("bottomTabs", createBottomTabs())
193
-                .put("externalComponent", createExternalComponent());
180
+                .put("bottomTabs", createBottomTabs());
194 181
         Options defaultOptions = Options.parse(mockLoader, json);
195 182
         Options options = new Options();
196 183
 
@@ -202,8 +189,7 @@ public class OptionsTest extends BaseTest {
202 189
         JSONObject defaultJson = new JSONObject()
203 190
                 .put("topBar", createOtherTopBar())
204 191
                 .put("fab", createOtherFab())
205
-                .put("bottomTabs", createOtherBottomTabs())
206
-                .put("externalComponent", createExternalComponent());
192
+                .put("bottomTabs", createOtherBottomTabs());
207 193
         Options defaultOptions = Options.parse(mockLoader, defaultJson);
208 194
 
209 195
         JSONObject json = new JSONObject()

+ 61
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ExternalComponentViewControllerTest.java View File

@@ -0,0 +1,61 @@
1
+package com.reactnativenavigation.viewcontrollers;
2
+
3
+import android.app.Activity;
4
+import android.support.v4.app.FragmentActivity;
5
+import android.widget.FrameLayout;
6
+
7
+import com.reactnativenavigation.BaseTest;
8
+import com.reactnativenavigation.parse.ExternalComponent;
9
+import com.reactnativenavigation.parse.Options;
10
+import com.reactnativenavigation.parse.params.Text;
11
+import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
12
+import com.reactnativenavigation.viewcontrollers.externalcomponent.FragmentCreatorMock;
13
+import com.reactnativenavigation.views.ExternalComponentLayout;
14
+
15
+import org.json.JSONObject;
16
+import org.junit.Test;
17
+
18
+import static org.assertj.core.api.Java6Assertions.assertThat;
19
+import static org.mockito.Mockito.spy;
20
+import static org.mockito.Mockito.times;
21
+import static org.mockito.Mockito.verify;
22
+
23
+public class ExternalComponentViewControllerTest extends BaseTest {
24
+    private ExternalComponentViewController uut;
25
+    private FragmentCreatorMock componentCreator;
26
+    private Activity activity;
27
+    private ExternalComponent ec;
28
+
29
+    @Override
30
+    public void beforeEach() {
31
+        componentCreator = spy(new FragmentCreatorMock());
32
+        activity = newActivity();
33
+        ec = createExternalComponent();
34
+        uut = spy(new ExternalComponentViewController(activity,
35
+                "fragmentId",
36
+                ec,
37
+                componentCreator,
38
+                new Options())
39
+        );
40
+    }
41
+
42
+    private ExternalComponent createExternalComponent() {
43
+        ExternalComponent component = new ExternalComponent();
44
+        component.name = new Text("fragmentComponent");
45
+        component.passProps = new JSONObject();
46
+        return component;
47
+    }
48
+
49
+    @Test
50
+    public void createView_returnsFrameLayout() throws Exception {
51
+        ExternalComponentLayout view = uut.getView();
52
+        assertThat(FrameLayout.class.isAssignableFrom(view.getClass())).isTrue();
53
+    }
54
+
55
+    @Test
56
+    public void createView_createsExternalComponent() throws Exception {
57
+        ExternalComponentLayout view = uut.getView();
58
+        verify(componentCreator, times(1)).create((FragmentActivity) activity, ec.passProps);
59
+        assertThat(view.getChildCount()).isGreaterThan(0);
60
+    }
61
+}

+ 33
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/externalcomponent/FragmentCreatorMock.java View File

@@ -0,0 +1,33 @@
1
+package com.reactnativenavigation.viewcontrollers.externalcomponent;
2
+
3
+import android.app.Activity;
4
+import android.app.FragmentManager;
5
+import android.app.FragmentTransaction;
6
+import android.support.v4.app.FragmentActivity;
7
+import android.widget.FrameLayout;
8
+
9
+import com.reactnativenavigation.R;
10
+
11
+import org.json.JSONObject;
12
+
13
+public class FragmentCreatorMock implements ExternalComponentCreator {
14
+    @Override
15
+    public ExternalComponent create(FragmentActivity activity, JSONObject props) {
16
+        return createContent(activity);
17
+    }
18
+
19
+    private ExternalComponent createContent(Activity activity) {
20
+        FrameLayout content = new FrameLayout(activity) {
21
+            @Override
22
+            protected void onAttachedToWindow() {
23
+                super.onAttachedToWindow();
24
+                FragmentManager fm = activity.getFragmentManager();
25
+                FragmentTransaction ft = fm.beginTransaction();
26
+                ft.add(R.id.fragment_screen_content, new SomeFragment());
27
+                ft.commitAllowingStateLoss();
28
+            }
29
+        };
30
+        content.setId(R.id.fragment_screen_content);
31
+        return () -> content;
32
+    }
33
+}

+ 8
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/externalcomponent/SomeFragment.java View File

@@ -0,0 +1,8 @@
1
+package com.reactnativenavigation.viewcontrollers.externalcomponent;
2
+
3
+import android.app.Fragment;
4
+
5
+public class SomeFragment extends Fragment {
6
+    public SomeFragment() {
7
+    }
8
+}

+ 1
- 1
lib/src/commands/LayoutTreeParser.ts View File

@@ -103,7 +103,7 @@ export class LayoutTreeParser {
103 103
     return {
104 104
       id: api.id,
105 105
       type: LayoutType.ExternalComponent,
106
-      data: { name: api.className, options: api.options, passProps: api.passProps },
106
+      data: { name: api.name, options: api.options, passProps: api.passProps },
107 107
       children: []
108 108
     };
109 109
   }

+ 49
- 0
playground/android/app/src/main/java/com/reactnativenavigation/playground/FragmentComponent.java View File

@@ -0,0 +1,49 @@
1
+package com.reactnativenavigation.playground;
2
+
3
+import android.os.Bundle;
4
+import android.support.annotation.NonNull;
5
+import android.support.v4.app.FragmentActivity;
6
+import android.support.v4.app.FragmentManager;
7
+import android.support.v4.app.FragmentTransaction;
8
+import android.view.View;
9
+import android.widget.FrameLayout;
10
+
11
+import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponent;
12
+
13
+import org.json.JSONObject;
14
+
15
+public class FragmentComponent implements ExternalComponent {
16
+    private final FrameLayout content;
17
+
18
+    FragmentComponent(FragmentActivity activity, JSONObject props) {
19
+        content = new FrameLayout(activity) {
20
+            @Override
21
+            protected void onAttachedToWindow() {
22
+                super.onAttachedToWindow();
23
+                addFragmentAfterContainerIsAttached(activity, props);
24
+            }
25
+        };
26
+        content.setId(R.id.fragment_screen_content);
27
+    }
28
+
29
+    private void addFragmentAfterContainerIsAttached(FragmentActivity activity, JSONObject props) {
30
+        FragmentManager fm = activity.getSupportFragmentManager();
31
+        FragmentTransaction transaction = fm.beginTransaction();
32
+        transaction.add(R.id.fragment_screen_content, createFragment(props));
33
+        transaction.commitAllowingStateLoss();
34
+    }
35
+
36
+    @NonNull
37
+    private FragmentScreen createFragment(JSONObject props) {
38
+        FragmentScreen fragment = new FragmentScreen();
39
+        Bundle args = new Bundle();
40
+        args.putString("text", props.optString("text", ""));
41
+        fragment.setArguments(args);
42
+        return fragment;
43
+    }
44
+
45
+    @Override
46
+    public View asView() {
47
+        return content;
48
+    }
49
+}

+ 15
- 0
playground/android/app/src/main/java/com/reactnativenavigation/playground/FragmentCreator.java View File

@@ -0,0 +1,15 @@
1
+package com.reactnativenavigation.playground;
2
+
3
+import android.support.v4.app.FragmentActivity;
4
+
5
+import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponent;
6
+import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;
7
+
8
+import org.json.JSONObject;
9
+
10
+public class FragmentCreator implements ExternalComponentCreator {
11
+    @Override
12
+    public ExternalComponent create(FragmentActivity activity, JSONObject props) {
13
+        return new FragmentComponent(activity, props);
14
+    }
15
+}

+ 19
- 0
playground/android/app/src/main/java/com/reactnativenavigation/playground/FragmentScreen.java View File

@@ -0,0 +1,19 @@
1
+package com.reactnativenavigation.playground;
2
+
3
+import android.os.Bundle;
4
+import android.support.annotation.Nullable;
5
+import android.support.v4.app.Fragment;
6
+import android.view.LayoutInflater;
7
+import android.view.View;
8
+import android.view.ViewGroup;
9
+import android.widget.TextView;
10
+
11
+public class FragmentScreen extends Fragment {
12
+    @Nullable
13
+    @Override
14
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
15
+        View view = inflater.inflate(R.layout.fragment_screen, container, false);
16
+        ((TextView) view.findViewById(R.id.text)).setText(getArguments().getString("text"));
17
+        return view;
18
+    }
19
+}

+ 10
- 4
playground/android/app/src/main/java/com/reactnativenavigation/playground/MainApplication.java View File

@@ -1,14 +1,20 @@
1 1
 package com.reactnativenavigation.playground;
2 2
 
3
-import android.support.annotation.*;
3
+import android.support.annotation.Nullable;
4 4
 
5
-import com.facebook.react.*;
6
-import com.reactnativenavigation.*;
5
+import com.facebook.react.ReactPackage;
6
+import com.reactnativenavigation.NavigationApplication;
7 7
 
8
-import java.util.*;
8
+import java.util.List;
9 9
 
10 10
 public class MainApplication extends NavigationApplication {
11 11
 
12
+    @Override
13
+    public void onCreate() {
14
+        super.onCreate();
15
+        registerExternalComponent("RNNCustomComponent", new FragmentCreator());
16
+    }
17
+
12 18
     @Override
13 19
     public boolean isDebug() {
14 20
         return BuildConfig.DEBUG;

+ 13
- 0
playground/android/app/src/main/res/layout/fragment_screen.xml View File

@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+                android:layout_width="match_parent"
4
+                android:layout_height="match_parent"
5
+                android:background="@android:color/holo_green_light">
6
+
7
+    <TextView
8
+        android:id="@+id/text"
9
+        android:layout_width="wrap_content"
10
+        android:layout_height="wrap_content"
11
+        android:layout_centerInParent="true"
12
+        android:text="@string/app_name"/>
13
+</RelativeLayout>

+ 5
- 2
playground/src/screens/WelcomeScreen.js View File

@@ -41,7 +41,7 @@ class WelcomeScreen extends Component {
41 41
         <Button title='Static Lifecycle Events' testID={testIDs.PUSH_STATIC_LIFECYCLE_BUTTON} onPress={this.onClickShowStaticLifecycleOverlay} />
42 42
         <Button title='Push' testID={testIDs.PUSH_BUTTON} onPress={this.onClickPush} />
43 43
         <Button title='Push Options Screen' testID={testIDs.PUSH_OPTIONS_BUTTON} onPress={this.onClickPushOptionsScreen} />
44
-        <Button title='Push Native Component' testID={testIDs.PUSH_NATIVE_COMPONENT_BUTTON} onPress={this.onClickPushExternalComponent} />
44
+        <Button title='Push External Component' testID={testIDs.PUSH_EXTERNAL_COMPONENT_BUTTON} onPress={this.onClickPushExternalComponent} />
45 45
         {Platform.OS === 'android' && <Button title='Push Top Tabs screen' testID={testIDs.PUSH_TOP_TABS_BUTTON} onPress={this.onClickPushTopTabsScreen} />}
46 46
         {Platform.OS === 'android' && <Button title='Back Handler' testID={testIDs.BACK_HANDLER_BUTTON} onPress={this.onClickBackHandler} />}
47 47
         <Button title='Show Modal' testID={testIDs.SHOW_MODAL_BUTTON} onPress={this.onClickShowModal} />
@@ -239,7 +239,10 @@ class WelcomeScreen extends Component {
239 239
   async onClickPushExternalComponent() {
240 240
     await Navigation.push(this.props.componentId, {
241 241
       externalComponent: {
242
-        className: 'RNNCustomViewController',
242
+        name: 'RNNCustomComponent',
243
+        passProps: {
244
+          text: 'This is an external component'
245
+        },
243 246
         options: {
244 247
           topBar: {
245 248
             title: 'pushed',

+ 1
- 1
playground/src/testIDs.js View File

@@ -53,7 +53,7 @@ module.exports = {
53 53
   OK_BUTTON: `OK_BUTTON`,
54 54
   MODAL_WITH_STACK_BUTTON: `MODAL_WITH_STACK_BUTTON`,
55 55
   CUSTOM_TRANSITION_BUTTON: `CUSTOM_TRANSITION_BUTTON`,
56
-  PUSH_NATIVE_COMPONENT_BUTTON: `PUSH_NATIVE_COMPONENT_BUTTON`,
56
+  PUSH_EXTERNAL_COMPONENT_BUTTON: `PUSH_EXTERNAL_COMPONENT_BUTTON`,
57 57
 
58 58
   // Elements
59 59
   SCROLLVIEW_ELEMENT: `SCROLLVIEW_ELEMENT`,