Browse Source

Component type (#5820)

Send componentType field in componentDidAppear and componentDidDisappear events.

The new field is either:
- TopBarButton
- TopBarTitle
- TopBarBackground
- Component
Guy Carmeli 5 years ago
parent
commit
3878b683cc
No account linked to committer's email address
72 changed files with 549 additions and 292 deletions
  1. 24
    4
      e2e/StaticLifecycleEvents.test.js
  2. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java
  3. 1
    0
      lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java
  4. 3
    2
      lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationReactInitializer.java
  5. 1
    2
      lib/android/app/src/main/java/com/reactnativenavigation/react/ReactComponentViewCreator.java
  6. 8
    7
      lib/android/app/src/main/java/com/reactnativenavigation/react/ReactView.java
  7. 18
    0
      lib/android/app/src/main/java/com/reactnativenavigation/react/events/ComponentType.java
  8. 6
    8
      lib/android/app/src/main/java/com/reactnativenavigation/react/events/EventEmitter.java
  9. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/utils/NativeCommandListener.java
  10. 0
    4
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/IReactView.java
  11. 9
    7
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/TitleBarButtonController.java
  12. 3
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/TitleBarReactViewController.java
  13. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java
  14. 7
    5
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java
  15. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/modal/ModalStack.java
  16. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/navigator/Navigator.java
  17. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java
  18. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerBuilder.java
  19. 3
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/topbar/TopBarBackgroundViewController.java
  20. 6
    7
      lib/android/app/src/main/java/com/reactnativenavigation/views/ComponentLayout.java
  21. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/views/ComponentViewCreator.java
  22. 1
    1
      lib/android/app/src/test/java/com/reactnativenavigation/TestUtils.java
  23. 0
    10
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleOverlay.java
  24. 0
    10
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleViewController.java
  25. 6
    6
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestComponentLayout.java
  26. 2
    2
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestComponentViewCreator.java
  27. 17
    13
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestReactView.java
  28. 4
    3
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/TopBarButtonCreatorMock.java
  29. 1
    1
      lib/android/app/src/test/java/com/reactnativenavigation/utils/NativeCommandListenerTest.java
  30. 7
    5
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ExternalComponentViewControllerTest.java
  31. 10
    8
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java
  32. 1
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsControllerTest.java
  33. 1
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalStackTest.java
  34. 1
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/navigator/NavigatorTest.java
  35. 1
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java
  36. 4
    0
      lib/ios/RNNBasePresenter.h
  37. 8
    0
      lib/ios/RNNBasePresenter.m
  38. 1
    1
      lib/ios/RNNBridgeManager.m
  39. 25
    3
      lib/ios/RNNComponentPresenter.m
  40. 9
    10
      lib/ios/RNNComponentViewController.m
  41. 11
    5
      lib/ios/RNNComponentViewCreator.h
  42. 2
    3
      lib/ios/RNNEventEmitter.h
  43. 6
    4
      lib/ios/RNNEventEmitter.m
  44. 4
    0
      lib/ios/RNNNavigationButtons.h
  45. 27
    1
      lib/ios/RNNNavigationButtons.m
  46. 5
    0
      lib/ios/RNNReactBackgroundView.h
  47. 9
    0
      lib/ios/RNNReactBackgroundView.m
  48. 5
    0
      lib/ios/RNNReactButtonView.h
  49. 9
    0
      lib/ios/RNNReactButtonView.m
  50. 3
    2
      lib/ios/RNNReactComponentRegistry.h
  51. 20
    12
      lib/ios/RNNReactComponentRegistry.m
  52. 2
    2
      lib/ios/RNNReactRootViewCreator.h
  53. 26
    17
      lib/ios/RNNReactRootViewCreator.m
  54. 9
    0
      lib/ios/RNNReactTitleView.h
  55. 44
    0
      lib/ios/RNNReactTitleView.m
  56. 15
    5
      lib/ios/RNNReactView.h
  57. 29
    35
      lib/ios/RNNReactView.m
  58. 15
    43
      lib/ios/RNNStackPresenter.m
  59. 0
    3
      lib/ios/RNNTopBarOptions.h
  60. 0
    1
      lib/ios/RNNTopBarOptions.m
  61. 3
    0
      lib/ios/RNNUIBarButtonItem.h
  62. 12
    0
      lib/ios/RNNUIBarButtonItem.m
  63. 24
    0
      lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj
  64. 4
    0
      lib/ios/UIViewController+LayoutProtocol.h
  65. 11
    1
      lib/ios/UIViewController+LayoutProtocol.m
  66. 15
    14
      lib/src/events/ComponentEventsObserver.test.tsx
  67. 4
    0
      lib/src/interfaces/ComponentEvents.ts
  68. 6
    6
      playground/ios/NavigationTests/RNNComponentPresenterTest.m
  69. 1
    1
      playground/ios/NavigationTests/RNNTestRootViewCreator.m
  70. 9
    1
      playground/src/screens/PushedScreen.js
  71. 21
    1
      playground/src/screens/StaticLifecycleOverlay.js
  72. 1
    0
      playground/src/testIDs.js

+ 24
- 4
e2e/StaticLifecycleEvents.test.js View File

11
   });
11
   });
12
 
12
 
13
   it('didAppear didDisappear', async () => {
13
   it('didAppear didDisappear', async () => {
14
-    await expect(elementByLabel('componentDidAppear | EventsOverlay')).toBeVisible();
14
+    await expect(elementByLabel('componentDidAppear | EventsOverlay | Component')).toBeVisible();
15
     await elementById(TestIDs.PUSH_BTN).tap();
15
     await elementById(TestIDs.PUSH_BTN).tap();
16
-    await expect(elementByLabel('componentDidAppear | Pushed')).toBeVisible();
17
-    await expect(elementByLabel('componentDidDisappear | EventsScreen')).toBeVisible();
16
+    await expect(elementByLabel('componentDidAppear | Pushed | Component')).toBeVisible();
17
+    await expect(elementByLabel('componentDidDisappear | EventsScreen | Component')).toBeVisible();
18
   });
18
   });
19
 
19
 
20
   it('pushing and popping screen dispatch static event', async () => {
20
   it('pushing and popping screen dispatch static event', async () => {
21
     await expect(elementByLabel('Static Lifecycle Events Overlay')).toBeVisible();
21
     await expect(elementByLabel('Static Lifecycle Events Overlay')).toBeVisible();
22
-    await expect(elementByLabel('componentDidAppear | EventsOverlay')).toBeVisible();
22
+    await expect(elementByLabel('componentDidAppear | EventsOverlay | Component')).toBeVisible();
23
     await elementById(TestIDs.PUSH_BTN).tap();
23
     await elementById(TestIDs.PUSH_BTN).tap();
24
     await expect(elementByLabel('push')).toBeVisible();
24
     await expect(elementByLabel('push')).toBeVisible();
25
     await elementById(TestIDs.POP_BTN).tap();
25
     await elementById(TestIDs.POP_BTN).tap();
40
     await expect(elementByLabel('Overlay Unmounted')).toBeVisible();
40
     await expect(elementByLabel('Overlay Unmounted')).toBeVisible();
41
     await elementByLabel('OK').tap();
41
     await elementByLabel('OK').tap();
42
   });
42
   });
43
+
44
+  it('top bar buttons didAppear didDisappear', async () => {
45
+    await elementById(TestIDs.PUSH_BTN).tap();
46
+    await elementById(TestIDs.PUSH_OPTIONS_BUTTON).tap();
47
+    await elementById(TestIDs.CLEAR_OVERLAY_EVENTS_BTN).tap();
48
+    await elementById(TestIDs.GOTO_BUTTONS_SCREEN).tap();
49
+    await expect(elementByLabel('componentDidAppear | CustomRoundedButton | TopBarButton')).toBeVisible();
50
+    await elementById(TestIDs.RESET_BUTTONS).tap();
51
+    await expect(elementByLabel('componentDidDisappear | CustomRoundedButton | TopBarButton')).toBeVisible();
52
+  });
53
+
54
+  it('top bar title didAppear didDisappear', async () => {
55
+    await elementById(TestIDs.PUSH_BTN).tap();
56
+    await elementById(TestIDs.PUSH_OPTIONS_BUTTON).tap();
57
+    await elementById(TestIDs.CLEAR_OVERLAY_EVENTS_BTN).tap();
58
+    await elementById(TestIDs.SET_REACT_TITLE_VIEW).tap();
59
+    await expect(elementByLabel('componentDidAppear | ReactTitleView | TopBarTitle')).toBeVisible();
60
+    await elementById(TestIDs.PUSH_BTN).tap();
61
+    await expect(elementByLabel('componentDidDisappear | ReactTitleView | TopBarTitle')).toBeVisible();
62
+  });
43
 });
63
 });

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

11
 import com.reactnativenavigation.presentation.RenderChecker;
11
 import com.reactnativenavigation.presentation.RenderChecker;
12
 import com.reactnativenavigation.presentation.SideMenuPresenter;
12
 import com.reactnativenavigation.presentation.SideMenuPresenter;
13
 import com.reactnativenavigation.presentation.StackPresenter;
13
 import com.reactnativenavigation.presentation.StackPresenter;
14
-import com.reactnativenavigation.react.EventEmitter;
14
+import com.reactnativenavigation.react.events.EventEmitter;
15
 import com.reactnativenavigation.utils.Assertions;
15
 import com.reactnativenavigation.utils.Assertions;
16
 import com.reactnativenavigation.utils.ImageLoader;
16
 import com.reactnativenavigation.utils.ImageLoader;
17
 import com.reactnativenavigation.utils.TypefaceLoader;
17
 import com.reactnativenavigation.utils.TypefaceLoader;

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

1
 package com.reactnativenavigation.react;
1
 package com.reactnativenavigation.react;
2
 
2
 
3
+import com.reactnativenavigation.react.events.EventEmitter;
3
 import com.reactnativenavigation.utils.LaunchArgsParser;
4
 import com.reactnativenavigation.utils.LaunchArgsParser;
4
 import com.facebook.react.ReactInstanceManager;
5
 import com.facebook.react.ReactInstanceManager;
5
 import com.facebook.react.bridge.Arguments;
6
 import com.facebook.react.bridge.Arguments;

+ 3
- 2
lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationReactInitializer.java View File

1
 package com.reactnativenavigation.react;
1
 package com.reactnativenavigation.react;
2
 
2
 
3
-import androidx.annotation.NonNull;
4
-
5
 import com.facebook.react.ReactInstanceManager;
3
 import com.facebook.react.ReactInstanceManager;
6
 import com.facebook.react.bridge.ReactContext;
4
 import com.facebook.react.bridge.ReactContext;
7
 import com.reactnativenavigation.NavigationActivity;
5
 import com.reactnativenavigation.NavigationActivity;
6
+import com.reactnativenavigation.react.events.EventEmitter;
7
+
8
+import androidx.annotation.NonNull;
8
 
9
 
9
 public class NavigationReactInitializer implements ReactInstanceManager.ReactInstanceEventListener {
10
 public class NavigationReactInitializer implements ReactInstanceManager.ReactInstanceEventListener {
10
 
11
 

+ 1
- 2
lib/android/app/src/main/java/com/reactnativenavigation/react/ReactComponentViewCreator.java View File

4
 
4
 
5
 import com.facebook.react.ReactInstanceManager;
5
 import com.facebook.react.ReactInstanceManager;
6
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
6
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
7
-import com.reactnativenavigation.viewcontrollers.IReactView;
8
 
7
 
9
 public class ReactComponentViewCreator implements ReactViewCreator {
8
 public class ReactComponentViewCreator implements ReactViewCreator {
10
 	private ReactInstanceManager reactInstanceManager;
9
 	private ReactInstanceManager reactInstanceManager;
14
 	}
13
 	}
15
 
14
 
16
 	@Override
15
 	@Override
17
-	public IReactView create(final Activity activity, final String componentId, final String componentName) {
16
+	public ReactView create(final Activity activity, final String componentId, final String componentName) {
18
 		return new ReactView(activity, reactInstanceManager, componentId, componentName);
17
 		return new ReactView(activity, reactInstanceManager, componentId, componentName);
19
 	}
18
 	}
20
 }
19
 }

+ 8
- 7
lib/android/app/src/main/java/com/reactnativenavigation/react/ReactView.java View File

3
 import android.annotation.SuppressLint;
3
 import android.annotation.SuppressLint;
4
 import android.content.Context;
4
 import android.content.Context;
5
 import android.os.Bundle;
5
 import android.os.Bundle;
6
-import androidx.annotation.RestrictTo;
7
 import android.view.MotionEvent;
6
 import android.view.MotionEvent;
8
 
7
 
9
 import com.facebook.react.ReactInstanceManager;
8
 import com.facebook.react.ReactInstanceManager;
13
 import com.facebook.react.uimanager.UIManagerModule;
12
 import com.facebook.react.uimanager.UIManagerModule;
14
 import com.facebook.react.uimanager.events.EventDispatcher;
13
 import com.facebook.react.uimanager.events.EventDispatcher;
15
 import com.reactnativenavigation.interfaces.ScrollEventListener;
14
 import com.reactnativenavigation.interfaces.ScrollEventListener;
15
+import com.reactnativenavigation.react.events.ComponentType;
16
+import com.reactnativenavigation.react.events.EventEmitter;
16
 import com.reactnativenavigation.viewcontrollers.IReactView;
17
 import com.reactnativenavigation.viewcontrollers.IReactView;
17
 import com.reactnativenavigation.views.Renderable;
18
 import com.reactnativenavigation.views.Renderable;
18
 import com.reactnativenavigation.views.element.Element;
19
 import com.reactnativenavigation.views.element.Element;
20
 import java.util.ArrayList;
21
 import java.util.ArrayList;
21
 import java.util.List;
22
 import java.util.List;
22
 
23
 
24
+import androidx.annotation.RestrictTo;
25
+
23
 @SuppressLint("ViewConstructor")
26
 @SuppressLint("ViewConstructor")
24
 public class ReactView extends ReactRootView implements IReactView, Renderable {
27
 public class ReactView extends ReactRootView implements IReactView, Renderable {
25
 
28
 
64
 		unmountReactApplication();
67
 		unmountReactApplication();
65
 	}
68
 	}
66
 
69
 
67
-	@Override
68
-	public void sendComponentStart() {
70
+	public void sendComponentStart(ComponentType type) {
69
         ReactContext currentReactContext = reactInstanceManager.getCurrentReactContext();
71
         ReactContext currentReactContext = reactInstanceManager.getCurrentReactContext();
70
         if (currentReactContext != null) {
72
         if (currentReactContext != null) {
71
-            new EventEmitter(currentReactContext).emitComponentDidAppear(componentId, componentName);
73
+            new EventEmitter(currentReactContext).emitComponentDidAppear(componentId, componentName, type);
72
         }
74
         }
73
 	}
75
 	}
74
 
76
 
75
-	@Override
76
-	public void sendComponentStop() {
77
+	public void sendComponentStop(ComponentType type) {
77
         ReactContext currentReactContext = reactInstanceManager.getCurrentReactContext();
78
         ReactContext currentReactContext = reactInstanceManager.getCurrentReactContext();
78
         if (currentReactContext != null) {
79
         if (currentReactContext != null) {
79
-            new EventEmitter(currentReactContext).emitComponentDidDisappear(componentId, componentName);
80
+            new EventEmitter(currentReactContext).emitComponentDidDisappear(componentId, componentName, type);
80
         }
81
         }
81
 	}
82
 	}
82
 
83
 

+ 18
- 0
lib/android/app/src/main/java/com/reactnativenavigation/react/events/ComponentType.java View File

1
+package com.reactnativenavigation.react.events;
2
+
3
+public enum ComponentType {
4
+    Component("Component"),
5
+    Button("TopBarButton"),
6
+    Title("TopBarTitle"),
7
+    Background("TopBarBackground");
8
+
9
+    private String name;
10
+
11
+    public String getName() {
12
+        return name;
13
+    }
14
+
15
+    ComponentType(String name) {
16
+        this.name = name;
17
+    }
18
+    }

lib/android/app/src/main/java/com/reactnativenavigation/react/EventEmitter.java → lib/android/app/src/main/java/com/reactnativenavigation/react/events/EventEmitter.java View File

1
-package com.reactnativenavigation.react;
1
+package com.reactnativenavigation.react.events;
2
 
2
 
3
 import android.util.Log;
3
 import android.util.Log;
4
 
4
 
28
     }
28
     }
29
 
29
 
30
     public void appLaunched() {
30
     public void appLaunched() {
31
-        emit(AppLaunched);
31
+        emit(EventEmitter.AppLaunched, Arguments.createMap());
32
     }
32
     }
33
 
33
 
34
-    public void emitComponentDidDisappear(String id, String componentName) {
34
+    public void emitComponentDidDisappear(String id, String componentName, ComponentType type) {
35
         WritableMap event = Arguments.createMap();
35
         WritableMap event = Arguments.createMap();
36
         event.putString("componentId", id);
36
         event.putString("componentId", id);
37
         event.putString("componentName", componentName);
37
         event.putString("componentName", componentName);
38
+        event.putString("componentType", type.getName());
38
         emit(ComponentDidDisappear, event);
39
         emit(ComponentDidDisappear, event);
39
     }
40
     }
40
 
41
 
41
-    public void emitComponentDidAppear(String id, String componentName) {
42
+    public void emitComponentDidAppear(String id, String componentName, ComponentType type) {
42
         WritableMap event = Arguments.createMap();
43
         WritableMap event = Arguments.createMap();
43
         event.putString("componentId", id);
44
         event.putString("componentId", id);
44
         event.putString("componentName", componentName);
45
         event.putString("componentName", componentName);
46
+        event.putString("componentType", type.getName());
45
         emit(ComponentDidAppear, event);
47
         emit(ComponentDidAppear, event);
46
     }
48
     }
47
 
49
 
80
         emit(ScreenPopped, event);
82
         emit(ScreenPopped, event);
81
     }
83
     }
82
 
84
 
83
-    private void emit(String eventName) {
84
-        emit(eventName, Arguments.createMap());
85
-    }
86
-
87
     private void emit(String eventName, WritableMap data) {
85
     private void emit(String eventName, WritableMap data) {
88
         if (reactContext == null) {
86
         if (reactContext == null) {
89
             Log.e("RNN", "Could not send event " + eventName + ". React context is null!");
87
             Log.e("RNN", "Could not send event " + eventName + ". React context is null!");

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/utils/NativeCommandListener.java View File

3
 import androidx.annotation.Nullable;
3
 import androidx.annotation.Nullable;
4
 
4
 
5
 import com.facebook.react.bridge.Promise;
5
 import com.facebook.react.bridge.Promise;
6
-import com.reactnativenavigation.react.EventEmitter;
6
+import com.reactnativenavigation.react.events.EventEmitter;
7
 
7
 
8
 public class NativeCommandListener extends CommandListenerAdapter {
8
 public class NativeCommandListener extends CommandListenerAdapter {
9
     private String commandId;
9
     private String commandId;

+ 0
- 4
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/IReactView.java View File

14
 
14
 
15
     View asView();
15
     View asView();
16
 
16
 
17
-    void sendComponentStart();
18
-
19
-    void sendComponentStop();
20
-
21
     void sendOnNavigationButtonPressed(String buttonId);
17
     void sendOnNavigationButtonPressed(String buttonId);
22
 
18
 
23
     ScrollEventListener getScrollEventListener();
19
     ScrollEventListener getScrollEventListener();

+ 9
- 7
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/TitleBarButtonController.java View File

1
-    package com.reactnativenavigation.viewcontrollers;
1
+package com.reactnativenavigation.viewcontrollers;
2
 
2
 
3
 import android.annotation.SuppressLint;
3
 import android.annotation.SuppressLint;
4
 import android.app.Activity;
4
 import android.app.Activity;
5
 import android.graphics.Color;
5
 import android.graphics.Color;
6
 import android.graphics.drawable.Drawable;
6
 import android.graphics.drawable.Drawable;
7
-import androidx.annotation.NonNull;
8
-import androidx.annotation.RestrictTo;
9
-import androidx.appcompat.widget.ActionMenuView;
10
-import androidx.appcompat.widget.Toolbar;
11
 import android.view.Menu;
7
 import android.view.Menu;
12
 import android.view.MenuItem;
8
 import android.view.MenuItem;
13
 import android.widget.ImageButton;
9
 import android.widget.ImageButton;
16
 import com.reactnativenavigation.parse.Options;
12
 import com.reactnativenavigation.parse.Options;
17
 import com.reactnativenavigation.parse.params.Button;
13
 import com.reactnativenavigation.parse.params.Button;
18
 import com.reactnativenavigation.parse.params.Text;
14
 import com.reactnativenavigation.parse.params.Text;
15
+import com.reactnativenavigation.react.events.ComponentType;
19
 import com.reactnativenavigation.utils.ArrayUtils;
16
 import com.reactnativenavigation.utils.ArrayUtils;
20
 import com.reactnativenavigation.utils.ButtonPresenter;
17
 import com.reactnativenavigation.utils.ButtonPresenter;
21
 import com.reactnativenavigation.utils.ImageLoader;
18
 import com.reactnativenavigation.utils.ImageLoader;
28
 import java.util.Collections;
25
 import java.util.Collections;
29
 import java.util.List;
26
 import java.util.List;
30
 
27
 
28
+import androidx.annotation.NonNull;
29
+import androidx.annotation.RestrictTo;
30
+import androidx.appcompat.widget.ActionMenuView;
31
+import androidx.appcompat.widget.Toolbar;
32
+
31
 public class TitleBarButtonController extends ViewController<TitleBarReactButtonView> implements MenuItem.OnMenuItemClickListener {
33
 public class TitleBarButtonController extends ViewController<TitleBarReactButtonView> implements MenuItem.OnMenuItemClickListener {
32
     public interface OnClickListener {
34
     public interface OnClickListener {
33
         void onPress(String buttonId);
35
         void onPress(String buttonId);
69
     @SuppressLint("MissingSuperCall")
71
     @SuppressLint("MissingSuperCall")
70
     @Override
72
     @Override
71
     public void onViewAppeared() {
73
     public void onViewAppeared() {
72
-        getView().sendComponentStart();
74
+        getView().sendComponentStart(ComponentType.Button);
73
     }
75
     }
74
 
76
 
75
     @SuppressLint("MissingSuperCall")
77
     @SuppressLint("MissingSuperCall")
76
     @Override
78
     @Override
77
     public void onViewDisappear() {
79
     public void onViewDisappear() {
78
-        getView().sendComponentStop();
80
+        getView().sendComponentStop(ComponentType.Button);
79
     }
81
     }
80
 
82
 
81
     @Override
83
     @Override

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

4
 
4
 
5
 import com.reactnativenavigation.parse.Component;
5
 import com.reactnativenavigation.parse.Component;
6
 import com.reactnativenavigation.parse.Options;
6
 import com.reactnativenavigation.parse.Options;
7
+import com.reactnativenavigation.react.events.ComponentType;
7
 import com.reactnativenavigation.utils.CompatUtils;
8
 import com.reactnativenavigation.utils.CompatUtils;
8
 import com.reactnativenavigation.views.titlebar.TitleBarReactView;
9
 import com.reactnativenavigation.views.titlebar.TitleBarReactView;
9
 import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
10
 import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
23
         super.onViewAppeared();
24
         super.onViewAppeared();
24
         if (!isDestroyed()) {
25
         if (!isDestroyed()) {
25
             runOnPreDraw(view -> view.setLayoutParams(view.getLayoutParams()));
26
             runOnPreDraw(view -> view.setLayoutParams(view.getLayoutParams()));
26
-            getView().sendComponentStart();
27
+            getView().sendComponentStart(ComponentType.Title);
27
         }
28
         }
28
     }
29
     }
29
 
30
 
30
     @Override
31
     @Override
31
     public void onViewDisappear() {
32
     public void onViewDisappear() {
32
-        getView().sendComponentStop();
33
+        getView().sendComponentStop(ComponentType.Title);
33
         super.onViewDisappear();
34
         super.onViewDisappear();
34
     }
35
     }
35
 
36
 

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

12
 import com.reactnativenavigation.presentation.BottomTabPresenter;
12
 import com.reactnativenavigation.presentation.BottomTabPresenter;
13
 import com.reactnativenavigation.presentation.BottomTabsPresenter;
13
 import com.reactnativenavigation.presentation.BottomTabsPresenter;
14
 import com.reactnativenavigation.presentation.Presenter;
14
 import com.reactnativenavigation.presentation.Presenter;
15
-import com.reactnativenavigation.react.EventEmitter;
15
+import com.reactnativenavigation.react.events.EventEmitter;
16
 import com.reactnativenavigation.utils.CommandListener;
16
 import com.reactnativenavigation.utils.CommandListener;
17
 import com.reactnativenavigation.utils.ImageLoader;
17
 import com.reactnativenavigation.utils.ImageLoader;
18
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
18
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;

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

1
 package com.reactnativenavigation.viewcontrollers.externalcomponent;
1
 package com.reactnativenavigation.viewcontrollers.externalcomponent;
2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
-import androidx.fragment.app.FragmentActivity;
5
-import androidx.core.view.ViewCompat;
6
 import android.view.View;
4
 import android.view.View;
7
 
5
 
8
 import com.facebook.react.ReactInstanceManager;
6
 import com.facebook.react.ReactInstanceManager;
9
 import com.reactnativenavigation.parse.ExternalComponent;
7
 import com.reactnativenavigation.parse.ExternalComponent;
10
 import com.reactnativenavigation.parse.Options;
8
 import com.reactnativenavigation.parse.Options;
11
 import com.reactnativenavigation.presentation.ExternalComponentPresenter;
9
 import com.reactnativenavigation.presentation.ExternalComponentPresenter;
12
-import com.reactnativenavigation.react.EventEmitter;
10
+import com.reactnativenavigation.react.events.ComponentType;
11
+import com.reactnativenavigation.react.events.EventEmitter;
13
 import com.reactnativenavigation.utils.CoordinatorLayoutUtils;
12
 import com.reactnativenavigation.utils.CoordinatorLayoutUtils;
14
 import com.reactnativenavigation.utils.StatusBarUtils;
13
 import com.reactnativenavigation.utils.StatusBarUtils;
15
 import com.reactnativenavigation.viewcontrollers.NoOpYellowBoxDelegate;
14
 import com.reactnativenavigation.viewcontrollers.NoOpYellowBoxDelegate;
17
 import com.reactnativenavigation.views.BehaviourDelegate;
16
 import com.reactnativenavigation.views.BehaviourDelegate;
18
 import com.reactnativenavigation.views.ExternalComponentLayout;
17
 import com.reactnativenavigation.views.ExternalComponentLayout;
19
 
18
 
19
+import androidx.core.view.ViewCompat;
20
+import androidx.fragment.app.FragmentActivity;
21
+
20
 import static com.reactnativenavigation.utils.ObjectUtils.perform;
22
 import static com.reactnativenavigation.utils.ObjectUtils.perform;
21
 
23
 
22
 public class ExternalComponentViewController extends ViewController<ExternalComponentLayout> {
24
 public class ExternalComponentViewController extends ViewController<ExternalComponentLayout> {
60
     @Override
62
     @Override
61
     public void onViewAppeared() {
63
     public void onViewAppeared() {
62
         super.onViewAppeared();
64
         super.onViewAppeared();
63
-        emitter.emitComponentDidAppear(getId(), externalComponent.name.get());
65
+        emitter.emitComponentDidAppear(getId(), externalComponent.name.get(), ComponentType.Component);
64
     }
66
     }
65
 
67
 
66
     @Override
68
     @Override
67
     public void onViewDisappear() {
69
     public void onViewDisappear() {
68
         super.onViewDisappear();
70
         super.onViewDisappear();
69
-        emitter.emitComponentDidDisappear(getId(), externalComponent.name.get());
71
+        emitter.emitComponentDidDisappear(getId(), externalComponent.name.get(), ComponentType.Component);
70
     }
72
     }
71
 
73
 
72
     @Override
74
     @Override

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/modal/ModalStack.java View File

7
 
7
 
8
 import com.reactnativenavigation.anim.ModalAnimator;
8
 import com.reactnativenavigation.anim.ModalAnimator;
9
 import com.reactnativenavigation.parse.Options;
9
 import com.reactnativenavigation.parse.Options;
10
-import com.reactnativenavigation.react.EventEmitter;
10
+import com.reactnativenavigation.react.events.EventEmitter;
11
 import com.reactnativenavigation.utils.CommandListener;
11
 import com.reactnativenavigation.utils.CommandListener;
12
 import com.reactnativenavigation.utils.CommandListenerAdapter;
12
 import com.reactnativenavigation.utils.CommandListenerAdapter;
13
 import com.reactnativenavigation.viewcontrollers.ViewController;
13
 import com.reactnativenavigation.viewcontrollers.ViewController;

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/navigator/Navigator.java View File

8
 import com.reactnativenavigation.presentation.OverlayManager;
8
 import com.reactnativenavigation.presentation.OverlayManager;
9
 import com.reactnativenavigation.presentation.Presenter;
9
 import com.reactnativenavigation.presentation.Presenter;
10
 import com.reactnativenavigation.presentation.RootPresenter;
10
 import com.reactnativenavigation.presentation.RootPresenter;
11
-import com.reactnativenavigation.react.EventEmitter;
11
+import com.reactnativenavigation.react.events.EventEmitter;
12
 import com.reactnativenavigation.utils.CommandListener;
12
 import com.reactnativenavigation.utils.CommandListener;
13
 import com.reactnativenavigation.utils.CommandListenerAdapter;
13
 import com.reactnativenavigation.utils.CommandListenerAdapter;
14
 import com.reactnativenavigation.utils.CompatUtils;
14
 import com.reactnativenavigation.utils.CompatUtils;

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

9
 import com.reactnativenavigation.presentation.Presenter;
9
 import com.reactnativenavigation.presentation.Presenter;
10
 import com.reactnativenavigation.presentation.StackPresenter;
10
 import com.reactnativenavigation.presentation.StackPresenter;
11
 import com.reactnativenavigation.react.Constants;
11
 import com.reactnativenavigation.react.Constants;
12
-import com.reactnativenavigation.react.EventEmitter;
12
+import com.reactnativenavigation.react.events.EventEmitter;
13
 import com.reactnativenavigation.utils.CommandListener;
13
 import com.reactnativenavigation.utils.CommandListener;
14
 import com.reactnativenavigation.utils.CommandListenerAdapter;
14
 import com.reactnativenavigation.utils.CommandListenerAdapter;
15
 import com.reactnativenavigation.utils.CompatUtils;
15
 import com.reactnativenavigation.utils.CompatUtils;

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerBuilder.java View File

6
 import com.reactnativenavigation.parse.Options;
6
 import com.reactnativenavigation.parse.Options;
7
 import com.reactnativenavigation.presentation.Presenter;
7
 import com.reactnativenavigation.presentation.Presenter;
8
 import com.reactnativenavigation.presentation.StackPresenter;
8
 import com.reactnativenavigation.presentation.StackPresenter;
9
-import com.reactnativenavigation.react.EventEmitter;
9
+import com.reactnativenavigation.react.events.EventEmitter;
10
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
10
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
11
 import com.reactnativenavigation.viewcontrollers.ViewController;
11
 import com.reactnativenavigation.viewcontrollers.ViewController;
12
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
12
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;

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

4
 
4
 
5
 import com.reactnativenavigation.parse.Component;
5
 import com.reactnativenavigation.parse.Component;
6
 import com.reactnativenavigation.parse.Options;
6
 import com.reactnativenavigation.parse.Options;
7
+import com.reactnativenavigation.react.events.ComponentType;
7
 import com.reactnativenavigation.utils.CompatUtils;
8
 import com.reactnativenavigation.utils.CompatUtils;
8
 import com.reactnativenavigation.viewcontrollers.ViewController;
9
 import com.reactnativenavigation.viewcontrollers.ViewController;
9
 import com.reactnativenavigation.viewcontrollers.YellowBoxDelegate;
10
 import com.reactnativenavigation.viewcontrollers.YellowBoxDelegate;
28
     @Override
29
     @Override
29
     public void onViewAppeared() {
30
     public void onViewAppeared() {
30
         super.onViewAppeared();
31
         super.onViewAppeared();
31
-        getView().sendComponentStart();
32
+        getView().sendComponentStart(ComponentType.Background);
32
     }
33
     }
33
 
34
 
34
     @Override
35
     @Override
35
     public void onViewDisappear() {
36
     public void onViewDisappear() {
36
-        getView().sendComponentStop();
37
+        getView().sendComponentStop(ComponentType.Background);
37
         super.onViewDisappear();
38
         super.onViewDisappear();
38
     }
39
     }
39
 
40
 

+ 6
- 7
lib/android/app/src/main/java/com/reactnativenavigation/views/ComponentLayout.java View File

8
 import com.reactnativenavigation.interfaces.ScrollEventListener;
8
 import com.reactnativenavigation.interfaces.ScrollEventListener;
9
 import com.reactnativenavigation.parse.Options;
9
 import com.reactnativenavigation.parse.Options;
10
 import com.reactnativenavigation.parse.params.Bool;
10
 import com.reactnativenavigation.parse.params.Bool;
11
-import com.reactnativenavigation.viewcontrollers.IReactView;
11
+import com.reactnativenavigation.react.ReactView;
12
+import com.reactnativenavigation.react.events.ComponentType;
12
 import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
13
 import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
13
 import com.reactnativenavigation.views.element.Element;
14
 import com.reactnativenavigation.views.element.Element;
14
 import com.reactnativenavigation.views.touch.OverlayTouchDelegate;
15
 import com.reactnativenavigation.views.touch.OverlayTouchDelegate;
22
 @SuppressLint("ViewConstructor")
23
 @SuppressLint("ViewConstructor")
23
 public class ComponentLayout extends CoordinatorLayout implements ReactComponent, TitleBarButtonController.OnClickListener {
24
 public class ComponentLayout extends CoordinatorLayout implements ReactComponent, TitleBarButtonController.OnClickListener {
24
 
25
 
25
-    private IReactView reactView;
26
+    private ReactView reactView;
26
     private final OverlayTouchDelegate touchDelegate;
27
     private final OverlayTouchDelegate touchDelegate;
27
 
28
 
28
-    public ComponentLayout(Context context, IReactView reactView) {
29
+    public ComponentLayout(Context context, ReactView reactView) {
29
 		super(context);
30
 		super(context);
30
 		this.reactView = reactView;
31
 		this.reactView = reactView;
31
         addView(reactView.asView(), matchParentLP());
32
         addView(reactView.asView(), matchParentLP());
47
         reactView.destroy();
48
         reactView.destroy();
48
     }
49
     }
49
 
50
 
50
-	@Override
51
 	public void sendComponentStart() {
51
 	public void sendComponentStart() {
52
-		reactView.sendComponentStart();
52
+		reactView.sendComponentStart(ComponentType.Component);
53
 	}
53
 	}
54
 
54
 
55
-	@Override
56
 	public void sendComponentStop() {
55
 	public void sendComponentStop() {
57
-		reactView.sendComponentStop();
56
+		reactView.sendComponentStop(ComponentType.Component);
58
 	}
57
 	}
59
 
58
 
60
     public void applyOptions(Options options) {
59
     public void applyOptions(Options options) {

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

4
 
4
 
5
 import com.facebook.react.ReactInstanceManager;
5
 import com.facebook.react.ReactInstanceManager;
6
 import com.reactnativenavigation.react.ReactComponentViewCreator;
6
 import com.reactnativenavigation.react.ReactComponentViewCreator;
7
+import com.reactnativenavigation.react.ReactView;
7
 import com.reactnativenavigation.viewcontrollers.IReactView;
8
 import com.reactnativenavigation.viewcontrollers.IReactView;
8
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
9
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
9
 
10
 
17
 
18
 
18
 	@Override
19
 	@Override
19
 	public IReactView create(Activity activity, String componentId, String componentName) {
20
 	public IReactView create(Activity activity, String componentId, String componentName) {
20
-        IReactView reactView = new ReactComponentViewCreator(instanceManager).create(activity, componentId, componentName);
21
+        ReactView reactView = new ReactComponentViewCreator(instanceManager).create(activity, componentId, componentName);
21
         return new ComponentLayout(activity, reactView);
22
         return new ComponentLayout(activity, reactView);
22
 	}
23
 	}
23
 }
24
 }

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/TestUtils.java View File

12
 import com.reactnativenavigation.parse.params.Bool;
12
 import com.reactnativenavigation.parse.params.Bool;
13
 import com.reactnativenavigation.presentation.RenderChecker;
13
 import com.reactnativenavigation.presentation.RenderChecker;
14
 import com.reactnativenavigation.presentation.StackPresenter;
14
 import com.reactnativenavigation.presentation.StackPresenter;
15
-import com.reactnativenavigation.react.EventEmitter;
15
+import com.reactnativenavigation.react.events.EventEmitter;
16
 import com.reactnativenavigation.utils.ImageLoader;
16
 import com.reactnativenavigation.utils.ImageLoader;
17
 import com.reactnativenavigation.utils.UiUtils;
17
 import com.reactnativenavigation.utils.UiUtils;
18
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
18
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;

+ 0
- 10
lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleOverlay.java View File

36
 
36
 
37
     }
37
     }
38
 
38
 
39
-    @Override
40
-    public void sendComponentStart() {
41
-
42
-    }
43
-
44
-    @Override
45
-    public void sendComponentStop() {
46
-
47
-    }
48
-
49
     @Override
39
     @Override
50
     public void sendOnNavigationButtonPressed(String buttonId) {
40
     public void sendOnNavigationButtonPressed(String buttonId) {
51
 
41
 

+ 0
- 10
lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleViewController.java View File

90
 
90
 
91
         }
91
         }
92
 
92
 
93
-        @Override
94
-        public void sendComponentStart() {
95
-
96
-        }
97
-
98
-        @Override
99
-        public void sendComponentStop() {
100
-
101
-        }
102
-
103
         @Override
93
         @Override
104
         public void sendOnNavigationButtonPressed(String buttonId) {
94
         public void sendOnNavigationButtonPressed(String buttonId) {
105
 
95
 

+ 6
- 6
lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestComponentLayout.java View File

6
 
6
 
7
 import com.reactnativenavigation.interfaces.ScrollEventListener;
7
 import com.reactnativenavigation.interfaces.ScrollEventListener;
8
 import com.reactnativenavigation.parse.Options;
8
 import com.reactnativenavigation.parse.Options;
9
-import com.reactnativenavigation.viewcontrollers.IReactView;
9
+import com.reactnativenavigation.react.ReactView;
10
+import com.reactnativenavigation.react.events.ComponentType;
10
 import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
11
 import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
11
 import com.reactnativenavigation.views.ComponentLayout;
12
 import com.reactnativenavigation.views.ComponentLayout;
12
 
13
 
13
 public class TestComponentLayout extends ComponentLayout implements TitleBarButtonController.OnClickListener {
14
 public class TestComponentLayout extends ComponentLayout implements TitleBarButtonController.OnClickListener {
14
 
15
 
15
-    private IReactView reactView;
16
+    private ReactView reactView;
16
 
17
 
17
-    public TestComponentLayout(final Context context, IReactView reactView) {
18
+    public TestComponentLayout(final Context context, ReactView reactView) {
18
         super(context, reactView);
19
         super(context, reactView);
19
         this.reactView = reactView;
20
         this.reactView = reactView;
20
     }
21
     }
21
 
22
 
22
-
23
     @Override
23
     @Override
24
     public boolean isReady() {
24
     public boolean isReady() {
25
         return false;
25
         return false;
36
 
36
 
37
     @Override
37
     @Override
38
     public void sendComponentStart() {
38
     public void sendComponentStart() {
39
-        reactView.sendComponentStart();
39
+        reactView.sendComponentStart(ComponentType.Component);
40
     }
40
     }
41
 
41
 
42
     @Override
42
     @Override
43
     public void sendComponentStop() {
43
     public void sendComponentStop() {
44
-        reactView.sendComponentStop();
44
+        reactView.sendComponentStop(ComponentType.Component);
45
     }
45
     }
46
 
46
 
47
     @Override
47
     @Override

+ 2
- 2
lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestComponentViewCreator.java View File

2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
 
4
 
5
+import com.reactnativenavigation.react.ReactView;
5
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
6
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
6
-import com.reactnativenavigation.viewcontrollers.IReactView;
7
 import com.reactnativenavigation.views.ComponentLayout;
7
 import com.reactnativenavigation.views.ComponentLayout;
8
 import com.reactnativenavigation.views.ReactComponent;
8
 import com.reactnativenavigation.views.ReactComponent;
9
 
9
 
12
 public class TestComponentViewCreator implements ReactViewCreator {
12
 public class TestComponentViewCreator implements ReactViewCreator {
13
     @Override
13
     @Override
14
     public ReactComponent create(final Activity activity, final String componentId, final String componentName) {
14
     public ReactComponent create(final Activity activity, final String componentId, final String componentName) {
15
-        IReactView reactView = spy(new TestReactView(activity));
15
+        ReactView reactView = spy(new TestReactView(activity));
16
         return new ComponentLayout(activity, reactView);
16
         return new ComponentLayout(activity, reactView);
17
     }
17
     }
18
 }
18
 }

+ 17
- 13
lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestReactView.java View File

1
 package com.reactnativenavigation.mocks;
1
 package com.reactnativenavigation.mocks;
2
 
2
 
3
 import android.content.Context;
3
 import android.content.Context;
4
-import androidx.annotation.NonNull;
4
+import android.os.Bundle;
5
 import android.view.MotionEvent;
5
 import android.view.MotionEvent;
6
-import android.view.View;
7
-import android.widget.FrameLayout;
8
 
6
 
7
+import com.facebook.react.ReactInstanceManager;
9
 import com.reactnativenavigation.interfaces.ScrollEventListener;
8
 import com.reactnativenavigation.interfaces.ScrollEventListener;
9
+import com.reactnativenavigation.react.ReactView;
10
+import com.reactnativenavigation.react.events.ComponentType;
10
 import com.reactnativenavigation.viewcontrollers.IReactView;
11
 import com.reactnativenavigation.viewcontrollers.IReactView;
11
 import com.reactnativenavigation.views.element.Element;
12
 import com.reactnativenavigation.views.element.Element;
12
 
13
 
13
 import java.util.Collections;
14
 import java.util.Collections;
14
 import java.util.List;
15
 import java.util.List;
15
 
16
 
16
-public class TestReactView extends FrameLayout implements IReactView {
17
+import androidx.annotation.NonNull;
18
+import androidx.annotation.Nullable;
19
+
20
+public class TestReactView extends ReactView implements IReactView {
17
 
21
 
18
     public TestReactView(@NonNull Context context) {
22
     public TestReactView(@NonNull Context context) {
19
-        super(context);
23
+        super(context, null, "", "");
20
     }
24
     }
21
 
25
 
22
     @Override
26
     @Override
23
-    public boolean isReady() {
24
-        return false;
27
+    public void startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName, @Nullable Bundle initialProperties, @Nullable String initialUITemplate) {
28
+
25
     }
29
     }
26
 
30
 
27
     @Override
31
     @Override
28
-    public View asView() {
29
-        return this;
32
+    public void sendComponentStart(ComponentType type) {
33
+
30
     }
34
     }
31
 
35
 
32
     @Override
36
     @Override
33
-    public void destroy() {
37
+    public void sendComponentStop(ComponentType type) {
34
 
38
 
35
     }
39
     }
36
 
40
 
37
     @Override
41
     @Override
38
-    public void sendComponentStart() {
39
-
42
+    public boolean isReady() {
43
+        return false;
40
     }
44
     }
41
 
45
 
42
     @Override
46
     @Override
43
-    public void sendComponentStop() {
47
+    public void destroy() {
44
 
48
 
45
     }
49
     }
46
 
50
 

+ 4
- 3
lib/android/app/src/test/java/com/reactnativenavigation/mocks/TopBarButtonCreatorMock.java View File

3
 import android.app.Activity;
3
 import android.app.Activity;
4
 
4
 
5
 import com.facebook.react.ReactInstanceManager;
5
 import com.facebook.react.ReactInstanceManager;
6
-import com.reactnativenavigation.views.titlebar.TitleBarReactButtonView;
6
+import com.reactnativenavigation.react.events.ComponentType;
7
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
7
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
8
+import com.reactnativenavigation.views.titlebar.TitleBarReactButtonView;
8
 
9
 
9
 import static org.mockito.Mockito.mock;
10
 import static org.mockito.Mockito.mock;
10
 
11
 
15
         final ReactInstanceManager reactInstanceManager = mock(ReactInstanceManager.class);
16
         final ReactInstanceManager reactInstanceManager = mock(ReactInstanceManager.class);
16
         return new TitleBarReactButtonView(activity, reactInstanceManager, componentId, componentName) {
17
         return new TitleBarReactButtonView(activity, reactInstanceManager, componentId, componentName) {
17
             @Override
18
             @Override
18
-            public void sendComponentStart() {
19
+            public void sendComponentStart(ComponentType type) {
19
 
20
 
20
             }
21
             }
21
 
22
 
22
             @Override
23
             @Override
23
-            public void sendComponentStop() {
24
+            public void sendComponentStop(ComponentType type) {
24
 
25
 
25
             }
26
             }
26
         };
27
         };

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/utils/NativeCommandListenerTest.java View File

2
 
2
 
3
 import com.facebook.react.bridge.Promise;
3
 import com.facebook.react.bridge.Promise;
4
 import com.reactnativenavigation.BaseTest;
4
 import com.reactnativenavigation.BaseTest;
5
-import com.reactnativenavigation.react.EventEmitter;
5
+import com.reactnativenavigation.react.events.EventEmitter;
6
 
6
 
7
 import org.junit.Test;
7
 import org.junit.Test;
8
 import org.mockito.ArgumentCaptor;
8
 import org.mockito.ArgumentCaptor;

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

1
 package com.reactnativenavigation.viewcontrollers;
1
 package com.reactnativenavigation.viewcontrollers;
2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
-import androidx.coordinatorlayout.widget.CoordinatorLayout;
5
-import androidx.fragment.app.FragmentActivity;
6
 
4
 
7
 import com.facebook.react.ReactInstanceManager;
5
 import com.facebook.react.ReactInstanceManager;
8
 import com.reactnativenavigation.BaseTest;
6
 import com.reactnativenavigation.BaseTest;
10
 import com.reactnativenavigation.parse.Options;
8
 import com.reactnativenavigation.parse.Options;
11
 import com.reactnativenavigation.parse.params.Text;
9
 import com.reactnativenavigation.parse.params.Text;
12
 import com.reactnativenavigation.presentation.ExternalComponentPresenter;
10
 import com.reactnativenavigation.presentation.ExternalComponentPresenter;
13
-import com.reactnativenavigation.react.EventEmitter;
11
+import com.reactnativenavigation.react.events.ComponentType;
12
+import com.reactnativenavigation.react.events.EventEmitter;
14
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
13
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
15
 import com.reactnativenavigation.viewcontrollers.externalcomponent.FragmentCreatorMock;
14
 import com.reactnativenavigation.viewcontrollers.externalcomponent.FragmentCreatorMock;
16
 import com.reactnativenavigation.views.ExternalComponentLayout;
15
 import com.reactnativenavigation.views.ExternalComponentLayout;
19
 import org.junit.Test;
18
 import org.junit.Test;
20
 import org.mockito.Mockito;
19
 import org.mockito.Mockito;
21
 
20
 
21
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
22
+import androidx.fragment.app.FragmentActivity;
23
+
22
 import static org.assertj.core.api.Java6Assertions.assertThat;
24
 import static org.assertj.core.api.Java6Assertions.assertThat;
23
 import static org.mockito.Mockito.spy;
25
 import static org.mockito.Mockito.spy;
24
 import static org.mockito.Mockito.times;
26
 import static org.mockito.Mockito.times;
66
     @Test
68
     @Test
67
     public void onViewAppeared_appearEventIsEmitted() {
69
     public void onViewAppeared_appearEventIsEmitted() {
68
         uut.onViewAppeared();
70
         uut.onViewAppeared();
69
-        verify(emitter).emitComponentDidAppear(uut.getId(), ec.name.get());
71
+        verify(emitter).emitComponentDidAppear(uut.getId(), ec.name.get(), ComponentType.Component);
70
     }
72
     }
71
 
73
 
72
     @Test
74
     @Test
73
     public void onViewDisappear_disappearEventIsEmitted() {
75
     public void onViewDisappear_disappearEventIsEmitted() {
74
         uut.onViewDisappear();
76
         uut.onViewDisappear();
75
-        verify(emitter).emitComponentDidDisappear(uut.getId(), ec.name.get());
77
+        verify(emitter).emitComponentDidDisappear(uut.getId(), ec.name.get(), ComponentType.Component);
76
     }
78
     }
77
 
79
 
78
     private ExternalComponent createExternalComponent() {
80
     private ExternalComponent createExternalComponent() {

+ 10
- 8
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java View File

1
 package com.reactnativenavigation.viewcontrollers;
1
 package com.reactnativenavigation.viewcontrollers;
2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
-import androidx.annotation.NonNull;
5
 import android.view.ViewGroup;
4
 import android.view.ViewGroup;
6
 
5
 
7
 import com.reactnativenavigation.BaseTest;
6
 import com.reactnativenavigation.BaseTest;
14
 import com.reactnativenavigation.parse.params.Text;
13
 import com.reactnativenavigation.parse.params.Text;
15
 import com.reactnativenavigation.presentation.ComponentPresenter;
14
 import com.reactnativenavigation.presentation.ComponentPresenter;
16
 import com.reactnativenavigation.presentation.Presenter;
15
 import com.reactnativenavigation.presentation.Presenter;
16
+import com.reactnativenavigation.react.events.ComponentType;
17
 import com.reactnativenavigation.utils.CommandListenerAdapter;
17
 import com.reactnativenavigation.utils.CommandListenerAdapter;
18
 import com.reactnativenavigation.utils.ViewHelper;
18
 import com.reactnativenavigation.utils.ViewHelper;
19
 import com.reactnativenavigation.viewcontrollers.stack.StackController;
19
 import com.reactnativenavigation.viewcontrollers.stack.StackController;
28
 import java.util.ArrayList;
28
 import java.util.ArrayList;
29
 import java.util.List;
29
 import java.util.List;
30
 
30
 
31
+import androidx.annotation.NonNull;
32
+
31
 import static org.assertj.core.api.Java6Assertions.assertThat;
33
 import static org.assertj.core.api.Java6Assertions.assertThat;
32
 import static org.mockito.ArgumentMatchers.any;
34
 import static org.mockito.ArgumentMatchers.any;
33
 import static org.mockito.ArgumentMatchers.eq;
35
 import static org.mockito.ArgumentMatchers.eq;
133
         TestReactView selectedTab = getActualTabView(1);
135
         TestReactView selectedTab = getActualTabView(1);
134
 
136
 
135
         uut.switchToTab(1);
137
         uut.switchToTab(1);
136
-        verify(initialTab, times(1)).sendComponentStop();
137
-        verify(selectedTab, times(1)).sendComponentStart();
138
-        verify(selectedTab, times(0)).sendComponentStop();
138
+        verify(initialTab, times(1)).sendComponentStop(ComponentType.Component);
139
+        verify(selectedTab, times(1)).sendComponentStart(ComponentType.Component);
140
+        verify(selectedTab, times(0)).sendComponentStop(ComponentType.Component);
139
     }
141
     }
140
 
142
 
141
     @Test
143
     @Test
146
         uut.switchToTab(1);
148
         uut.switchToTab(1);
147
         uut.switchToTab(0);
149
         uut.switchToTab(0);
148
 
150
 
149
-        verify(getActualTabView(0), times(1)).sendComponentStop();
150
-        verify(getActualTabView(0), times(2)).sendComponentStart();
151
-        verify(getActualTabView(1), times(1)).sendComponentStart();
152
-        verify(getActualTabView(1), times(1)).sendComponentStop();
151
+        verify(getActualTabView(0), times(1)).sendComponentStop(ComponentType.Component);
152
+        verify(getActualTabView(0), times(2)).sendComponentStart(ComponentType.Component);
153
+        verify(getActualTabView(1), times(1)).sendComponentStart(ComponentType.Component);
154
+        verify(getActualTabView(1), times(1)).sendComponentStop(ComponentType.Component);
153
     }
155
     }
154
 
156
 
155
     @Test
157
     @Test

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsControllerTest.java View File

18
 import com.reactnativenavigation.presentation.BottomTabPresenter;
18
 import com.reactnativenavigation.presentation.BottomTabPresenter;
19
 import com.reactnativenavigation.presentation.BottomTabsPresenter;
19
 import com.reactnativenavigation.presentation.BottomTabsPresenter;
20
 import com.reactnativenavigation.presentation.Presenter;
20
 import com.reactnativenavigation.presentation.Presenter;
21
-import com.reactnativenavigation.react.EventEmitter;
21
+import com.reactnativenavigation.react.events.EventEmitter;
22
 import com.reactnativenavigation.utils.CommandListenerAdapter;
22
 import com.reactnativenavigation.utils.CommandListenerAdapter;
23
 import com.reactnativenavigation.utils.ImageLoader;
23
 import com.reactnativenavigation.utils.ImageLoader;
24
 import com.reactnativenavigation.utils.OptionHelper;
24
 import com.reactnativenavigation.utils.OptionHelper;

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalStackTest.java View File

9
 import com.reactnativenavigation.anim.ModalAnimator;
9
 import com.reactnativenavigation.anim.ModalAnimator;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
11
 import com.reactnativenavigation.parse.Options;
11
 import com.reactnativenavigation.parse.Options;
12
-import com.reactnativenavigation.react.EventEmitter;
12
+import com.reactnativenavigation.react.events.EventEmitter;
13
 import com.reactnativenavigation.utils.CommandListener;
13
 import com.reactnativenavigation.utils.CommandListener;
14
 import com.reactnativenavigation.utils.CommandListenerAdapter;
14
 import com.reactnativenavigation.utils.CommandListenerAdapter;
15
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
15
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/navigator/NavigatorTest.java View File

19
 import com.reactnativenavigation.presentation.OverlayManager;
19
 import com.reactnativenavigation.presentation.OverlayManager;
20
 import com.reactnativenavigation.presentation.Presenter;
20
 import com.reactnativenavigation.presentation.Presenter;
21
 import com.reactnativenavigation.presentation.RootPresenter;
21
 import com.reactnativenavigation.presentation.RootPresenter;
22
-import com.reactnativenavigation.react.EventEmitter;
22
+import com.reactnativenavigation.react.events.EventEmitter;
23
 import com.reactnativenavigation.utils.CommandListener;
23
 import com.reactnativenavigation.utils.CommandListener;
24
 import com.reactnativenavigation.utils.CommandListenerAdapter;
24
 import com.reactnativenavigation.utils.CommandListenerAdapter;
25
 import com.reactnativenavigation.utils.CompatUtils;
25
 import com.reactnativenavigation.utils.CompatUtils;

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java View File

22
 import com.reactnativenavigation.parse.params.Text;
22
 import com.reactnativenavigation.parse.params.Text;
23
 import com.reactnativenavigation.presentation.RenderChecker;
23
 import com.reactnativenavigation.presentation.RenderChecker;
24
 import com.reactnativenavigation.presentation.StackPresenter;
24
 import com.reactnativenavigation.presentation.StackPresenter;
25
-import com.reactnativenavigation.react.EventEmitter;
25
+import com.reactnativenavigation.react.events.EventEmitter;
26
 import com.reactnativenavigation.utils.CommandListenerAdapter;
26
 import com.reactnativenavigation.utils.CommandListenerAdapter;
27
 import com.reactnativenavigation.utils.StatusBarUtils;
27
 import com.reactnativenavigation.utils.StatusBarUtils;
28
 import com.reactnativenavigation.utils.TitleBarHelper;
28
 import com.reactnativenavigation.utils.TitleBarHelper;

+ 4
- 0
lib/ios/RNNBasePresenter.h View File

30
 
30
 
31
 - (void)viewDidLayoutSubviews;
31
 - (void)viewDidLayoutSubviews;
32
 
32
 
33
+- (void)componentDidAppear;
34
+
35
+- (void)componentDidDisappear;
36
+
33
 - (UIStatusBarStyle)getStatusBarStyle:(RNNNavigationOptions *)resolvedOptions;
37
 - (UIStatusBarStyle)getStatusBarStyle:(RNNNavigationOptions *)resolvedOptions;
34
 
38
 
35
 - (UIInterfaceOrientationMask)getOrientation:(RNNNavigationOptions *)options;
39
 - (UIInterfaceOrientationMask)getOrientation:(RNNNavigationOptions *)options;

+ 8
- 0
lib/ios/RNNBasePresenter.m View File

28
     _defaultOptions = defaultOptions;
28
     _defaultOptions = defaultOptions;
29
 }
29
 }
30
 
30
 
31
+- (void)componentDidAppear {
32
+    
33
+}
34
+
35
+- (void)componentDidDisappear {
36
+    
37
+}
38
+
31
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions {
39
 - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions {
32
     UIViewController* viewController = self.boundViewController;
40
     UIViewController* viewController = self.boundViewController;
33
     RNNNavigationOptions *withDefault = [initialOptions withDefault:[self defaultOptions]];
41
     RNNNavigationOptions *withDefault = [initialOptions withDefault:[self defaultOptions]];

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

87
 - (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
87
 - (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
88
 	RNNEventEmitter *eventEmitter = [[RNNEventEmitter alloc] init];
88
 	RNNEventEmitter *eventEmitter = [[RNNEventEmitter alloc] init];
89
 
89
 
90
-	id<RNNComponentViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
90
+	id<RNNComponentViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge eventEmitter:eventEmitter];
91
 	_componentRegistry = [[RNNReactComponentRegistry alloc] initWithCreator:rootViewCreator];
91
 	_componentRegistry = [[RNNReactComponentRegistry alloc] initWithCreator:rootViewCreator];
92
 	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator eventEmitter:eventEmitter store:_store componentRegistry:_componentRegistry andBridge:bridge bottomTabsAttachModeFactory:[BottomTabsAttachModeFactory new]];
92
 	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator eventEmitter:eventEmitter store:_store componentRegistry:_componentRegistry andBridge:bridge bottomTabsAttachModeFactory:[BottomTabsAttachModeFactory new]];
93
 
93
 

+ 25
- 3
lib/ios/RNNComponentPresenter.m View File

4
 #import "RCTConvert+Modal.h"
4
 #import "RCTConvert+Modal.h"
5
 #import "RNNTitleViewHelper.h"
5
 #import "RNNTitleViewHelper.h"
6
 #import "UIViewController+LayoutProtocol.h"
6
 #import "UIViewController+LayoutProtocol.h"
7
+#import "RNNReactTitleView.h"
7
 
8
 
8
 @interface RNNComponentPresenter() {
9
 @interface RNNComponentPresenter() {
9
-	RNNReactView* _customTitleView;
10
+	RNNReactTitleView* _customTitleView;
10
 	RNNTitleViewHelper* _titleViewHelper;
11
 	RNNTitleViewHelper* _titleViewHelper;
11
 	RNNReactComponentRegistry* _componentRegistry;
12
 	RNNReactComponentRegistry* _componentRegistry;
12
 }
13
 }
26
 	_navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self.boundViewController componentRegistry:_componentRegistry];
27
 	_navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self.boundViewController componentRegistry:_componentRegistry];
27
 }
28
 }
28
 
29
 
30
+- (void)componentDidAppear {
31
+    RNNReactView* component = (RNNReactView *)self.boundViewController.view;
32
+    if ([component respondsToSelector:@selector(componentDidAppear)]) {
33
+        [component componentDidAppear];
34
+    }
35
+    [_customTitleView componentDidAppear];
36
+    [_navigationButtons componentDidAppear];
37
+}
38
+
39
+- (void)componentDidDisappear {
40
+    RNNReactView* component = (RNNReactView *)self.boundViewController.view;
41
+    if ([component respondsToSelector:@selector(componentDidDisappear)]) {
42
+        [component componentDidDisappear];
43
+    }
44
+    
45
+    [_customTitleView componentDidDisappear];
46
+    [_navigationButtons componentDidDisappear];
47
+}
48
+
29
 - (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options {
49
 - (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options {
30
 	[super applyOptionsOnWillMoveToParentViewController:options];
50
 	[super applyOptionsOnWillMoveToParentViewController:options];
31
 }
51
 }
156
 }
176
 }
157
 
177
 
158
 - (void)removeTitleComponentIfNeeded:(RNNNavigationOptions *)options {
178
 - (void)removeTitleComponentIfNeeded:(RNNNavigationOptions *)options {
159
-	if (options.topBar.title.text.hasValue && !options.topBar.component.hasValue) {
179
+	if (options.topBar.title.text.hasValue) {
180
+        [_customTitleView componentDidDisappear];
160
 		[_customTitleView removeFromSuperview];
181
 		[_customTitleView removeFromSuperview];
161
 		_customTitleView = nil;
182
 		_customTitleView = nil;
162
 	}
183
 	}
175
 	}
196
 	}
176
 	
197
 	
177
 	if (options.topBar.title.component.name.hasValue) {
198
 	if (options.topBar.title.component.name.hasValue) {
178
-		_customTitleView = [_componentRegistry createComponentIfNotExists:options.topBar.title.component parentComponentId:viewController.layoutInfo.componentId reactViewReadyBlock:readyBlock];
199
+        _customTitleView = (RNNReactTitleView *)[_componentRegistry createComponentIfNotExists:options.topBar.title.component parentComponentId:viewController.layoutInfo.componentId componentType:RNNComponentTypeTopBarTitle reactViewReadyBlock:readyBlock];
179
 		_customTitleView.backgroundColor = UIColor.clearColor;
200
 		_customTitleView.backgroundColor = UIColor.clearColor;
180
 		NSString* alignment = [options.topBar.title.component.alignment getWithDefaultValue:@""];
201
 		NSString* alignment = [options.topBar.title.component.alignment getWithDefaultValue:@""];
181
 		[_customTitleView setAlignment:alignment inFrame:viewController.navigationController.navigationBar.frame];
202
 		[_customTitleView setAlignment:alignment inFrame:viewController.navigationController.navigationBar.frame];
183
 		
204
 		
184
 		viewController.navigationItem.titleView = nil;
205
 		viewController.navigationItem.titleView = nil;
185
 		viewController.navigationItem.titleView = _customTitleView;
206
 		viewController.navigationItem.titleView = _customTitleView;
207
+        [_customTitleView componentDidAppear];
186
 	} else {
208
 	} else {
187
 		[_customTitleView removeFromSuperview];
209
 		[_customTitleView removeFromSuperview];
188
 		if (readyBlock) {
210
 		if (readyBlock) {

+ 9
- 10
lib/ios/RNNComponentViewController.m View File

29
 	[self.parentViewController onChildWillAppear];
29
 	[self.parentViewController onChildWillAppear];
30
 }
30
 }
31
 
31
 
32
--(void)viewDidAppear:(BOOL)animated {
33
-	[super viewDidAppear:animated];
34
-	[self.eventEmitter sendComponentDidAppear:self.layoutInfo.componentId componentName:self.layoutInfo.name];
35
-}
36
-
37
-- (void)viewWillDisappear:(BOOL)animated {
38
-	[super viewWillDisappear:animated];
32
+- (void)viewDidAppear:(BOOL)animated {
33
+    [super viewDidAppear:animated];
34
+    [self componentDidAppear];
39
 }
35
 }
40
 
36
 
41
 - (void)viewDidDisappear:(BOOL)animated {
37
 - (void)viewDidDisappear:(BOOL)animated {
42
-	[super viewDidDisappear:animated];
43
-	[self.eventEmitter sendComponentDidDisappear:self.layoutInfo.componentId componentName:self.layoutInfo.name];
38
+    [super viewDidDisappear:animated];
39
+    [self componentDidDisappear];
44
 }
40
 }
45
 
41
 
46
 - (void)loadView {
42
 - (void)loadView {
56
 
52
 
57
 - (void)renderReactViewIfNeeded {
53
 - (void)renderReactViewIfNeeded {
58
     if (!self.isViewLoaded) {
54
     if (!self.isViewLoaded) {
59
-        self.view = [self.creator createRootView:self.layoutInfo.name rootViewId:self.layoutInfo.componentId reactViewReadyBlock:^{
55
+        self.view = [self.creator createRootView:self.layoutInfo.name
56
+                                      rootViewId:self.layoutInfo.componentId
57
+                                          ofType:RNNComponentTypeComponent
58
+                             reactViewReadyBlock:^{
60
             [self->_presenter renderComponents:self.resolveOptions perform:^{
59
             [self->_presenter renderComponents:self.resolveOptions perform:^{
61
                 [self readyForPresentation];
60
                 [self readyForPresentation];
62
             }];
61
             }];

+ 11
- 5
lib/ios/RNNComponentViewCreator.h View File

2
 #import <UIKit/UIKit.h>
2
 #import <UIKit/UIKit.h>
3
 #import "RNNComponentOptions.h"
3
 #import "RNNComponentOptions.h"
4
 #import "RNNReactView.h"
4
 #import "RNNReactView.h"
5
+#import "RNNReactButtonView.h"
6
+#import "RNNReactTitleView.h"
7
+#import "RNNReactBackgroundView.h"
5
 
8
 
6
-@protocol RNNComponentViewCreator
7
-
8
-- (RNNReactView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
9
+typedef enum RNNComponentType {
10
+    RNNComponentTypeComponent,
11
+    RNNComponentTypeTopBarTitle,
12
+    RNNComponentTypeTopBarButton,
13
+    RNNComponentTypeTopBarBackground
14
+} RNNComponentType;
9
 
15
 
10
-- (UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions;
16
+@protocol RNNComponentViewCreator
11
 
17
 
12
-- (UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
18
+- (RNNReactView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId ofType:(RNNComponentType)componentType reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
13
 
19
 
14
 @end
20
 @end
15
 
21
 

+ 2
- 3
lib/ios/RNNEventEmitter.h View File

1
 #import <Foundation/Foundation.h>
1
 #import <Foundation/Foundation.h>
2
-
3
 #import <React/RCTEventEmitter.h>
2
 #import <React/RCTEventEmitter.h>
4
 #import <React/RCTBridgeModule.h>
3
 #import <React/RCTBridgeModule.h>
5
 
4
 
7
 
6
 
8
 - (void)sendOnAppLaunched;
7
 - (void)sendOnAppLaunched;
9
 
8
 
10
-- (void)sendComponentDidAppear:(NSString*)componentId componentName:(NSString*)componentName;
9
+- (void)sendComponentDidAppear:(NSString*)componentId componentName:(NSString*)componentName componentType:(NSString *)componentType;
11
 
10
 
12
-- (void)sendComponentDidDisappear:(NSString*)componentId componentName:(NSString*)componentName;
11
+- (void)sendComponentDidDisappear:(NSString *)componentId componentName:(NSString *)componentName componentType:(NSString *)componentType;
13
 
12
 
14
 - (void)sendOnNavigationButtonPressed:(NSString*)componentId buttonId:(NSString*)buttonId;
13
 - (void)sendOnNavigationButtonPressed:(NSString*)componentId buttonId:(NSString*)buttonId;
15
 
14
 

+ 6
- 4
lib/ios/RNNEventEmitter.m View File

44
     }
44
     }
45
 }
45
 }
46
 
46
 
47
-- (void)sendComponentDidAppear:(NSString *)componentId componentName:(NSString *)componentName {
47
+- (void)sendComponentDidAppear:(NSString *)componentId componentName:(NSString *)componentName componentType:(NSString *)componentType {
48
     [self send:ComponentDidAppear body:@{
48
     [self send:ComponentDidAppear body:@{
49
         @"componentId":componentId,
49
         @"componentId":componentId,
50
-        @"componentName": componentName
50
+        @"componentName": componentName,
51
+        @"componentType": componentType
51
     }];
52
     }];
52
 }
53
 }
53
 
54
 
54
-- (void)sendComponentDidDisappear:(NSString *)componentId componentName:(NSString *)componentName{
55
+- (void)sendComponentDidDisappear:(NSString *)componentId componentName:(NSString *)componentName componentType:(NSString *)componentType {
55
     [self send:ComponentDidDisappear body:@{
56
     [self send:ComponentDidDisappear body:@{
56
         @"componentId":componentId,
57
         @"componentId":componentId,
57
-        @"componentName": componentName
58
+        @"componentName": componentName,
59
+        @"componentType": componentType
58
     }];
60
     }];
59
 }
61
 }
60
 
62
 

+ 4
- 0
lib/ios/RNNNavigationButtons.h View File

10
 
10
 
11
 -(void)applyLeftButtons:(NSArray*)leftButtons rightButtons:(NSArray*)rightButtons defaultLeftButtonStyle:(RNNButtonOptions *)defaultLeftButtonStyle defaultRightButtonStyle:(RNNButtonOptions *)defaultRightButtonStyle;
11
 -(void)applyLeftButtons:(NSArray*)leftButtons rightButtons:(NSArray*)rightButtons defaultLeftButtonStyle:(RNNButtonOptions *)defaultLeftButtonStyle defaultRightButtonStyle:(RNNButtonOptions *)defaultRightButtonStyle;
12
 
12
 
13
+- (void)componentDidAppear;
14
+
15
+- (void)componentDidDisappear;
16
+
13
 @end
17
 @end
14
 
18
 
15
 
19
 

+ 27
- 1
lib/ios/RNNNavigationButtons.m View File

63
         [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.rightBarButtonItems];
63
         [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.rightBarButtonItems];
64
         [self.viewController.navigationItem setRightBarButtonItems:barButtonItems animated:animated];
64
         [self.viewController.navigationItem setRightBarButtonItems:barButtonItems animated:animated];
65
     }
65
     }
66
+    
67
+    [self notifyButtonsDidAppear:barButtonItems];
68
+}
69
+
70
+- (NSArray *)currentButtons {
71
+    NSArray* currentButtons = [self.viewController.navigationItem.leftBarButtonItems arrayByAddingObjectsFromArray:self.viewController.navigationItem.rightBarButtonItems];
72
+    return currentButtons;
73
+}
74
+
75
+- (void)componentDidAppear {
76
+    for (RNNUIBarButtonItem* barButtonItem in [self currentButtons]) {
77
+        [barButtonItem notifyDidAppear];
78
+    }
79
+}
80
+
81
+- (void)componentDidDisappear {
82
+    for (RNNUIBarButtonItem* barButtonItem in [self currentButtons]) {
83
+        [barButtonItem notifyDidDisappear];
84
+    }
85
+}
86
+
87
+- (void)notifyButtonsDidAppear:(NSArray *)barButtonItems {
88
+    for (RNNUIBarButtonItem* barButtonItem in barButtonItems) {
89
+        [barButtonItem notifyDidAppear];
90
+    }
66
 }
91
 }
67
 
92
 
68
 - (void)clearPreviousButtonViews:(NSArray<UIBarButtonItem *> *)newButtons oldButtons:(NSArray<UIBarButtonItem *> *)oldButtons {
93
 - (void)clearPreviousButtonViews:(NSArray<UIBarButtonItem *> *)newButtons oldButtons:(NSArray<UIBarButtonItem *> *)oldButtons {
71
     for (UIBarButtonItem* buttonItem in removedButtons) {
96
     for (UIBarButtonItem* buttonItem in removedButtons) {
72
         RNNReactView* reactView = buttonItem.customView;
97
         RNNReactView* reactView = buttonItem.customView;
73
         if ([reactView isKindOfClass:[RNNReactView class]]) {
98
         if ([reactView isKindOfClass:[RNNReactView class]]) {
99
+            [reactView componentDidDisappear];
74
             [_componentRegistry removeChildComponent:reactView.componentId];
100
             [_componentRegistry removeChildComponent:reactView.componentId];
75
         }
101
         }
76
     }
102
     }
117
         componentOptions.componentId = [[Text alloc] initWithValue:component[@"componentId"]];
143
         componentOptions.componentId = [[Text alloc] initWithValue:component[@"componentId"]];
118
         componentOptions.name = [[Text alloc] initWithValue:component[@"name"]];
144
         componentOptions.name = [[Text alloc] initWithValue:component[@"name"]];
119
         
145
         
120
-        RNNReactView *view = [_componentRegistry createComponentIfNotExists:componentOptions parentComponentId:self.viewController.layoutInfo.componentId reactViewReadyBlock:nil];
146
+        RNNReactButtonView *view = [_componentRegistry createComponentIfNotExists:componentOptions parentComponentId:self.viewController.layoutInfo.componentId componentType:RNNComponentTypeTopBarButton reactViewReadyBlock:nil];
121
         barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withCustomView:view];
147
         barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withCustomView:view];
122
     } else if (iconImage) {
148
     } else if (iconImage) {
123
         barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withIcon:iconImage];
149
         barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withIcon:iconImage];

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

1
+#import "RNNReactTitleView.h"
2
+
3
+@interface RNNReactBackgroundView : RNNReactTitleView
4
+
5
+@end

+ 9
- 0
lib/ios/RNNReactBackgroundView.m View File

1
+#import "RNNReactBackgroundView.h"
2
+
3
+@implementation RNNReactBackgroundView
4
+
5
+- (NSString *)componentType {
6
+	return ComponentTypeBackground;
7
+}
8
+
9
+@end

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

1
+#import "RNNReactView.h"
2
+
3
+@interface RNNReactButtonView : RNNReactView
4
+
5
+@end

+ 9
- 0
lib/ios/RNNReactButtonView.m View File

1
+#import "RNNReactButtonView.h"
2
+
3
+@implementation RNNReactButtonView
4
+
5
+- (NSString *)componentType {
6
+    return ComponentTypeButton;
7
+}
8
+
9
+@end

+ 3
- 2
lib/ios/RNNReactComponentRegistry.h View File

1
 #import <Foundation/Foundation.h>
1
 #import <Foundation/Foundation.h>
2
-#import "RNNReactView.h"
2
+#import "RNNReactButtonView.h"
3
+#import "RNNReactTitleView.h"
3
 #import "RNNComponentOptions.h"
4
 #import "RNNComponentOptions.h"
4
 #import "RNNComponentViewCreator.h"
5
 #import "RNNComponentViewCreator.h"
5
 
6
 
7
 
8
 
8
 - (instancetype)initWithCreator:(id<RNNComponentViewCreator>)creator;
9
 - (instancetype)initWithCreator:(id<RNNComponentViewCreator>)creator;
9
 
10
 
10
-- (RNNReactView *)createComponentIfNotExists:(RNNComponentOptions *)component parentComponentId:(NSString *)parentComponentId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
11
+- (RNNReactButtonView *)createComponentIfNotExists:(RNNComponentOptions *)component parentComponentId:(NSString *)parentComponentId componentType:(RNNComponentType)componentType reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
11
 
12
 
12
 - (void)removeComponent:(NSString *)componentId;
13
 - (void)removeComponent:(NSString *)componentId;
13
 
14
 

+ 20
- 12
lib/ios/RNNReactComponentRegistry.m View File

16
 	return self;
16
 	return self;
17
 }
17
 }
18
 
18
 
19
-- (RNNReactView *)createComponentIfNotExists:(RNNComponentOptions *)component parentComponentId:(NSString *)parentComponentId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
20
-	NSMapTable* parentComponentDict = [self componentsForParentId:parentComponentId];
21
-	
22
-	RNNReactView* reactView = [parentComponentDict objectForKey:component.componentId.get];
23
-	if (!reactView) {
24
-		reactView = (RNNReactView *)[_creator createRootViewFromComponentOptions:component reactViewReadyBlock:reactViewReadyBlock];
25
-        [parentComponentDict setObject:reactView forKey:component.componentId.get];
26
-	} else if (reactViewReadyBlock) {
27
-		reactViewReadyBlock();
28
-	}
29
-	
30
-	return reactView;
19
+- (RNNReactButtonView *)createComponentIfNotExists:(RNNComponentOptions *)component parentComponentId:(NSString *)parentComponentId componentType:(RNNComponentType)componentType reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
20
+    RNNReactView* reactView = [self findComponent:component.componentId.get parentComponentId:parentComponentId];
21
+    if (!reactView) {
22
+        reactView = [_creator createRootView:component.name.get rootViewId:component.componentId.get ofType:componentType reactViewReadyBlock:reactViewReadyBlock];
23
+        [self storeComponent:reactView componentId:component.componentId.get parentComponentId:parentComponentId];
24
+    } else if (reactViewReadyBlock) {
25
+        reactViewReadyBlock();
26
+    }
27
+    
28
+    return (RNNReactButtonView *)reactView;
29
+}
30
+
31
+- (RNNReactView *)findComponent:(NSString *)componentId parentComponentId:(NSString *)parentComponentId {
32
+    NSMapTable* parentComponentDict = [self componentsForParentId:parentComponentId];
33
+    return [parentComponentDict objectForKey:componentId];
34
+}
35
+
36
+- (void)storeComponent:(RNNReactView *)component componentId:(NSString *)componentId parentComponentId:(NSString *)parentComponentId {
37
+    NSMapTable* parentComponentDict = [self componentsForParentId:parentComponentId];
38
+    [parentComponentDict setObject:component forKey:componentId];
31
 }
39
 }
32
 
40
 
33
 - (NSMapTable *)componentsForParentId:(NSString *)parentComponentId {
41
 - (NSMapTable *)componentsForParentId:(NSString *)parentComponentId {

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

1
 #import <Foundation/Foundation.h>
1
 #import <Foundation/Foundation.h>
2
 #import "RNNComponentViewCreator.h"
2
 #import "RNNComponentViewCreator.h"
3
-
3
+#import "RNNEventEmitter.h"
4
 #import <React/RCTBridge.h>
4
 #import <React/RCTBridge.h>
5
 
5
 
6
 @interface RNNReactRootViewCreator : NSObject <RNNComponentViewCreator>
6
 @interface RNNReactRootViewCreator : NSObject <RNNComponentViewCreator>
7
 
7
 
8
--(instancetype)initWithBridge:(RCTBridge*)bridge;
8
+-(instancetype)initWithBridge:(RCTBridge*)bridge eventEmitter:(RNNEventEmitter*)eventEmitter;
9
 
9
 
10
 @end
10
 @end

+ 26
- 17
lib/ios/RNNReactRootViewCreator.m View File

4
 
4
 
5
 @implementation RNNReactRootViewCreator {
5
 @implementation RNNReactRootViewCreator {
6
 	RCTBridge *_bridge;
6
 	RCTBridge *_bridge;
7
+    RNNEventEmitter* _eventEmitter;
7
 }
8
 }
8
 
9
 
9
-- (instancetype)initWithBridge:(RCTBridge*)bridge {
10
+- (instancetype)initWithBridge:(RCTBridge*)bridge eventEmitter:(RNNEventEmitter*)eventEmitter {
10
 	self = [super init];
11
 	self = [super init];
11
-	
12
 	_bridge = bridge;
12
 	_bridge = bridge;
13
-	
13
+    _eventEmitter = eventEmitter;
14
 	return self;
14
 	return self;
15
 }
15
 }
16
 
16
 
17
-- (RNNReactView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
18
-	if (!rootViewId) {
19
-		@throw [NSException exceptionWithName:@"MissingViewId" reason:@"Missing view id" userInfo:nil];
20
-	}
21
-	
22
-	RNNReactView *view = [[RNNReactView alloc] initWithBridge:_bridge
23
-												   moduleName:name
24
-											initialProperties:@{@"componentId": rootViewId}
25
-										  reactViewReadyBlock:reactViewReadyBlock];
26
-	return view;
17
+- (RNNReactView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId ofType:(RNNComponentType)componentType reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
18
+    [self verifyRootViewId:rootViewId];
19
+    return [[[self resolveComponentViewClass:componentType] alloc] initWithBridge:_bridge
20
+             moduleName:name
21
+      initialProperties:@{@"componentId": rootViewId}
22
+           eventEmitter:_eventEmitter
23
+    reactViewReadyBlock:reactViewReadyBlock];
27
 }
24
 }
28
 
25
 
29
-- (UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions {
30
-	return [self createRootView:componentOptions.name.get rootViewId:componentOptions.componentId.get reactViewReadyBlock:nil];
26
+- (Class)resolveComponentViewClass:(RNNComponentType)componentType {
27
+    switch (componentType) {
28
+        case RNNComponentTypeTopBarTitle:
29
+            return RNNReactTitleView.class;
30
+        case RNNComponentTypeTopBarButton:
31
+            return RNNReactButtonView.class;
32
+        case RNNComponentTypeTopBarBackground:
33
+            return RNNReactBackgroundView.class;
34
+        case RNNComponentTypeComponent:
35
+        default:
36
+            return RNNReactView.class;
37
+    }
31
 }
38
 }
32
 
39
 
33
-- (UIView*)createRootViewFromComponentOptions:(RNNComponentOptions*)componentOptions reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
34
-	return [self createRootView:componentOptions.name.get rootViewId:componentOptions.componentId.get reactViewReadyBlock:reactViewReadyBlock];
40
+- (void)verifyRootViewId:(NSString *)rootViewId {
41
+    if (!rootViewId) {
42
+        @throw [NSException exceptionWithName:@"MissingViewId" reason:@"Missing view id" userInfo:nil];
43
+    }
35
 }
44
 }
36
 
45
 
37
 @end
46
 @end

+ 9
- 0
lib/ios/RNNReactTitleView.h View File

1
+#import "RNNReactView.h"
2
+
3
+@interface RNNReactTitleView : RNNReactView <RCTRootViewDelegate>
4
+
5
+- (void)setAlignment:(NSString *)alignment inFrame:(CGRect)frame;
6
+
7
+@property (nonatomic, copy) void (^rootViewDidChangeIntrinsicSize)(CGSize intrinsicSize);
8
+
9
+@end

+ 44
- 0
lib/ios/RNNReactTitleView.m View File

1
+#import "RNNReactTitleView.h"
2
+
3
+@implementation RNNReactTitleView {
4
+    BOOL _fillParent;
5
+}
6
+
7
+- (NSString *)componentType {
8
+    return ComponentTypeTitle;
9
+}
10
+
11
+- (CGSize)intrinsicContentSize {
12
+    if (_fillParent) {
13
+        return UILayoutFittingExpandedSize;
14
+    } else {
15
+        return [super intrinsicContentSize];
16
+    }
17
+}
18
+
19
+- (void)setAlignment:(NSString *)alignment inFrame:(CGRect)frame {
20
+    if ([alignment isEqualToString:@"fill"]) {
21
+        _fillParent = YES;
22
+        self.frame = frame;
23
+        self.sizeFlexibility = RCTRootViewSizeFlexibilityNone;
24
+    } else {
25
+        self.sizeFlexibility = RCTRootViewSizeFlexibilityWidthAndHeight;
26
+        __weak RNNReactView *weakSelf = self;
27
+        [self setRootViewDidChangeIntrinsicSize:^(CGSize intrinsicSize) {
28
+            [weakSelf setFrame:CGRectMake(0, 0, intrinsicSize.width, intrinsicSize.height)];
29
+        }];
30
+    }
31
+}
32
+
33
+- (void)setRootViewDidChangeIntrinsicSize:(void (^)(CGSize))rootViewDidChangeIntrinsicSize {
34
+        _rootViewDidChangeIntrinsicSize = rootViewDidChangeIntrinsicSize;
35
+        self.delegate = self;
36
+}
37
+
38
+- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView {
39
+    if (_rootViewDidChangeIntrinsicSize) {
40
+        _rootViewDidChangeIntrinsicSize(rootView.intrinsicContentSize);
41
+    }
42
+}
43
+
44
+@end

+ 15
- 5
lib/ios/RNNReactView.h View File

1
 #import <React/RCTRootView.h>
1
 #import <React/RCTRootView.h>
2
 #import <React/RCTRootViewDelegate.h>
2
 #import <React/RCTRootViewDelegate.h>
3
+#import "RNNEventEmitter.h"
4
+
5
+#define ComponentTypeScreen @"Component"
6
+#define ComponentTypeTitle @"TopBarTitle"
7
+#define ComponentTypeButton @"TopBarButton"
8
+#define ComponentTypeBackground @"TopBarBackground"
3
 
9
 
4
 typedef void (^RNNReactViewReadyCompletionBlock)(void);
10
 typedef void (^RNNReactViewReadyCompletionBlock)(void);
5
 
11
 
6
-@interface RNNReactView : RCTRootView <RCTRootViewDelegate>
12
+@interface RNNReactView : RCTRootView
7
 
13
 
8
-- (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
14
+- (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties eventEmitter:(RNNEventEmitter *)eventEmitter reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
9
 
15
 
10
-@property (nonatomic, copy) void (^rootViewDidChangeIntrinsicSize)(CGSize intrinsicSize);
11
 @property (nonatomic, copy) RNNReactViewReadyCompletionBlock reactViewReadyBlock;
16
 @property (nonatomic, copy) RNNReactViewReadyCompletionBlock reactViewReadyBlock;
12
-
13
-- (void)setAlignment:(NSString *)alignment inFrame:(CGRect)frame;
17
+@property (nonatomic, strong) RNNEventEmitter* eventEmitter;
14
 
18
 
15
 - (NSString *)componentId;
19
 - (NSString *)componentId;
16
 
20
 
21
+- (NSString *)componentType;
22
+
23
+- (void)componentDidAppear;
24
+
25
+- (void)componentDidDisappear;
26
+
17
 @end
27
 @end

+ 29
- 35
lib/ios/RNNReactView.m View File

3
 #import <React/RCTUIManager.h>
3
 #import <React/RCTUIManager.h>
4
 
4
 
5
 @implementation RNNReactView {
5
 @implementation RNNReactView {
6
-	BOOL _fillParent;
6
+    BOOL _isAppeared;
7
 }
7
 }
8
 
8
 
9
-- (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
9
+- (instancetype)initWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties eventEmitter:(RNNEventEmitter *)eventEmitter reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
10
 	self = [super initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties];
10
 	self = [super initWithBridge:bridge moduleName:moduleName initialProperties:initialProperties];
11
 	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentDidAppear:) name:RCTContentDidAppearNotification object:nil];
11
 	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentDidAppear:) name:RCTContentDidAppearNotification object:nil];
12
 	 _reactViewReadyBlock = reactViewReadyBlock;
12
 	 _reactViewReadyBlock = reactViewReadyBlock;
13
-	
13
+    _eventEmitter = eventEmitter;
14
+    
14
 	return self;
15
 	return self;
15
 }
16
 }
16
 
17
 
23
 
24
 
24
 - (void)contentDidAppear:(NSNotification *)notification {
25
 - (void)contentDidAppear:(NSNotification *)notification {
25
 	RNNReactView* appearedView = notification.object;
26
 	RNNReactView* appearedView = notification.object;
26
-	
27
-	 if (_reactViewReadyBlock && [appearedView.appProperties[@"componentId"] isEqual:self.componentId]) {
28
-	 	_reactViewReadyBlock();
29
-		 _reactViewReadyBlock = nil;
30
-		 [[NSNotificationCenter defaultCenter] removeObserver:self];
27
+	 if ([appearedView.appProperties[@"componentId"] isEqual:self.componentId]) {
28
+         [self reactViewReady];
31
 	 }
29
 	 }
32
 }
30
 }
33
 
31
 
34
-- (NSString *)componentId {
35
-	return self.appProperties[@"componentId"];
32
+- (void)reactViewReady {
33
+    if (_reactViewReadyBlock) {
34
+        _reactViewReadyBlock();
35
+        _reactViewReadyBlock = nil;
36
+    }
37
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
36
 }
38
 }
37
 
39
 
38
-- (void)setRootViewDidChangeIntrinsicSize:(void (^)(CGSize))rootViewDidChangeIntrinsicSize {
39
-		_rootViewDidChangeIntrinsicSize = rootViewDidChangeIntrinsicSize;
40
-		self.delegate = self;
40
+
41
+- (void)componentDidAppear {
42
+    if (!_isAppeared) {
43
+        [_eventEmitter sendComponentDidAppear:self.componentId componentName:self.moduleName componentType:self.componentType];
44
+    }
45
+    
46
+    _isAppeared = YES;
41
 }
47
 }
42
 
48
 
43
-- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView {
44
-	if (_rootViewDidChangeIntrinsicSize) {
45
-		_rootViewDidChangeIntrinsicSize(rootView.intrinsicContentSize);
46
-	}
49
+- (void)componentDidDisappear {
50
+    if (_isAppeared) {
51
+        [_eventEmitter sendComponentDidDisappear:self.componentId componentName:self.moduleName componentType:self.componentType];
52
+    }
53
+    
54
+    _isAppeared = NO;
47
 }
55
 }
48
 
56
 
49
-- (CGSize)intrinsicContentSize {
50
-	if (_fillParent) {
51
-		return UILayoutFittingExpandedSize;
52
-	} else {
53
-		return [super intrinsicContentSize];
54
-	}
57
+- (NSString *)componentId {
58
+	return self.appProperties[@"componentId"];
55
 }
59
 }
56
 
60
 
57
-- (void)setAlignment:(NSString *)alignment inFrame:(CGRect)frame {
58
-    if ([alignment isEqualToString:@"fill"]) {
59
-        _fillParent = YES;
60
-        self.frame = frame;
61
-        self.sizeFlexibility = RCTRootViewSizeFlexibilityNone;
62
-    } else {
63
-        self.sizeFlexibility = RCTRootViewSizeFlexibilityWidthAndHeight;
64
-        __weak RNNReactView *weakSelf = self;
65
-        [self setRootViewDidChangeIntrinsicSize:^(CGSize intrinsicSize) {
66
-            [weakSelf setFrame:CGRectMake(0, 0, intrinsicSize.width, intrinsicSize.height)];
67
-        }];
68
-    }
61
+- (NSString *)componentType {
62
+    return ComponentTypeScreen;
69
 }
63
 }
70
 
64
 
71
 @end
65
 @end

+ 15
- 43
lib/ios/RNNStackPresenter.m View File

3
 #import "RNNStackController.h"
3
 #import "RNNStackController.h"
4
 #import "RNNCustomTitleView.h"
4
 #import "RNNCustomTitleView.h"
5
 #import "TopBarPresenterCreator.h"
5
 #import "TopBarPresenterCreator.h"
6
+#import "RNNReactBackgroundView.h"
6
 
7
 
7
 @interface RNNStackPresenter() {
8
 @interface RNNStackPresenter() {
8
 	RNNReactComponentRegistry* _componentRegistry;
9
 	RNNReactComponentRegistry* _componentRegistry;
9
-	UIView* _customTopBar;
10
 	UIView* _customTopBarBackground;
10
 	UIView* _customTopBarBackground;
11
-	RNNReactView* _customTopBarBackgroundReactView;
11
+	RNNReactView* _topBarBackgroundReactView;
12
     TopBarPresenter* _topBarPresenter;
12
     TopBarPresenter* _topBarPresenter;
13
 }
13
 }
14
 
14
 
28
     _topBarPresenter = [TopBarPresenterCreator createWithBoundedNavigationController:self.stackController];
28
     _topBarPresenter = [TopBarPresenterCreator createWithBoundedNavigationController:self.stackController];
29
 }
29
 }
30
 
30
 
31
+- (void)componentDidAppear {
32
+    [_topBarBackgroundReactView componentDidAppear];
33
+}
34
+
35
+- (void)componentDidDisappear {
36
+    [_topBarBackgroundReactView componentDidDisappear];
37
+}
38
+
31
 - (RNNStackController *)stackController {
39
 - (RNNStackController *)stackController {
32
     return (RNNStackController *)self.boundViewController;
40
     return (RNNStackController *)self.boundViewController;
33
 }
41
 }
115
 		[stack setBackButtonColor:options.topBar.backButton.color.get];
123
 		[stack setBackButtonColor:options.topBar.backButton.color.get];
116
 	}
124
 	}
117
 
125
 
118
-	if (options.topBar.component.name.hasValue) {
119
-		[self setCustomNavigationBarView:options perform:nil];
120
-	}
121
-	
122
 	if (options.topBar.background.component.name.hasValue) {
126
 	if (options.topBar.background.component.name.hasValue) {
123
 		[self setCustomNavigationComponentBackground:options perform:nil];
127
 		[self setCustomNavigationComponentBackground:options perform:nil];
124
 	}
128
 	}
131
 	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
135
 	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
132
 		dispatch_group_t group = dispatch_group_create();
136
 		dispatch_group_t group = dispatch_group_create();
133
 		
137
 		
134
-		dispatch_group_enter(group);
135
-		dispatch_async(dispatch_get_main_queue(), ^{
136
-			[self setCustomNavigationBarView:options perform:^{
137
-				dispatch_group_leave(group);
138
-			}];
139
-		});
140
-		
141
 		dispatch_group_enter(group);
138
 		dispatch_group_enter(group);
142
 		dispatch_async(dispatch_get_main_queue(), ^{
139
 		dispatch_async(dispatch_get_main_queue(), ^{
143
 			[self setCustomNavigationComponentBackground:options perform:^{
140
 			[self setCustomNavigationComponentBackground:options perform:^{
155
 	});
152
 	});
156
 }
153
 }
157
 
154
 
158
-- (void)setCustomNavigationBarView:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
159
-	RNNStackController* stack = self.stackController;
160
-	if (![options.topBar.component.waitForRender getWithDefaultValue:NO] && readyBlock) {
161
-		readyBlock();
162
-		readyBlock = nil;
163
-	}
164
-	if (options.topBar.component.name.hasValue) {
165
-		NSString* currentChildComponentId = [stack getCurrentChild].layoutInfo.componentId;
166
-		RCTRootView *reactView = [_componentRegistry createComponentIfNotExists:options.topBar.component parentComponentId:currentChildComponentId reactViewReadyBlock:readyBlock];
167
-		
168
-		if (_customTopBar) {
169
-			[_customTopBar removeFromSuperview];
170
-		}
171
-		_customTopBar = [[RNNCustomTitleView alloc] initWithFrame:stack.navigationBar.bounds subView:reactView alignment:@"fill"];
172
-		reactView.backgroundColor = UIColor.clearColor;
173
-		_customTopBar.backgroundColor = UIColor.clearColor;
174
-		[stack.navigationBar addSubview:_customTopBar];
175
-	} else {
176
-		[_customTopBar removeFromSuperview];
177
-		_customTopBar = nil;
178
-		if (readyBlock) {
179
-			readyBlock();
180
-		}
181
-	}
182
-}
183
-
184
 - (void)setCustomNavigationComponentBackground:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
155
 - (void)setCustomNavigationComponentBackground:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
185
     RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
156
     RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
186
 	RNNStackController* stack = self.stackController;
157
 	RNNStackController* stack = self.stackController;
188
 		readyBlock();
159
 		readyBlock();
189
 		readyBlock = nil;
160
 		readyBlock = nil;
190
 	}
161
 	}
162
+    
191
 	if (withDefault.topBar.background.component.name.hasValue) {
163
 	if (withDefault.topBar.background.component.name.hasValue) {
192
 		NSString* currentChildComponentId = [stack getCurrentChild].layoutInfo.componentId;
164
 		NSString* currentChildComponentId = [stack getCurrentChild].layoutInfo.componentId;
193
-		RNNReactView *reactView = [_componentRegistry createComponentIfNotExists:withDefault.topBar.background.component parentComponentId:currentChildComponentId reactViewReadyBlock:readyBlock];
194
-		_customTopBarBackgroundReactView = reactView;
165
+		_topBarBackgroundReactView = [_componentRegistry createComponentIfNotExists:withDefault.topBar.background.component parentComponentId:currentChildComponentId componentType:RNNComponentTypeTopBarBackground reactViewReadyBlock:readyBlock];
195
 		
166
 		
196
 	} else {
167
 	} else {
168
+        [_topBarBackgroundReactView componentDidDisappear];
197
 		[_customTopBarBackground removeFromSuperview];
169
 		[_customTopBarBackground removeFromSuperview];
198
 		_customTopBarBackground = nil;
170
 		_customTopBarBackground = nil;
199
 		if (readyBlock) {
171
 		if (readyBlock) {
207
 	if (_customTopBarBackground) {
179
 	if (_customTopBarBackground) {
208
 		[_customTopBarBackground removeFromSuperview];
180
 		[_customTopBarBackground removeFromSuperview];
209
 	}
181
 	}
210
-	RNNCustomTitleView* customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:stack.navigationBar.bounds subView:_customTopBarBackgroundReactView alignment:@"fill"];
211
-	_customTopBarBackground = customTopBarBackground;
182
+	_customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:stack.navigationBar.bounds subView:_topBarBackgroundReactView alignment:@"fill"];
212
 	
183
 	
213
 	[stack.navigationBar insertSubview:_customTopBarBackground atIndex:1];
184
 	[stack.navigationBar insertSubview:_customTopBarBackground atIndex:1];
185
+    [_topBarBackgroundReactView componentDidAppear];
214
 }
186
 }
215
 
187
 
216
 - (void)dealloc {
188
 - (void)dealloc {

+ 0
- 3
lib/ios/RNNTopBarOptions.h View File

35
 @property (nonatomic, strong) RNNButtonOptions* leftButtonStyle;
35
 @property (nonatomic, strong) RNNButtonOptions* leftButtonStyle;
36
 @property (nonatomic, strong) RNNButtonOptions* rightButtonStyle;
36
 @property (nonatomic, strong) RNNButtonOptions* rightButtonStyle;
37
 
37
 
38
-
39
-@property (nonatomic, strong) RNNComponentOptions* component;
40
-
41
 @end
38
 @end

+ 0
- 1
lib/ios/RNNTopBarOptions.m View File

36
 	self.backButton = [[RNNBackButtonOptions alloc] initWithDict:dict[@"backButton"]];
36
 	self.backButton = [[RNNBackButtonOptions alloc] initWithDict:dict[@"backButton"]];
37
 	self.leftButtonStyle = [[RNNButtonOptions alloc] initWithDict:dict[@"leftButtonStyle"]];
37
 	self.leftButtonStyle = [[RNNButtonOptions alloc] initWithDict:dict[@"leftButtonStyle"]];
38
 	self.rightButtonStyle = [[RNNButtonOptions alloc] initWithDict:dict[@"rightButtonStyle"]];
38
 	self.rightButtonStyle = [[RNNButtonOptions alloc] initWithDict:dict[@"rightButtonStyle"]];
39
-	self.component = [[RNNComponentOptions alloc] initWithDict:dict[@"component"]];
40
 	
39
 	
41
 	if (self.leftButtonColor.hasValue) {
40
 	if (self.leftButtonColor.hasValue) {
42
 		self.leftButtonStyle.color = self.leftButtonColor;
41
 		self.leftButtonStyle.color = self.leftButtonColor;

+ 3
- 0
lib/ios/RNNUIBarButtonItem.h View File

12
 -(instancetype)init:(NSString*)buttonId withCustomView:(RCTRootView *)reactView;
12
 -(instancetype)init:(NSString*)buttonId withCustomView:(RCTRootView *)reactView;
13
 -(instancetype)init:(NSString*)buttonId withSystemItem:(NSString*)systemItemName;
13
 -(instancetype)init:(NSString*)buttonId withSystemItem:(NSString*)systemItemName;
14
 
14
 
15
+- (void)notifyDidAppear;
16
+- (void)notifyDidDisappear;
17
+
15
 @end
18
 @end
16
 
19
 

+ 12
- 0
lib/ios/RNNUIBarButtonItem.m View File

63
 	return self;
63
 	return self;
64
 }
64
 }
65
 
65
 
66
+- (void)notifyDidAppear {
67
+    if ([self.customView isKindOfClass:[RNNReactView class]]) {
68
+        [((RNNReactView *)self.customView) componentDidAppear];
69
+    }
70
+}
71
+
72
+- (void)notifyDidDisappear {
73
+    if ([self.customView isKindOfClass:[RNNReactView class]]) {
74
+        [((RNNReactView *)self.customView) componentDidDisappear];
75
+    }
76
+}
77
+
66
 - (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView {
78
 - (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView {
67
 	self.widthConstraint.constant = rootView.intrinsicContentSize.width;
79
 	self.widthConstraint.constant = rootView.intrinsicContentSize.width;
68
 	self.heightConstraint.constant = rootView.intrinsicContentSize.height;
80
 	self.heightConstraint.constant = rootView.intrinsicContentSize.height;

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

131
 		503955982174864E00B0A663 /* NullDouble.m in Sources */ = {isa = PBXBuildFile; fileRef = 503955962174864E00B0A663 /* NullDouble.m */; };
131
 		503955982174864E00B0A663 /* NullDouble.m in Sources */ = {isa = PBXBuildFile; fileRef = 503955962174864E00B0A663 /* NullDouble.m */; };
132
 		5039559B2174867000B0A663 /* DoubleParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 503955992174867000B0A663 /* DoubleParser.h */; };
132
 		5039559B2174867000B0A663 /* DoubleParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 503955992174867000B0A663 /* DoubleParser.h */; };
133
 		5039559C2174867000B0A663 /* DoubleParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5039559A2174867000B0A663 /* DoubleParser.m */; };
133
 		5039559C2174867000B0A663 /* DoubleParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5039559A2174867000B0A663 /* DoubleParser.m */; };
134
+		503A8A1923BCB2ED0094D1C4 /* RNNReactButtonView.h in Headers */ = {isa = PBXBuildFile; fileRef = 503A8A1723BCB2ED0094D1C4 /* RNNReactButtonView.h */; };
135
+		503A8A1A23BCB2ED0094D1C4 /* RNNReactButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = 503A8A1823BCB2ED0094D1C4 /* RNNReactButtonView.m */; };
136
+		503A8A1D23BCB3230094D1C4 /* RNNReactTitleView.h in Headers */ = {isa = PBXBuildFile; fileRef = 503A8A1B23BCB3230094D1C4 /* RNNReactTitleView.h */; };
137
+		503A8A1E23BCB3230094D1C4 /* RNNReactTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 503A8A1C23BCB3230094D1C4 /* RNNReactTitleView.m */; };
138
+		503A8A2123BCE9C60094D1C4 /* RNNReactBackgroundView.h in Headers */ = {isa = PBXBuildFile; fileRef = 503A8A1F23BCE9C60094D1C4 /* RNNReactBackgroundView.h */; };
139
+		503A8A2223BCE9C60094D1C4 /* RNNReactBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = 503A8A2023BCE9C60094D1C4 /* RNNReactBackgroundView.m */; };
134
 		50415CBA20553B8E00BB682E /* RNNScreenTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 50415CB820553B8E00BB682E /* RNNScreenTransition.h */; };
140
 		50415CBA20553B8E00BB682E /* RNNScreenTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 50415CB820553B8E00BB682E /* RNNScreenTransition.h */; };
135
 		50415CBB20553B8E00BB682E /* RNNScreenTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 50415CB920553B8E00BB682E /* RNNScreenTransition.m */; };
141
 		50415CBB20553B8E00BB682E /* RNNScreenTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 50415CB920553B8E00BB682E /* RNNScreenTransition.m */; };
136
 		50451D052042DAEB00695F00 /* RNNPushAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 50451D032042DAEB00695F00 /* RNNPushAnimation.h */; };
142
 		50451D052042DAEB00695F00 /* RNNPushAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 50451D032042DAEB00695F00 /* RNNPushAnimation.h */; };
513
 		503955962174864E00B0A663 /* NullDouble.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NullDouble.m; sourceTree = "<group>"; };
519
 		503955962174864E00B0A663 /* NullDouble.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NullDouble.m; sourceTree = "<group>"; };
514
 		503955992174867000B0A663 /* DoubleParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DoubleParser.h; sourceTree = "<group>"; };
520
 		503955992174867000B0A663 /* DoubleParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DoubleParser.h; sourceTree = "<group>"; };
515
 		5039559A2174867000B0A663 /* DoubleParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DoubleParser.m; sourceTree = "<group>"; };
521
 		5039559A2174867000B0A663 /* DoubleParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DoubleParser.m; sourceTree = "<group>"; };
522
+		503A8A1723BCB2ED0094D1C4 /* RNNReactButtonView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNReactButtonView.h; sourceTree = "<group>"; };
523
+		503A8A1823BCB2ED0094D1C4 /* RNNReactButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNReactButtonView.m; sourceTree = "<group>"; };
524
+		503A8A1B23BCB3230094D1C4 /* RNNReactTitleView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNReactTitleView.h; sourceTree = "<group>"; };
525
+		503A8A1C23BCB3230094D1C4 /* RNNReactTitleView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNReactTitleView.m; sourceTree = "<group>"; };
526
+		503A8A1F23BCE9C60094D1C4 /* RNNReactBackgroundView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNReactBackgroundView.h; sourceTree = "<group>"; };
527
+		503A8A2023BCE9C60094D1C4 /* RNNReactBackgroundView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNReactBackgroundView.m; sourceTree = "<group>"; };
516
 		50415CB820553B8E00BB682E /* RNNScreenTransition.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNScreenTransition.h; sourceTree = "<group>"; };
528
 		50415CB820553B8E00BB682E /* RNNScreenTransition.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNScreenTransition.h; sourceTree = "<group>"; };
517
 		50415CB920553B8E00BB682E /* RNNScreenTransition.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNScreenTransition.m; sourceTree = "<group>"; };
529
 		50415CB920553B8E00BB682E /* RNNScreenTransition.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNScreenTransition.m; sourceTree = "<group>"; };
518
 		50451D032042DAEB00695F00 /* RNNPushAnimation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNPushAnimation.h; sourceTree = "<group>"; };
530
 		50451D032042DAEB00695F00 /* RNNPushAnimation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNPushAnimation.h; sourceTree = "<group>"; };
1138
 				50CED450239F9DFC00C42EE2 /* TopBarPresenter.m */,
1150
 				50CED450239F9DFC00C42EE2 /* TopBarPresenter.m */,
1139
 				501E0215213E7EA3003365C5 /* RNNReactView.h */,
1151
 				501E0215213E7EA3003365C5 /* RNNReactView.h */,
1140
 				501E0216213E7EA3003365C5 /* RNNReactView.m */,
1152
 				501E0216213E7EA3003365C5 /* RNNReactView.m */,
1153
+				503A8A1723BCB2ED0094D1C4 /* RNNReactButtonView.h */,
1154
+				503A8A1823BCB2ED0094D1C4 /* RNNReactButtonView.m */,
1155
+				503A8A1B23BCB3230094D1C4 /* RNNReactTitleView.h */,
1156
+				503A8A1C23BCB3230094D1C4 /* RNNReactTitleView.m */,
1157
+				503A8A1F23BCE9C60094D1C4 /* RNNReactBackgroundView.h */,
1158
+				503A8A2023BCE9C60094D1C4 /* RNNReactBackgroundView.m */,
1141
 				26916C961E4B9E7700D13680 /* RNNReactRootViewCreator.h */,
1159
 				26916C961E4B9E7700D13680 /* RNNReactRootViewCreator.h */,
1142
 				26916C971E4B9E7700D13680 /* RNNReactRootViewCreator.m */,
1160
 				26916C971E4B9E7700D13680 /* RNNReactRootViewCreator.m */,
1143
 				7BA500761E254908001B9E1B /* RNNSplashScreen.h */,
1161
 				7BA500761E254908001B9E1B /* RNNSplashScreen.h */,
1364
 				5060DE73219DAD7E00D0C052 /* ReactNativeNavigation.h in Headers */,
1382
 				5060DE73219DAD7E00D0C052 /* ReactNativeNavigation.h in Headers */,
1365
 				261F0E6A1E6F028A00989DE2 /* RNNNavigationStackManager.h in Headers */,
1383
 				261F0E6A1E6F028A00989DE2 /* RNNNavigationStackManager.h in Headers */,
1366
 				50EB4ED72068EBE000D6ED34 /* RNNBackgroundOptions.h in Headers */,
1384
 				50EB4ED72068EBE000D6ED34 /* RNNBackgroundOptions.h in Headers */,
1385
+				503A8A2123BCE9C60094D1C4 /* RNNReactBackgroundView.h in Headers */,
1367
 				504AFE761FFFF1E00076E904 /* RNNNavigationOptions.h in Headers */,
1386
 				504AFE761FFFF1E00076E904 /* RNNNavigationOptions.h in Headers */,
1368
 				504AFE771FFFF1E20076E904 /* RNNTopBarOptions.h in Headers */,
1387
 				504AFE771FFFF1E20076E904 /* RNNTopBarOptions.h in Headers */,
1369
 				5038A3CE216E35E0009280BC /* Dictionary.h in Headers */,
1388
 				5038A3CE216E35E0009280BC /* Dictionary.h in Headers */,
1389
+				503A8A1D23BCB3230094D1C4 /* RNNReactTitleView.h in Headers */,
1370
 				509416A323A11C340036092C /* Enum.h in Headers */,
1390
 				509416A323A11C340036092C /* Enum.h in Headers */,
1371
 				26916C981E4B9E7700D13680 /* RNNReactRootViewCreator.h in Headers */,
1391
 				26916C981E4B9E7700D13680 /* RNNReactRootViewCreator.h in Headers */,
1372
 				5012241A21736678000F5F98 /* Image.h in Headers */,
1392
 				5012241A21736678000F5F98 /* Image.h in Headers */,
1406
 				507F43C51FF4F17C00D9425B /* RNNTopTabsViewController.h in Headers */,
1426
 				507F43C51FF4F17C00D9425B /* RNNTopTabsViewController.h in Headers */,
1407
 				501223D72173590F000F5F98 /* RNNStackPresenter.h in Headers */,
1427
 				501223D72173590F000F5F98 /* RNNStackPresenter.h in Headers */,
1408
 				50495946216F5FB5006D2B81 /* TextParser.h in Headers */,
1428
 				50495946216F5FB5006D2B81 /* TextParser.h in Headers */,
1429
+				503A8A1923BCB2ED0094D1C4 /* RNNReactButtonView.h in Headers */,
1409
 				505EDD3C214FA8000071C7DE /* RNNComponentPresenter.h in Headers */,
1430
 				505EDD3C214FA8000071C7DE /* RNNComponentPresenter.h in Headers */,
1410
 				502CB46E20CD1DDA0019B2FE /* RNNBackButtonOptions.h in Headers */,
1431
 				502CB46E20CD1DDA0019B2FE /* RNNBackButtonOptions.h in Headers */,
1411
 				50495939216E5750006D2B81 /* Bool.h in Headers */,
1432
 				50495939216E5750006D2B81 /* Bool.h in Headers */,
1665
 				5016E8F020209690009D4F7C /* RNNCustomTitleView.m in Sources */,
1686
 				5016E8F020209690009D4F7C /* RNNCustomTitleView.m in Sources */,
1666
 				503955982174864E00B0A663 /* NullDouble.m in Sources */,
1687
 				503955982174864E00B0A663 /* NullDouble.m in Sources */,
1667
 				E8DA24411F97459B00CD552B /* RNNElementFinder.m in Sources */,
1688
 				E8DA24411F97459B00CD552B /* RNNElementFinder.m in Sources */,
1689
+				503A8A2223BCE9C60094D1C4 /* RNNReactBackgroundView.m in Sources */,
1668
 				50570B272061473D006A1B5C /* RNNTitleOptions.m in Sources */,
1690
 				50570B272061473D006A1B5C /* RNNTitleOptions.m in Sources */,
1669
 				5047E4F122674AD400908DD3 /* RNNLayoutManager.m in Sources */,
1691
 				5047E4F122674AD400908DD3 /* RNNLayoutManager.m in Sources */,
1670
 				5012241F217366D4000F5F98 /* ColorParser.m in Sources */,
1692
 				5012241F217366D4000F5F98 /* ColorParser.m in Sources */,
1677
 				A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */,
1699
 				A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */,
1678
 				5050465521F8F4490035497A /* RNNReactComponentRegistry.m in Sources */,
1700
 				5050465521F8F4490035497A /* RNNReactComponentRegistry.m in Sources */,
1679
 				509416AC23A11CB20036092C /* NullEnum.m in Sources */,
1701
 				509416AC23A11CB20036092C /* NullEnum.m in Sources */,
1702
+				503A8A1A23BCB2ED0094D1C4 /* RNNReactButtonView.m in Sources */,
1680
 				50570BEB2063E09B006A1B5C /* RNNTitleViewHelper.m in Sources */,
1703
 				50570BEB2063E09B006A1B5C /* RNNTitleViewHelper.m in Sources */,
1681
 				263905E71E4CAC950023D7D3 /* RNNSideMenuChildVC.m in Sources */,
1704
 				263905E71E4CAC950023D7D3 /* RNNSideMenuChildVC.m in Sources */,
1682
 				50495957216F6B3D006D2B81 /* DictionaryParser.m in Sources */,
1705
 				50495957216F6B3D006D2B81 /* DictionaryParser.m in Sources */,
1775
 				5038A3D3216E364C009280BC /* Text.m in Sources */,
1798
 				5038A3D3216E364C009280BC /* Text.m in Sources */,
1776
 				5017D9E2239D2C6C00B74047 /* BottomTabsAttachModeFactory.m in Sources */,
1799
 				5017D9E2239D2C6C00B74047 /* BottomTabsAttachModeFactory.m in Sources */,
1777
 				5012240F21735999000F5F98 /* RNNBasePresenter.m in Sources */,
1800
 				5012240F21735999000F5F98 /* RNNBasePresenter.m in Sources */,
1801
+				503A8A1E23BCB3230094D1C4 /* RNNReactTitleView.m in Sources */,
1778
 				5038A375216CDDB6009280BC /* UIViewController+SideMenuController.m in Sources */,
1802
 				5038A375216CDDB6009280BC /* UIViewController+SideMenuController.m in Sources */,
1779
 				E8E518331F83B3E0000467AC /* RNNUtils.m in Sources */,
1803
 				E8E518331F83B3E0000467AC /* RNNUtils.m in Sources */,
1780
 				50451D062042DAEB00695F00 /* RNNPushAnimation.m in Sources */,
1804
 				50451D062042DAEB00695F00 /* RNNPushAnimation.m in Sources */,

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

28
 
28
 
29
 - (void)readyForPresentation;
29
 - (void)readyForPresentation;
30
 
30
 
31
+- (void)componentDidAppear;
32
+
33
+- (void)componentDidDisappear;
34
+
31
 @property (nonatomic, retain) RNNBasePresenter* presenter;
35
 @property (nonatomic, retain) RNNBasePresenter* presenter;
32
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
36
 @property (nonatomic, retain) RNNLayoutInfo* layoutInfo;
33
 @property (nonatomic, strong) RNNNavigationOptions* options;
37
 @property (nonatomic, strong) RNNNavigationOptions* options;

+ 11
- 1
lib/ios/UIViewController+LayoutProtocol.m View File

114
 
114
 
115
 - (void)onChildWillAppear {
115
 - (void)onChildWillAppear {
116
 	[self.presenter applyOptions:self.resolveOptions];
116
 	[self.presenter applyOptions:self.resolveOptions];
117
-	[((UISplitViewController *)self.parentViewController) onChildWillAppear];
117
+	[self.parentViewController onChildWillAppear];
118
+}
119
+
120
+- (void)componentDidAppear {
121
+    [self.presenter componentDidAppear];
122
+    [self.parentViewController componentDidAppear];
123
+}
124
+
125
+- (void)componentDidDisappear {
126
+    [self.presenter componentDidDisappear];
127
+    [self.parentViewController componentDidDisappear];
118
 }
128
 }
119
 
129
 
120
 - (void)willMoveToParentViewController:(UIViewController *)parent {
130
 - (void)willMoveToParentViewController:(UIViewController *)parent {

+ 15
- 14
lib/src/events/ComponentEventsObserver.test.tsx View File

148
     expect(tree.toJSON()).toBeDefined();
148
     expect(tree.toJSON()).toBeDefined();
149
     expect(didAppearFn).not.toHaveBeenCalled();
149
     expect(didAppearFn).not.toHaveBeenCalled();
150
 
150
 
151
-    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
151
+    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
152
     expect(didAppearFn).toHaveBeenCalledTimes(1);
152
     expect(didAppearFn).toHaveBeenCalledTimes(1);
153
   });
153
   });
154
 
154
 
158
 
158
 
159
     expect(tree.toJSON()).toBeDefined();
159
     expect(tree.toJSON()).toBeDefined();
160
     
160
     
161
-    uut.notifyComponentDidAppear({ componentId: 'dontUseThisId', componentName: 'doesnt matter' });
161
+    uut.notifyComponentDidAppear({ componentId: 'dontUseThisId', componentName: 'doesnt matter', componentType: 'Component' });
162
     expect(didAppearFn).not.toHaveBeenCalled();
162
     expect(didAppearFn).not.toHaveBeenCalled();
163
     
163
     
164
 
164
 
165
-    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
165
+    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
166
     expect(didAppearFn).toHaveBeenCalledTimes(1);
166
     expect(didAppearFn).toHaveBeenCalledTimes(1);
167
   });
167
   });
168
 
168
 
174
     expect(didDisappearFn).not.toHaveBeenCalled();
174
     expect(didDisappearFn).not.toHaveBeenCalled();
175
     expect(willUnmountFn).not.toHaveBeenCalled();
175
     expect(willUnmountFn).not.toHaveBeenCalled();
176
 
176
 
177
-    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
177
+    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
178
     expect(didAppearFn).toHaveBeenCalledTimes(1);
178
     expect(didAppearFn).toHaveBeenCalledTimes(1);
179
 
179
 
180
-    uut.notifyComponentDidDisappear({ componentId: 'myCompId', componentName: 'doesnt matter' });
180
+    uut.notifyComponentDidDisappear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
181
     expect(didDisappearFn).toHaveBeenCalledTimes(1);
181
     expect(didDisappearFn).toHaveBeenCalledTimes(1);
182
 
182
 
183
     uut.notifyNavigationButtonPressed({ componentId: 'myCompId', buttonId: 'myButtonId' });
183
     uut.notifyNavigationButtonPressed({ componentId: 'myCompId', buttonId: 'myButtonId' });
211
   it(`componentDidAppear should receive component props from store`, () => {
211
   it(`componentDidAppear should receive component props from store`, () => {
212
     const event = {
212
     const event = {
213
       componentId: 'myCompId',
213
       componentId: 'myCompId',
214
+      componentType: 'Component',
214
       passProps: {
215
       passProps: {
215
         propA: 'propA'
216
         propA: 'propA'
216
       },
217
       },
220
     mockStore.updateProps(event.componentId, event.passProps)
221
     mockStore.updateProps(event.componentId, event.passProps)
221
     expect(didAppearFn).not.toHaveBeenCalled();
222
     expect(didAppearFn).not.toHaveBeenCalled();
222
 
223
 
223
-    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
224
+    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
224
     expect(didAppearFn).toHaveBeenCalledTimes(1);
225
     expect(didAppearFn).toHaveBeenCalledTimes(1);
225
     expect(didAppearFn).toHaveBeenCalledWith(event);
226
     expect(didAppearFn).toHaveBeenCalledWith(event);
226
   });
227
   });
227
 
228
 
228
   it(`doesnt call other componentIds`, () => {
229
   it(`doesnt call other componentIds`, () => {
229
     renderer.create(<BoundScreen componentId={'myCompId'} />);
230
     renderer.create(<BoundScreen componentId={'myCompId'} />);
230
-    uut.notifyComponentDidAppear({ componentId: 'other', componentName: 'doesnt matter' });
231
+    uut.notifyComponentDidAppear({ componentId: 'other', componentName: 'doesnt matter', componentType: 'Component' });
231
     expect(didAppearFn).not.toHaveBeenCalled();
232
     expect(didAppearFn).not.toHaveBeenCalled();
232
   });
233
   });
233
 
234
 
235
     const tree = renderer.create(<SimpleScreen componentId={'myCompId'} />);
236
     const tree = renderer.create(<SimpleScreen componentId={'myCompId'} />);
236
     expect((tree.getInstance() as any).componentDidAppear).toBeUndefined();
237
     expect((tree.getInstance() as any).componentDidAppear).toBeUndefined();
237
     uut.bindComponent(tree.getInstance() as any);
238
     uut.bindComponent(tree.getInstance() as any);
238
-    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
239
+    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
239
   });
240
   });
240
 
241
 
241
   it(`returns unregister fn`, () => {
242
   it(`returns unregister fn`, () => {
242
     renderer.create(<BoundScreen componentId={'123'} />);
243
     renderer.create(<BoundScreen componentId={'123'} />);
243
 
244
 
244
-    uut.notifyComponentDidAppear({ componentId: '123', componentName: 'doesnt matter' });
245
+    uut.notifyComponentDidAppear({ componentId: '123', componentName: 'doesnt matter', componentType: 'Component' });
245
     expect(didAppearFn).toHaveBeenCalledTimes(1);
246
     expect(didAppearFn).toHaveBeenCalledTimes(1);
246
 
247
 
247
     subscription.remove();
248
     subscription.remove();
248
 
249
 
249
-    uut.notifyComponentDidAppear({ componentId: '123', componentName: 'doesnt matter' });
250
+    uut.notifyComponentDidAppear({ componentId: '123', componentName: 'doesnt matter', componentType: 'Component' });
250
     expect(didAppearFn).toHaveBeenCalledTimes(1);
251
     expect(didAppearFn).toHaveBeenCalledTimes(1);
251
   });
252
   });
252
 
253
 
256
 
257
 
257
     uut.unmounted('123');
258
     uut.unmounted('123');
258
 
259
 
259
-    uut.notifyComponentDidAppear({ componentId: '123', componentName: 'doesnt matter' });
260
+    uut.notifyComponentDidAppear({ componentId: '123', componentName: 'doesnt matter', componentType: 'Component' });
260
     expect(didAppearFn).not.toHaveBeenCalled();
261
     expect(didAppearFn).not.toHaveBeenCalled();
261
   });
262
   });
262
 
263
 
272
     const result2 = uut.bindComponent(instance2);
273
     const result2 = uut.bindComponent(instance2);
273
     expect(result1).not.toEqual(result2);
274
     expect(result1).not.toEqual(result2);
274
 
275
 
275
-    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
276
+    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
276
 
277
 
277
     expect(instance1.componentDidAppear).toHaveBeenCalledTimes(1);
278
     expect(instance1.componentDidAppear).toHaveBeenCalledTimes(1);
278
     expect(instance2.componentDidAppear).toHaveBeenCalledTimes(1);
279
     expect(instance2.componentDidAppear).toHaveBeenCalledTimes(1);
279
 
280
 
280
     result2.remove();
281
     result2.remove();
281
 
282
 
282
-    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
283
+    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
283
     expect(instance1.componentDidAppear).toHaveBeenCalledTimes(2);
284
     expect(instance1.componentDidAppear).toHaveBeenCalledTimes(2);
284
     expect(instance2.componentDidAppear).toHaveBeenCalledTimes(1);
285
     expect(instance2.componentDidAppear).toHaveBeenCalledTimes(1);
285
 
286
 
286
     result1.remove();
287
     result1.remove();
287
 
288
 
288
-    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
289
+    uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter', componentType: 'Component' });
289
     expect(instance1.componentDidAppear).toHaveBeenCalledTimes(2);
290
     expect(instance1.componentDidAppear).toHaveBeenCalledTimes(2);
290
     expect(instance2.componentDidAppear).toHaveBeenCalledTimes(1);
291
     expect(instance2.componentDidAppear).toHaveBeenCalledTimes(1);
291
   });
292
   });

+ 4
- 0
lib/src/interfaces/ComponentEvents.ts View File

1
+export type ComponentType = 'Component' | 'TopBarTitle' | 'TopBarBackground' | 'TopBarButton';
2
+
1
 export interface ComponentEvent {
3
 export interface ComponentEvent {
2
   componentId: string;
4
   componentId: string;
3
 }
5
 }
5
 export interface ComponentDidAppearEvent extends ComponentEvent {
7
 export interface ComponentDidAppearEvent extends ComponentEvent {
6
   componentName: string;
8
   componentName: string;
7
   passProps?: object;
9
   passProps?: object;
10
+  componentType: ComponentType;
8
 }
11
 }
9
 
12
 
10
 export interface ComponentDidDisappearEvent extends ComponentEvent {
13
 export interface ComponentDidDisappearEvent extends ComponentEvent {
11
   componentName: string;
14
   componentName: string;
15
+  componentType: ComponentType;
12
 }
16
 }
13
 
17
 
14
 export interface NavigationButtonPressedEvent extends ComponentEvent {
18
 export interface NavigationButtonPressedEvent extends ComponentEvent {

+ 6
- 6
playground/ios/NavigationTests/RNNComponentPresenterTest.m View File

170
 	[[(id)self.componentRegistry expect] createComponentIfNotExists:[OCMArg checkWithBlock:^BOOL(RNNComponentOptions* options) {
170
 	[[(id)self.componentRegistry expect] createComponentIfNotExists:[OCMArg checkWithBlock:^BOOL(RNNComponentOptions* options) {
171
 		return [options.name.get isEqual:@"titleComponent"] &&
171
 		return [options.name.get isEqual:@"titleComponent"] &&
172
 		[options.componentId.get isEqual:@"id"];
172
 		[options.componentId.get isEqual:@"id"];
173
-	}] parentComponentId:self.uut.boundComponentId reactViewReadyBlock:[OCMArg any]];
173
+	}] parentComponentId:self.uut.boundComponentId componentType:RNNComponentTypeTopBarTitle reactViewReadyBlock:[OCMArg any]];
174
 	[self.uut renderComponents:self.options perform:nil];
174
 	[self.uut renderComponents:self.options perform:nil];
175
 	[(id)self.componentRegistry verify];
175
 	[(id)self.componentRegistry verify];
176
 	
176
 	
189
 	[[(id)self.componentRegistry expect] createComponentIfNotExists:[OCMArg checkWithBlock:^BOOL(RNNComponentOptions* options) {
189
 	[[(id)self.componentRegistry expect] createComponentIfNotExists:[OCMArg checkWithBlock:^BOOL(RNNComponentOptions* options) {
190
 		return [options.name.get isEqual:@"titleComponent"] &&
190
 		return [options.name.get isEqual:@"titleComponent"] &&
191
 		[options.componentId.get isEqual:@"id"];
191
 		[options.componentId.get isEqual:@"id"];
192
-	}] parentComponentId:self.uut.boundComponentId reactViewReadyBlock:[OCMArg any]];
192
+	}] parentComponentId:self.uut.boundComponentId componentType:RNNComponentTypeTopBarTitle reactViewReadyBlock:[OCMArg any]];
193
 	[self.uut renderComponents:self.options perform:nil];
193
 	[self.uut renderComponents:self.options perform:nil];
194
 	[(id)self.componentRegistry verify];
194
 	[(id)self.componentRegistry verify];
195
 	
195
 	
198
 }
198
 }
199
 
199
 
200
 - (void)testRemoveTitleComponentIfNeeded_componentIsRemovedIfTitleTextIsDefined {
200
 - (void)testRemoveTitleComponentIfNeeded_componentIsRemovedIfTitleTextIsDefined {
201
-	id mockTitle = [OCMockObject niceMockForClass:[RNNReactView class]];
202
-    OCMStub([self.componentRegistry createComponentIfNotExists:[OCMArg any] parentComponentId:[OCMArg any] reactViewReadyBlock:nil]).andReturn(mockTitle);
201
+	id mockTitle = [OCMockObject niceMockForClass:[RNNReactTitleView class]];
202
+    OCMStub([self.componentRegistry createComponentIfNotExists:[OCMArg any] parentComponentId:[OCMArg any] componentType:RNNComponentTypeTopBarTitle reactViewReadyBlock:nil]).andReturn(mockTitle);
203
 
203
 
204
 	RNNComponentOptions* component = [RNNComponentOptions new];
204
 	RNNComponentOptions* component = [RNNComponentOptions new];
205
 	component.name = [[Text alloc] initWithValue:@"componentName"];
205
 	component.name = [[Text alloc] initWithValue:@"componentName"];
219
 }
219
 }
220
 
220
 
221
 - (void)testRemoveTitleComponentIfNeeded_componentIsNotRemovedIfMergeOptionsIsCalledWithoutTitleText {
221
 - (void)testRemoveTitleComponentIfNeeded_componentIsNotRemovedIfMergeOptionsIsCalledWithoutTitleText {
222
-    id mockTitle = [OCMockObject niceMockForClass:[RNNReactView class]];
223
-    OCMStub([self.componentRegistry createComponentIfNotExists:[OCMArg any] parentComponentId:[OCMArg any] reactViewReadyBlock:nil]).andReturn(mockTitle);
222
+    id mockTitle = [OCMockObject niceMockForClass:[RNNReactTitleView class]];
223
+    OCMStub([self.componentRegistry createComponentIfNotExists:[OCMArg any] parentComponentId:[OCMArg any]  componentType:RNNComponentTypeTopBarTitle reactViewReadyBlock:nil]).andReturn(mockTitle);
224
 
224
 
225
     RNNComponentOptions* component = [RNNComponentOptions new];
225
     RNNComponentOptions* component = [RNNComponentOptions new];
226
     component.name = [[Text alloc] initWithValue:@"componentName"];
226
     component.name = [[Text alloc] initWithValue:@"componentName"];

+ 1
- 1
playground/ios/NavigationTests/RNNTestRootViewCreator.m View File

2
 
2
 
3
 @implementation RNNTestRootViewCreator
3
 @implementation RNNTestRootViewCreator
4
 
4
 
5
-- (UIView*)createRootView:(NSString*)name rootViewId:(NSString*)rootViewId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
5
+- (RNNReactView *)createRootView:(NSString *)name rootViewId:(NSString *)rootViewId ofType:(RNNComponentType)componentType reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
6
 	UIView *view = [[UIView alloc] init];
6
 	UIView *view = [[UIView alloc] init];
7
 	view.tag = [rootViewId intValue];
7
 	view.tag = [rootViewId intValue];
8
 	return view;
8
 	return view;

+ 9
- 1
playground/src/screens/PushedScreen.js View File

14
   POP_TO_ROOT_BTN,
14
   POP_TO_ROOT_BTN,
15
   ADD_BACK_HANDLER,
15
   ADD_BACK_HANDLER,
16
   REMOVE_BACK_HANDLER,
16
   REMOVE_BACK_HANDLER,
17
-  SET_STACK_ROOT_BUTTON
17
+  SET_STACK_ROOT_BUTTON,
18
+  PUSH_OPTIONS_BUTTON
18
 } = require('../testIDs');
19
 } = require('../testIDs');
19
 const Screens = require('./Screens');
20
 const Screens = require('./Screens');
20
 
21
 
56
         <Button label='Add BackHandler' testID={ADD_BACK_HANDLER} onPress={this.addBackHandler} />
57
         <Button label='Add BackHandler' testID={ADD_BACK_HANDLER} onPress={this.addBackHandler} />
57
         <Button label='Remove BackHandler' testID={REMOVE_BACK_HANDLER} onPress={this.removeBackHandler} />
58
         <Button label='Remove BackHandler' testID={REMOVE_BACK_HANDLER} onPress={this.removeBackHandler} />
58
         <Button label='Set Stack Root' testID={SET_STACK_ROOT_BUTTON} onPress={this.setStackRoot} />
59
         <Button label='Set Stack Root' testID={SET_STACK_ROOT_BUTTON} onPress={this.setStackRoot} />
60
+        <Button label='Push Options Screen' testID={PUSH_OPTIONS_BUTTON} onPress={this.pushOptionsScreen} />
59
       </Root>
61
       </Root>
60
     );
62
     );
61
   }
63
   }
89
     }
91
     }
90
   });
92
   });
91
 
93
 
94
+  pushOptionsScreen = () => Navigation.push(this, {
95
+    component: {
96
+      name: Screens.Options
97
+    }
98
+  });
99
+
92
   popToFirstScreen = () => Navigation.popTo(this.props.previousScreenIds[0]);
100
   popToFirstScreen = () => Navigation.popTo(this.props.previousScreenIds[0]);
93
 
101
 
94
   popToRoot = () => Navigation.popToRoot(this);
102
   popToRoot = () => Navigation.popToRoot(this);

+ 21
- 1
playground/src/screens/StaticLifecycleOverlay.js View File

60
     } else if (event.commandName) {
60
     } else if (event.commandName) {
61
       return <Text style={styles.h2}>{`${event.commandName}`}</Text>;
61
       return <Text style={styles.h2}>{`${event.commandName}`}</Text>;
62
     } else if (event.componentName) {
62
     } else if (event.componentName) {
63
-      return <Text style={styles.h2}>{`${event.event} | ${event.componentName}`}</Text>;
63
+      return <Text style={styles.h2}>{`${event.event} | ${event.componentName} | ${event.componentType}`}</Text>;
64
     } else if (event.buttonId) {
64
     } else if (event.buttonId) {
65
       return <Text style={styles.h2}>{`${event.event} | ${event.buttonId}`}</Text>;
65
       return <Text style={styles.h2}>{`${event.event} | ${event.buttonId}`}</Text>;
66
     } else {
66
     } else {
82
           {events}
82
           {events}
83
         </View>
83
         </View>
84
         {this.renderDismissButton()}
84
         {this.renderDismissButton()}
85
+        {this.renderClearButton()}
85
       </View>
86
       </View>
86
     );
87
     );
87
   }
88
   }
96
       </TouchableOpacity>
97
       </TouchableOpacity>
97
     );
98
     );
98
   }
99
   }
100
+
101
+  renderClearButton = () => {
102
+    return (
103
+      <TouchableOpacity
104
+        style={styles.clearBtn}
105
+        onPress={() => this.setState({events: []})}
106
+      >
107
+        <Text testID={TestIDs.CLEAR_OVERLAY_EVENTS_BTN} style={{ color: 'red', alignSelf: 'center' }}>Clear</Text>
108
+      </TouchableOpacity>
109
+    );
110
+  }
99
 }
111
 }
100
 module.exports = StaticLifecycleOverlay;
112
 module.exports = StaticLifecycleOverlay;
101
 
113
 
116
     backgroundColor: 'white',
128
     backgroundColor: 'white',
117
     justifyContent: 'center'
129
     justifyContent: 'center'
118
   },
130
   },
131
+  clearBtn: {
132
+    position: 'absolute',
133
+    right: 0,
134
+    width: 35,
135
+    height: 35,
136
+    backgroundColor: 'white',
137
+    justifyContent: 'center'
138
+  },
119
   events: {
139
   events: {
120
     flexDirection: 'column',
140
     flexDirection: 'column',
121
     marginHorizontal: 2
141
     marginHorizontal: 2

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

84
   PORTRAIT_ORIENTATION_BTN: 'PORTRAIT_ORIENTATION_BTN',
84
   PORTRAIT_ORIENTATION_BTN: 'PORTRAIT_ORIENTATION_BTN',
85
   LANDSCAPE_ORIENTATION_BTN: 'LANDSCAPE_ORIENTATION_BTN',
85
   LANDSCAPE_ORIENTATION_BTN: 'LANDSCAPE_ORIENTATION_BTN',
86
   DISMISS_BTN: 'DISMISS_BTN',
86
   DISMISS_BTN: 'DISMISS_BTN',
87
+  CLEAR_OVERLAY_EVENTS_BTN: 'CLEAR_OVERLAY_EVENTS_BTN',
87
   SEARCH_BTN: 'SEARCH_BTN',
88
   SEARCH_BTN: 'SEARCH_BTN',
88
   SET_STACK_ROOT_BTN: 'SET_STACK_ROOT_BTN',
89
   SET_STACK_ROOT_BTN: 'SET_STACK_ROOT_BTN',
89
   SET_STACK_ROOT_WITH_ID_BTN: 'SET_STACK_ROOT_WITH_ID_BTN',
90
   SET_STACK_ROOT_WITH_ID_BTN: 'SET_STACK_ROOT_WITH_ID_BTN',