Browse Source

[Experimental] Custom transition animation for ios (#1955)

* screen Background Color iOS

* ios v2 topBarTextFontFamily

* added topBarHidden to iOS

* minor fix and topBarHideOnScroll

* minor fix

* topBarButtonColor iOS

* topBarTranslucent iOS

* topBarTranslucent IOS minor fixes

* eslint fixes

* minor fixes

* changed setTabBadge to tabBadge and added a unit test in iOS

* added fontSize on iOS

* minor fix

* topBarTransparent

* minor fix

* first dirty custom transition iOS poc. in need of complete refactor and testing

* dirty poc for view transition

* dirty poc of interactive transition

* deleted unNeeded Files

* cleaning

* cleaning, support for interactiveImagePop and backButton custom transition

* cleaning

* merge v2 into custom-transition-animation fix

* merge fix

* merge fix

* cleaning and merge fix

* support for multiple animation in parralel, animations with are not shared element including: velocity, spring, alpha and translate

* last commit should also include these

* added resize mode animation and fixed flickering bug

* refactoring

* first cleaning and another test

* cleaning

* commandsHandler now accepts bridge in constructor, fixed tests, added e2e test

* eslint

* android pop now recieves two parameters - preparation for custom transition

* Refactor + add afterLoad to modal

* merge v2 second try

* merge fix

* merge fix

* fix ios unit tests

* fixed topBarTransparent e2e

* fix js tests

* refactored RNNAnimator, RNNAnimatedView, small fixes

* refactor topBarLargeTitle

* fixed lifycycle bug with componentWillUnmount, small fixes

* fix transparent conflict

* removered Element.js from coverage report

* comment redundent test
(still needs to be discussed), small fix

* removed commented test, moved element.js to adapters
bogobogo 7 years ago
parent
commit
49bd92d4b5
66 changed files with 1804 additions and 131 deletions
  1. 20
    0
      e2e/CustomTransition.js
  2. 0
    1
      e2e/Orientations.test.js
  3. 8
    0
      e2e/ScreenStyle.test.js
  4. 12
    0
      lib/ios/RNNAnimatedView.h
  5. 65
    0
      lib/ios/RNNAnimatedView.m
  6. 8
    0
      lib/ios/RNNAnimator.h
  7. 157
    0
      lib/ios/RNNAnimator.m
  8. 3
    3
      lib/ios/RNNBridgeModule.m
  9. 2
    2
      lib/ios/RNNCommandsHandler.h
  10. 26
    8
      lib/ios/RNNCommandsHandler.m
  11. 6
    0
      lib/ios/RNNElement.h
  12. 30
    0
      lib/ios/RNNElement.m
  13. 14
    0
      lib/ios/RNNElementFinder.h
  14. 56
    0
      lib/ios/RNNElementFinder.m
  15. 12
    0
      lib/ios/RNNElementView.h
  16. 6
    0
      lib/ios/RNNElementView.m
  17. 15
    0
      lib/ios/RNNInteractivePopAnimator.h
  18. 175
    0
      lib/ios/RNNInteractivePopAnimator.m
  19. 2
    1
      lib/ios/RNNModalManager.h
  20. 19
    2
      lib/ios/RNNModalManager.m
  21. 0
    1
      lib/ios/RNNNavigationController.h
  22. 4
    0
      lib/ios/RNNNavigationOptions.h
  23. 59
    7
      lib/ios/RNNNavigationOptions.m
  24. 6
    2
      lib/ios/RNNNavigationStackManager.h
  25. 52
    4
      lib/ios/RNNNavigationStackManager.m
  26. 3
    3
      lib/ios/RNNRootViewController.h
  27. 35
    3
      lib/ios/RNNRootViewController.m
  28. 1
    0
      lib/ios/RNNTopBarOptions.h
  29. 1
    0
      lib/ios/RNNTopBarOptions.m
  30. 33
    0
      lib/ios/RNNTransitionStateHolder.h
  31. 32
    0
      lib/ios/RNNTransitionStateHolder.m
  32. 8
    0
      lib/ios/RNNUtils.h
  33. 25
    0
      lib/ios/RNNUtils.m
  34. 27
    0
      lib/ios/RNNViewLocation.h
  35. 49
    0
      lib/ios/RNNViewLocation.m
  36. 1
    1
      lib/ios/ReactNativeNavigation.m
  37. 122
    1
      lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj
  38. 3
    1
      lib/ios/ReactNativeNavigation.xcodeproj/xcshareddata/xcschemes/ReactNativeNavigation.xcscheme
  39. 15
    11
      lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m
  40. 1
    2
      lib/ios/ReactNativeNavigationTests/RNNNavigationStackManagerTest.m
  41. 43
    11
      lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m
  42. 26
    0
      lib/ios/ReactNativeNavigationTests/RNNTransitionStateHolderTest.m
  43. 24
    0
      lib/ios/VICMAImageView.h
  44. 280
    0
      lib/ios/VICMAImageView.m
  45. 4
    3
      lib/src/Navigation.js
  46. 20
    0
      lib/src/adapters/Element.js
  47. 2
    2
      lib/src/adapters/NativeCommandsSender.js
  48. 2
    2
      lib/src/commands/Commands.js
  49. 13
    1
      lib/src/commands/Commands.test.js
  50. 26
    42
      package-lock.json
  51. 4
    4
      package.json
  52. BIN
      playground/img/1024.jpeg
  53. BIN
      playground/img/2048.jpeg
  54. BIN
      playground/img/400.jpeg
  55. BIN
      playground/img/4096.jpeg
  56. BIN
      playground/img/Icon-87.png
  57. BIN
      playground/img/fff.png
  58. 9
    3
      playground/ios/playground.xcodeproj/project.pbxproj
  59. 2
    0
      playground/ios/playground.xcodeproj/xcshareddata/xcschemes/playground.xcscheme
  60. 0
    1
      playground/src/app.js
  61. 94
    0
      playground/src/containers/CustomTransitionDestination.js
  62. 94
    0
      playground/src/containers/CustomTransitionOrigin.js
  63. 29
    1
      playground/src/containers/OptionsScreen.js
  64. 8
    7
      playground/src/containers/ScrollViewScreen.js
  65. 7
    1
      playground/src/containers/WelcomeScreen.js
  66. 4
    0
      playground/src/containers/index.js

+ 20
- 0
e2e/CustomTransition.js View File

1
+
2
+const Utils = require('./Utils');
3
+
4
+const elementByLabel = Utils.elementByLabel;
5
+
6
+describe('custom transition', () => {
7
+  beforeEach(async () => {
8
+    await device.relaunchApp();
9
+  });
10
+
11
+  it('sanity', async () => {
12
+    await elementByLabel('Push Options Screen').tap();
13
+    await elementByLabel('Custom Transition').tap();
14
+    await expect(element(by.id('shared_image1'))).toExist();
15
+    await element(by.id('shared_image1')).tap();
16
+    await expect(element(by.id('shared_image2'))).toExist();
17
+    await element(by.id('shared_image2')).tap();
18
+    await expect(element(by.id('shared_image1'))).toExist();
19
+  });
20
+});

+ 0
- 1
e2e/Orientations.test.js View File

49
   it('landscape only', async () => {
49
   it('landscape only', async () => {
50
     await elementByLabel('Orientation').tap();
50
     await elementByLabel('Orientation').tap();
51
     await elementByLabel('landscape only').tap();
51
     await elementByLabel('landscape only').tap();
52
-    await expect(element(by.id('currentOrientation'))).toHaveText('Portrait');
53
     await device.setOrientation('landscape');
52
     await device.setOrientation('landscape');
54
     await expect(element(by.id('currentOrientation'))).toHaveText('Landscape');
53
     await expect(element(by.id('currentOrientation'))).toHaveText('Landscape');
55
     await device.setOrientation('portrait');
54
     await device.setOrientation('portrait');

+ 8
- 0
e2e/ScreenStyle.test.js View File

45
     await expect(element(by.type('UINavigationBar'))).toBeVisible();
45
     await expect(element(by.type('UINavigationBar'))).toBeVisible();
46
   });
46
   });
47
 
47
 
48
+  it('makes topBar transparent and opaque', async () => {
49
+    await elementByLabel('Push Options Screen').tap();
50
+    await elementByLabel('Top Bar Transparent').tap();
51
+    await expect(element(by.type('_UIVisualEffectBackdropView'))).toBeNotVisible();
52
+    await elementByLabel('Top Bar Opaque').tap();
53
+    await expect(element(by.type('_UIVisualEffectBackdropView')).atIndex(1)).toBeVisible();
54
+  });
55
+
48
   it('set Tab Bar badge on a current Tab', async () => {
56
   it('set Tab Bar badge on a current Tab', async () => {
49
     await elementByLabel('Switch to tab based app').tap();
57
     await elementByLabel('Switch to tab based app').tap();
50
     await elementByLabel('Set Tab Badge').tap();
58
     await elementByLabel('Set Tab Badge').tap();

+ 12
- 0
lib/ios/RNNAnimatedView.h View File

1
+#import <UIKit/UIKit.h>
2
+#import "RNNTransitionStateHolder.h"
3
+#import "RNNViewLocation.h"
4
+#import "VICMAImageView.h"
5
+
6
+@class RNNViewLocation;
7
+@class RNNTransitionStateHolder;
8
+@interface RNNAnimatedView : UIView
9
+
10
+-(instancetype)initWithTransition:(RNNTransitionStateHolder*)transition andLocation:(RNNViewLocation*)location andIsBackButton:(BOOL)backButton;
11
++(UIViewContentMode)contentModefromString:(NSString*)resizeMode;
12
+@end

+ 65
- 0
lib/ios/RNNAnimatedView.m View File

1
+#import "RNNAnimatedView.h"
2
+#import "RNNElementView.h"
3
+
4
+@implementation RNNAnimatedView
5
+
6
+-(instancetype)initWithTransition:(RNNTransitionStateHolder*)transition andLocation:(RNNViewLocation*)location andIsBackButton:(BOOL)backButton {
7
+	UIView* animatedView = nil;
8
+	if (backButton) {
9
+		if ([self elementIsImage:transition.fromElement]) {
10
+			animatedView = [self createImageAnimatedView:animatedView fromElement:transition.fromElement toElement:transition.toElement];
11
+		} else {
12
+			if (transition.toElement) {
13
+				animatedView = [[transition.toElement subviews][0] snapshotViewAfterScreenUpdates:NO];
14
+			} else {
15
+				animatedView = [[transition.fromElement subviews][0] snapshotViewAfterScreenUpdates:NO];
16
+			}
17
+		}
18
+		[self assignStyle:animatedView withSize:location.toSize center:location.toCenter andAlpha:transition.endAlpha];
19
+	} else {
20
+		if ([self elementIsImage:transition.fromElement]) {
21
+			animatedView = [self createImageAnimatedView:animatedView fromElement:transition.fromElement toElement:transition.fromElement];
22
+		} else {
23
+			if (transition.isFromVC) {
24
+				animatedView = [[transition.fromElement subviews][0] snapshotViewAfterScreenUpdates:NO];
25
+			} else {
26
+				animatedView = [[transition.fromElement subviews][0] snapshotViewAfterScreenUpdates:YES];
27
+			}
28
+		}
29
+		[self assignStyle:animatedView withSize:location.fromSize center:location.fromCenter andAlpha:transition.startAlpha];
30
+	}
31
+	return (RNNAnimatedView*)animatedView;
32
+}
33
+
34
+-(BOOL)elementIsImage:(RNNElementView*)element {
35
+	return [[element subviews][0] isKindOfClass:[UIImageView class]];
36
+}
37
+
38
+-(UIView*)createImageAnimatedView:(UIView*)animatedView fromElement:(RNNElementView*)fromElement toElement:(RNNElementView*)toElement {
39
+	UIImage* image = [[fromElement subviews][0] image];
40
+	animatedView = [[VICMAImageView alloc] initWithImage:image];
41
+	animatedView.contentMode = UIViewContentModeScaleAspectFill;
42
+	if (toElement.resizeMode){
43
+		animatedView.contentMode = [RNNAnimatedView contentModefromString:toElement.resizeMode];
44
+	}
45
+	return animatedView;
46
+}
47
+
48
+-(void)assignStyle:(UIView*)animatedView withSize:(CGSize)size center:(CGPoint)center andAlpha:(double)alpha {
49
+	animatedView.frame = CGRectMake(0, 0, size.width, size.height);
50
+	animatedView.center = center;
51
+	animatedView.alpha = alpha;
52
+}
53
+
54
++(UIViewContentMode)contentModefromString:(NSString*)resizeMode{
55
+	if ([resizeMode isEqualToString:@"cover"]) {
56
+		return UIViewContentModeScaleAspectFill;
57
+	} else if ([resizeMode isEqualToString:@"contain"]) {
58
+		return UIViewContentModeScaleAspectFit;
59
+	} else if ([resizeMode isEqualToString:@"stretch"]) {
60
+		return UIViewContentModeScaleToFill;
61
+	} else {
62
+		return 0;
63
+	}
64
+}
65
+@end

+ 8
- 0
lib/ios/RNNAnimator.h View File

1
+#import <Foundation/Foundation.h>
2
+#import <UIKit/UIKit.h>
3
+#import "RNNElementView.h"
4
+
5
+@interface RNNAnimator : NSObject <UIViewControllerAnimatedTransitioning>
6
+-(void)setupTransition:(NSDictionary*)data;
7
+
8
+@end

+ 157
- 0
lib/ios/RNNAnimator.m View File

1
+#import <React/RCTRedBox.h>
2
+#import "RNNAnimator.h"
3
+#import "RNNElementView.h"
4
+#import "RNNInteractivePopAnimator.h"
5
+#import "VICMAImageView.h"
6
+#import "RNNTransitionStateHolder.h"
7
+#import "RNNElementFinder.h"
8
+#import "RNNViewLocation.h"
9
+#import "RNNAnimatedView.h"
10
+
11
+@interface  RNNAnimator()
12
+@property (nonatomic, strong)NSArray* animations;
13
+@property (nonatomic)double duration;
14
+@property (nonatomic)double springDamping;
15
+@property (nonatomic)double springVelocity;
16
+@property (nonatomic, strong) RNNInteractivePopAnimator* interactivePopAnimator;
17
+@property (nonatomic) BOOL backButton;
18
+@property (nonatomic, strong) UIViewController* fromVC;
19
+@property (nonatomic, strong) UIViewController* toVC;
20
+@end
21
+
22
+@implementation RNNAnimator
23
+
24
+-(void)setupTransition:(NSDictionary*)data{
25
+	if ([data objectForKey:@"animations"]) {
26
+		self.animations= [data objectForKey:@"animations"];
27
+	} else {
28
+		[[NSException exceptionWithName:NSInvalidArgumentException reason:@"No animations" userInfo:nil] raise];
29
+	}
30
+	if ([data objectForKey:@"duration"]) {
31
+		self.duration = [[data objectForKey:@"duration"] doubleValue];
32
+	} else {
33
+		self.duration = 0.7;
34
+	}
35
+	if ([data objectForKey:@"springDamping"]) {
36
+		self.springDamping = [[data objectForKey:@"springDamping"] doubleValue];
37
+	} else {
38
+		self.springDamping = 0.85;
39
+	}
40
+	if ([data objectForKey:@"springVelocity"]) {
41
+		self.springVelocity= [[data objectForKey:@"springVelocity"] doubleValue];
42
+	} else {
43
+		self.springVelocity = 0.8;
44
+	}
45
+	
46
+	self.backButton = false;
47
+}
48
+
49
+-(NSArray*)prepareSharedElementTransition:(NSArray*)RNNSharedElementsToVC
50
+						andfromVCElements:(NSArray*)RNNSharedElementsFromVC
51
+						withContainerView:(UIView*)containerView
52
+{
53
+	NSMutableArray* transitions = [NSMutableArray new];
54
+	for (NSDictionary* transition in self.animations) {
55
+		RNNTransitionStateHolder* transitionStateHolder = [[RNNTransitionStateHolder alloc] initWithTransition:transition];
56
+		RNNElementFinder* elementFinder = [[RNNElementFinder alloc] initWithToVC:self.toVC andfromVC:self.fromVC];
57
+		[elementFinder findElementsInTransition:transitionStateHolder];
58
+		RNNViewLocation* animatedViewLocations = [[RNNViewLocation alloc] initWithTransition:transitionStateHolder andVC:self.fromVC];
59
+		RNNAnimatedView* animatedView = [[RNNAnimatedView alloc] initWithTransition:transitionStateHolder andLocation:animatedViewLocations andIsBackButton:self.backButton];
60
+		transitionStateHolder.locations = animatedViewLocations;
61
+		[containerView addSubview:animatedView];
62
+		[containerView bringSubviewToFront:animatedView];
63
+		transitionStateHolder.animatedView = animatedView;
64
+		[transitions addObject:transitionStateHolder];
65
+		if (transitionStateHolder.isSharedElementTransition){
66
+			[transitionStateHolder.toElement setHidden: YES];
67
+		}
68
+		[transitionStateHolder.fromElement setHidden:YES];
69
+	}
70
+	return transitions;
71
+}
72
+
73
+-(void)animateTransitions:(NSArray*)transitions {
74
+	for (RNNTransitionStateHolder* transition in transitions ) {
75
+		[UIView animateWithDuration:transition.duration delay:transition.startDelay usingSpringWithDamping:transition.springDamping initialSpringVelocity:transition.springVelocity options:UIViewAnimationOptionCurveEaseOut  animations:^{
76
+			RNNAnimatedView* animatedView = transition.animatedView;
77
+			if (!self.backButton) {
78
+				[self setAnimatedViewFinalProperties:animatedView toElement:transition.toElement fromElement:transition.fromElement isSharedElementTransition:transition.isSharedElementTransition withTransform:transition.locations.transform withCenter:transition.locations.toCenter andAlpha:transition.endAlpha];
79
+			} else {
80
+				[self setAnimatedViewFinalProperties:animatedView toElement:transition.fromElement fromElement:transition.fromElement isSharedElementTransition:transition.isSharedElementTransition withTransform:transition.locations.transformBack withCenter:transition.locations.fromCenter andAlpha:transition.startAlpha];
81
+			}
82
+		} completion:^(BOOL finished) {
83
+
84
+		}];
85
+	}
86
+}
87
+
88
+-(void)setAnimatedViewFinalProperties:(RNNAnimatedView*)animatedView toElement:(RNNElementView*)toElement fromElement:(RNNElementView*)fromElement isSharedElementTransition:(BOOL)isShared withTransform:(CGAffineTransform)transform withCenter:(CGPoint)center andAlpha:(double)alpha {
89
+	animatedView.alpha = alpha;
90
+	animatedView.center = center;
91
+	animatedView.transform = transform;
92
+	if (isShared) {
93
+		if ([[fromElement subviews][0] isKindOfClass:[UIImageView class]]) {
94
+			animatedView.contentMode = UIViewContentModeScaleAspectFill;
95
+			if ([toElement resizeMode]){
96
+				animatedView.contentMode = [RNNAnimatedView contentModefromString:[toElement resizeMode]];
97
+			}
98
+		}
99
+	}
100
+}
101
+
102
+
103
+-(void)animateComplition:(NSArray*)transitions fromVCSnapshot:(UIView*)fromSnapshot andTransitioningContext:(id<UIViewControllerContextTransitioning>)transitionContext {
104
+	[UIView animateWithDuration:[self transitionDuration:transitionContext ] delay:0 usingSpringWithDamping:self.springDamping initialSpringVelocity:self.springVelocity options:UIViewAnimationOptionCurveEaseOut  animations:^{
105
+				self.toVC.view.alpha = 1;
106
+			} completion:^(BOOL finished) {
107
+				for (RNNTransitionStateHolder* transition in transitions ) {
108
+					[transition.fromElement setHidden:NO];
109
+					if (transition.isSharedElementTransition) {
110
+						[transition.toElement setHidden:NO];
111
+					}
112
+					RNNAnimatedView* animtedView = transition.animatedView;
113
+					[animtedView removeFromSuperview];
114
+					
115
+					if (transition.interactivePop) {
116
+						self.interactivePopAnimator = [[RNNInteractivePopAnimator alloc] initWithTopView:transition.toElement andBottomView:transition.fromElement andOriginFrame:transition.locations.fromFrame andViewController:self.toVC];
117
+						UIPanGestureRecognizer* gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopAnimator
118
+																								  action:@selector(handleGesture:)];
119
+						[transition.toElement addGestureRecognizer:gesture];
120
+					}
121
+				}
122
+				[fromSnapshot removeFromSuperview];
123
+				if (![transitionContext transitionWasCancelled]) {
124
+					self.toVC.view.alpha = 1;
125
+					[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
126
+					self.backButton = true;
127
+				}
128
+			}];
129
+}
130
+
131
+- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
132
+{
133
+	return self.duration;
134
+}
135
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
136
+{
137
+	UIViewController* toVC   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
138
+	UIViewController* fromVC  = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
139
+	UIView* containerView = [transitionContext containerView];
140
+	self.fromVC = fromVC;
141
+	self.toVC = toVC;
142
+	toVC.view.frame = fromVC.view.frame;
143
+	UIView* fromSnapshot = [fromVC.view snapshotViewAfterScreenUpdates:true];
144
+	fromSnapshot.frame = fromVC.view.frame;
145
+	[containerView addSubview:fromSnapshot];
146
+	[containerView addSubview:toVC.view];
147
+	toVC.view.alpha = 0;
148
+	NSArray* onlyForTesting = @[];
149
+	NSArray* onlyForTesting2 = @[];
150
+	NSArray* transitions = [self prepareSharedElementTransition:onlyForTesting andfromVCElements:onlyForTesting2 withContainerView:containerView];
151
+	[self animateComplition:transitions fromVCSnapshot:fromSnapshot andTransitioningContext:transitionContext];
152
+	[self animateTransitions:transitions];
153
+}
154
+@end
155
+
156
+
157
+

+ 3
- 3
lib/ios/RNNBridgeModule.m View File

3
 @implementation RNNBridgeModule {
3
 @implementation RNNBridgeModule {
4
 	RNNCommandsHandler* _commandsHandler;
4
 	RNNCommandsHandler* _commandsHandler;
5
 }
5
 }
6
-
6
+@synthesize bridge = _bridge;
7
 RCT_EXPORT_MODULE();
7
 RCT_EXPORT_MODULE();
8
 
8
 
9
 - (dispatch_queue_t)methodQueue {
9
 - (dispatch_queue_t)methodQueue {
30
 	[_commandsHandler push:containerId layout:layout];
30
 	[_commandsHandler push:containerId layout:layout];
31
 }
31
 }
32
 
32
 
33
-RCT_EXPORT_METHOD(pop:(NSString*)containerId) {
34
-	[_commandsHandler pop:containerId];
33
+RCT_EXPORT_METHOD(pop:(NSString*)containerId options:(NSDictionary*)options) {
34
+	[_commandsHandler pop:containerId options:(NSDictionary*)options];
35
 }
35
 }
36
 
36
 
37
 RCT_EXPORT_METHOD(popTo:(NSString*)containerId) {
37
 RCT_EXPORT_METHOD(popTo:(NSString*)containerId) {

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

6
 
6
 
7
 @interface RNNCommandsHandler : NSObject
7
 @interface RNNCommandsHandler : NSObject
8
 
8
 
9
--(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory;
9
+-(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory andBridge:(RCTBridge*)bridge;
10
 
10
 
11
 -(void) setRoot:(NSDictionary*)layout;
11
 -(void) setRoot:(NSDictionary*)layout;
12
 
12
 
14
 
14
 
15
 -(void) push:(NSString*)containerId layout:(NSDictionary*)layout;
15
 -(void) push:(NSString*)containerId layout:(NSDictionary*)layout;
16
 
16
 
17
--(void) pop:(NSString*)containerId;
17
+-(void) pop:(NSString*)containerId options:(NSDictionary*)options;
18
 
18
 
19
 -(void) popTo:(NSString*)containerId;
19
 -(void) popTo:(NSString*)containerId;
20
 
20
 

+ 26
- 8
lib/ios/RNNCommandsHandler.m View File

1
-
2
 #import "RNNCommandsHandler.h"
1
 #import "RNNCommandsHandler.h"
3
-
4
 #import "RNNModalManager.h"
2
 #import "RNNModalManager.h"
5
 #import "RNNNavigationStackManager.h"
3
 #import "RNNNavigationStackManager.h"
6
 #import "RNNNavigationOptions.h"
4
 #import "RNNNavigationOptions.h"
9
 @implementation RNNCommandsHandler {
7
 @implementation RNNCommandsHandler {
10
 	RNNControllerFactory *_controllerFactory;
8
 	RNNControllerFactory *_controllerFactory;
11
 	RNNStore *_store;
9
 	RNNStore *_store;
10
+	RCTBridge* _bridge;
12
 	RNNNavigationStackManager* _navigationStackManager;
11
 	RNNNavigationStackManager* _navigationStackManager;
13
 	RNNModalManager* _modalManager;
12
 	RNNModalManager* _modalManager;
14
 }
13
 }
15
 
14
 
16
--(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory {
15
+-(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory andBridge:(RCTBridge*)bridge {
17
 	self = [super init];
16
 	self = [super init];
17
+	_bridge = bridge;
18
 	_store = store;
18
 	_store = store;
19
 	_controllerFactory = controllerFactory;
19
 	_controllerFactory = controllerFactory;
20
 	_navigationStackManager = [[RNNNavigationStackManager alloc] initWithStore:_store];
20
 	_navigationStackManager = [[RNNNavigationStackManager alloc] initWithStore:_store];
47
 	}
47
 	}
48
 }
48
 }
49
 
49
 
50
--(void) push:(NSString*)containerId layout:(NSDictionary*)layout {
50
+-(void)push:(NSString*)containerId layout:(NSDictionary*)layout {
51
 	[self assertReady];
51
 	[self assertReady];
52
-	
52
+	NSDictionary* customAnimation = layout[@"data"][@"customTransition"];
53
 	UIViewController *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
53
 	UIViewController *newVc = [_controllerFactory createLayoutAndSaveToStore:layout];
54
-	[_navigationStackManager push:newVc onTop:containerId];
54
+	RCTBridge* bridge = _bridge;
55
+	if (customAnimation) {
56
+		if ([customAnimation objectForKey:@"animations"]) {
57
+			[_navigationStackManager push:newVc onTop:containerId customAnimationData:(NSDictionary*)customAnimation bridge:bridge];
58
+		} else {
59
+			[[NSException exceptionWithName:NSInvalidArgumentException reason:@"unsupported transitionAnimation" userInfo:nil] raise];
60
+		}
61
+	} else {
62
+		[_navigationStackManager push:newVc onTop:containerId customAnimationData:(NSDictionary*)nil bridge:bridge];
63
+	}
55
 }
64
 }
56
 
65
 
57
--(void) pop:(NSString*)containerId {
66
+-(void)pop:(NSString*)containerId options:(NSDictionary*)options{
58
 	[self assertReady];
67
 	[self assertReady];
68
+	NSDictionary* animationData = options[@"customTransition"];
69
+	if (animationData){
70
+		if ([animationData objectForKey:@"animations"]) {
71
+			[_navigationStackManager pop:containerId withAnimationData:animationData];
72
+		} else {
73
+			[[NSException exceptionWithName:NSInvalidArgumentException reason:@"unsupported transitionAnimation" userInfo:nil] raise];
74
+		}
75
+	} else {
76
+		[_navigationStackManager pop:containerId withAnimationData:nil];
77
+	}
59
 	
78
 	
60
-	[_navigationStackManager pop:containerId];
61
 }
79
 }
62
 
80
 
63
 -(void) popTo:(NSString*)containerId {
81
 -(void) popTo:(NSString*)containerId {

+ 6
- 0
lib/ios/RNNElement.h View File

1
+#import <React/RCTViewManager.h>
2
+#import <Foundation/Foundation.h>
3
+
4
+@interface RNNElement : RCTViewManager
5
+
6
+@end

+ 30
- 0
lib/ios/RNNElement.m View File

1
+
2
+#import <React/RCTViewManager.h>
3
+#import "RNNElement.h"
4
+#import "RNNElementView.h"
5
+@interface RNNElement()
6
+
7
+
8
+@end
9
+@implementation RNNElement
10
+
11
+
12
+RCT_CUSTOM_VIEW_PROPERTY(elementId, NSString, RNNElement)
13
+{
14
+	[(RNNElementView*)view setElementId:json];
15
+}
16
+
17
+RCT_CUSTOM_VIEW_PROPERTY(resizeMode, NSString, RNNElement)
18
+{
19
+	[(RNNElementView*)view setResizeMode:json];
20
+}
21
+
22
+RCT_EXPORT_MODULE();
23
+
24
+- (RNNElementView *)view
25
+{
26
+	RNNElementView* element = [[RNNElementView alloc] init];
27
+	return element;
28
+}
29
+
30
+@end

+ 14
- 0
lib/ios/RNNElementFinder.h View File

1
+#import <Foundation/Foundation.h>
2
+#import "RNNElementView.h"
3
+#import "RNNTransitionStateHolder.h"
4
+
5
+@interface RNNElementFinder : NSObject
6
+
7
+@property (nonatomic, strong) NSArray* toVCTransitionElements;
8
+@property (nonatomic, strong) NSArray* fromVCTransitionElements;
9
+
10
+-(instancetype)initWithToVC:(UIViewController*)toVC andfromVC:(UIViewController*)fromVC;
11
+-(NSArray*)findRNNElementViews:(UIView*)view;
12
+-(RNNElementView*)findViewToAnimate:(NSArray*)RNNTransitionElementViews withId:(NSString*)elementId;
13
+-(void)findElementsInTransition:(RNNTransitionStateHolder*)transitionStateHolder;
14
+@end

+ 56
- 0
lib/ios/RNNElementFinder.m View File

1
+#import "RNNElementFinder.h"
2
+
3
+@implementation RNNElementFinder 
4
+
5
+-(instancetype)initWithToVC:(UIViewController*)toVC andfromVC:(UIViewController*)fromVC {
6
+	self = [super init];
7
+	self.toVCTransitionElements = [self findRNNElementViews:toVC.view];
8
+	self.fromVCTransitionElements = [self findRNNElementViews:fromVC.view];
9
+	return self;
10
+}
11
+
12
+-(RNNElementView*)findViewToAnimate:(NSArray*)RNNTransitionElementViews withId:(NSString*)elementId{
13
+	for (RNNElementView* view in RNNTransitionElementViews) {
14
+		if ([view.elementId isEqualToString:elementId]){
15
+			return view;
16
+		}
17
+	}
18
+	return nil;
19
+}
20
+
21
+-(NSArray*)findRNNElementViews:(UIView*)view{
22
+	NSMutableArray* elementViews = [NSMutableArray new];
23
+	for(UIView *aView in view.subviews){
24
+		if([aView isMemberOfClass:[RNNElementView class]]){
25
+			[elementViews addObject:aView];
26
+		} else{
27
+			if ([aView subviews]) {
28
+				[elementViews addObjectsFromArray:[self findRNNElementViews:aView]];
29
+			}
30
+		}
31
+	}
32
+	return elementViews;
33
+}
34
+
35
+-(void)findElementsInTransition:(RNNTransitionStateHolder*)transitionStateHolder {
36
+	if ([self findViewToAnimate:self.toVCTransitionElements withId:transitionStateHolder.fromId]) {
37
+		transitionStateHolder.fromElement = [self findViewToAnimate:self.toVCTransitionElements withId:transitionStateHolder.fromId];
38
+		transitionStateHolder.isFromVC = false;
39
+	} else if ([self findViewToAnimate:self.fromVCTransitionElements withId:transitionStateHolder.fromId]){
40
+		transitionStateHolder.fromElement = [self findViewToAnimate:self.fromVCTransitionElements withId:transitionStateHolder.fromId];
41
+		transitionStateHolder.isFromVC = true;
42
+	} else {
43
+		[[NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"elementId %@ does not exist", transitionStateHolder.fromId] userInfo:nil] raise];
44
+	}
45
+	if (transitionStateHolder.toId) {
46
+		if ([self findViewToAnimate:self.toVCTransitionElements withId:transitionStateHolder.toId]) {
47
+			transitionStateHolder.toElement = [self findViewToAnimate:self.toVCTransitionElements withId:transitionStateHolder.toId];
48
+		} else if ([self findViewToAnimate:self.fromVCTransitionElements withId:transitionStateHolder.toId]){
49
+			transitionStateHolder.toElement = [self findViewToAnimate:self.fromVCTransitionElements withId:transitionStateHolder.toId];
50
+		} else {
51
+			[[NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"elementId %@ does not exist", transitionStateHolder.toId] userInfo:nil] raise];
52
+		}
53
+	}
54
+}
55
+
56
+@end

+ 12
- 0
lib/ios/RNNElementView.h View File

1
+#import <UIKit/UIKit.h>
2
+
3
+@interface RNNElementView : UIView
4
+
5
+@property (nonatomic, strong) NSString* elementId;
6
+@property (nonatomic, strong) NSString* type;
7
+@property (nonatomic, strong) NSString* resizeMode;
8
+@property (nonatomic, strong) NSNumber* interactive;
9
+@property (nonatomic, strong) UIViewController* vc;
10
+@property (nonatomic) CGPoint originalCenter;
11
+
12
+@end

+ 6
- 0
lib/ios/RNNElementView.m View File

1
+#import "RNNElementView.h"
2
+
3
+@implementation RNNElementView
4
+
5
+
6
+@end

+ 15
- 0
lib/ios/RNNInteractivePopAnimator.h View File

1
+#import <UIKit/UIKit.h>
2
+#import "RNNElementView.h"
3
+
4
+@interface RNNInteractivePopAnimator : UIPercentDrivenInteractiveTransition <UINavigationControllerDelegate, UIViewControllerAnimatedTransitioning, UIViewControllerInteractiveTransitioning>
5
+
6
+@property (nonatomic, strong) RNNElementView* topView;
7
+@property (nonatomic, strong) RNNElementView* bottomView;
8
+@property (nonatomic, strong) UIViewController* vc;
9
+@property (nonatomic) CGRect originFrame;
10
+@property CGPoint toCenter;
11
+
12
+-(instancetype)initWithTopView:(RNNElementView*)topView andBottomView:(RNNElementView*)bottomView andOriginFrame:(CGRect)originFrame andViewController:(UIViewController*)vc;
13
+-(void)handleGesture:(UIPanGestureRecognizer*)recognizer;
14
+
15
+@end

+ 175
- 0
lib/ios/RNNInteractivePopAnimator.m View File

1
+#import "RNNInteractivePopAnimator.h"
2
+#import "RNNAnimator.h"
3
+#import "RNNAnimatedView.h"
4
+#import "RNNElementView.h"
5
+#import "RNNRootViewController.h"
6
+#import "VICMAImageView.h"
7
+
8
+@interface  RNNInteractivePopAnimator()
9
+@property (nonatomic) CGRect topFrame;
10
+@property (nonatomic) CGFloat percent;
11
+@property (nonatomic) UINavigationController* nc;
12
+@property (nonatomic) UIView* imageSnapshot;
13
+@property (nonatomic) double totalTranslate;
14
+@property (nonatomic) id transitionContext;
15
+
16
+
17
+@end
18
+
19
+@implementation RNNInteractivePopAnimator
20
+
21
+-(instancetype)initWithTopView:(RNNElementView*)topView andBottomView:(RNNElementView*)bottomView andOriginFrame:(CGRect)originFrame andViewController:(UIViewController*)vc{
22
+	RNNInteractivePopAnimator* interactiveController = [[RNNInteractivePopAnimator alloc] init];
23
+	[interactiveController setTopView:topView];
24
+	[interactiveController setBottomView:bottomView];
25
+	[interactiveController setOriginFrame:originFrame];
26
+	[interactiveController setVc:vc];
27
+	[interactiveController setNc:vc.navigationController];
28
+	return interactiveController;
29
+}
30
+
31
+-(void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
32
+	[super startInteractiveTransition:transitionContext];
33
+}
34
+
35
+-(BOOL)shouldBeginInteractivePop:(CGPoint)velocity {
36
+	if (velocity.y > 0) {
37
+		return YES;
38
+	}
39
+	return NO;
40
+}
41
+
42
+-(BOOL)shouldCancelInteractivePop:(UIPanGestureRecognizer*)recognizer {
43
+	return ([recognizer velocityInView:self.imageSnapshot].y < 0 || self.totalTranslate < 0);
44
+}
45
+-(void)handleGesture:(UIPanGestureRecognizer*)recognizer {
46
+	CGPoint translation = [recognizer translationInView:self.topView];
47
+	if (recognizer.state == UIGestureRecognizerStateBegan) {
48
+		CGPoint velocity = [recognizer velocityInView:recognizer.view];
49
+		self.nc.delegate = self;
50
+		if ([self shouldBeginInteractivePop:velocity]) {
51
+			[self.nc popViewControllerAnimated:YES];
52
+		}
53
+	} else
54
+	if (recognizer.state == UIGestureRecognizerStateChanged) {
55
+		self.totalTranslate = self.totalTranslate + translation.y;
56
+		[self animateAlongsideTransition:^void(id context){
57
+			self.imageSnapshot.center = CGPointMake(self.imageSnapshot.center.x + translation.x,
58
+													self.imageSnapshot.center.y + translation.y);
59
+		}
60
+							  completion:nil];
61
+		[recognizer setTranslation:CGPointMake(0, 0) inView:self.imageSnapshot];
62
+		if (self.totalTranslate >= 0 && self.totalTranslate <= 400.0) {
63
+			[self updateInteractiveTransition:self.totalTranslate/400];
64
+		}
65
+	} else if (recognizer.state == UIGestureRecognizerStateEnded) {
66
+		if([self shouldCancelInteractivePop:recognizer]) {
67
+			[self cancelInteractiveTransition];
68
+			[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0.8 options:UIViewAnimationOptionCurveEaseOut  animations:^{
69
+				self.imageSnapshot.frame = self.topFrame;
70
+			} completion:^(BOOL finished) {
71
+				self.nc.delegate = (RNNRootViewController*)self.vc;
72
+			}];
73
+		} else {
74
+			[UIView animateWithDuration:0.3 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0.8 options:UIViewAnimationOptionCurveEaseOut  animations:^{
75
+				self.imageSnapshot.frame = self.originFrame;
76
+				self.imageSnapshot.contentMode = UIViewContentModeScaleAspectFill;
77
+				if ([self.bottomView resizeMode]) {
78
+					self.imageSnapshot.contentMode = [RNNAnimatedView contentModefromString:[self.bottomView resizeMode]];
79
+				}
80
+			} completion:^(BOOL finished) {
81
+				self.nc.delegate = nil;
82
+			}];
83
+			[self finishInteractiveTransition];
84
+		}
85
+	}
86
+}
87
+- (BOOL)animateAlongsideTransition:(void (^)(id<UIViewControllerTransitionCoordinatorContext> context))animation
88
+						completion:(void (^)(id<UIViewControllerTransitionCoordinatorContext> context))completion;{
89
+	animation(nil);
90
+	return YES;
91
+}
92
+- (void)animationEnded:(BOOL)transitionCompleted {
93
+	
94
+}
95
+
96
+- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
97
+{
98
+	return 0.7;
99
+}
100
+
101
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
102
+{
103
+	self.totalTranslate = 0;
104
+	self.transitionContext = transitionContext;
105
+	UIViewController* toVC   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
106
+	UIViewController* fromVC  = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
107
+	UIView* containerView = [transitionContext containerView];
108
+	
109
+	toVC.view.frame = fromVC.view.frame;
110
+	UIView* topViewContent = [self.topView subviews][0];
111
+	UIImage* image = [[self.topView subviews][0] image];
112
+	UIView* imageSnapshot = [[VICMAImageView alloc] initWithImage:image];
113
+	CGPoint fromSharedViewFrameOrigin = [topViewContent.superview convertPoint:topViewContent.frame.origin toView:fromVC.view];
114
+	CGRect fromOriginRect = CGRectMake(fromSharedViewFrameOrigin.x, fromSharedViewFrameOrigin.y, topViewContent.frame.size.width, topViewContent.frame.size.height);
115
+	self.topFrame = fromOriginRect;
116
+	imageSnapshot.contentMode = UIViewContentModeScaleAspectFill;
117
+	if ([self.topView resizeMode]) {
118
+		imageSnapshot.contentMode = [RNNAnimatedView contentModefromString:[self.topView resizeMode]];
119
+	}
120
+	imageSnapshot.frame = fromOriginRect;
121
+	self.imageSnapshot = imageSnapshot;
122
+	[self.bottomView setHidden:YES];
123
+	UIView* toSnapshot = [toVC.view snapshotViewAfterScreenUpdates:true];
124
+	toSnapshot.frame = fromVC.view.frame;
125
+	[containerView insertSubview:(UIView *)toSnapshot atIndex:1];
126
+	[containerView addSubview:self.imageSnapshot];
127
+	toSnapshot.alpha = 0.0;
128
+	[self.topView setHidden:YES];
129
+	[UIView animateKeyframesWithDuration:(NSTimeInterval)[self transitionDuration:transitionContext]
130
+								   delay:0
131
+								 options: UIViewKeyframeAnimationOptionAllowUserInteraction
132
+							  animations:^{
133
+								  [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:1 animations:^{
134
+									  fromVC.view.alpha = 0;
135
+									  toSnapshot.alpha = 1;
136
+								  }];
137
+							  }
138
+							  completion:^(BOOL finished) {
139
+								  [self.bottomView setHidden:NO];
140
+								  [toSnapshot removeFromSuperview];
141
+								  [self.imageSnapshot removeFromSuperview];
142
+								  self.totalTranslate = 0;
143
+								  if (![transitionContext transitionWasCancelled]) {
144
+									  [containerView addSubview: toVC.view];
145
+									  [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
146
+									  
147
+								  }
148
+								  if ([transitionContext transitionWasCancelled]) {
149
+									  [self.topView setHidden:NO];
150
+									  [containerView addSubview: fromVC.view];
151
+									  [transitionContext completeTransition:NO];
152
+								  }
153
+							  }];
154
+}
155
+
156
+- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
157
+								  animationControllerForOperation:(UINavigationControllerOperation)operation
158
+											   fromViewController:(UIViewController*)fromVC
159
+												 toViewController:(UIViewController*)toVC {
160
+	
161
+		if (operation == UINavigationControllerOperationPop) {
162
+			return self;
163
+		} else {
164
+			return nil;
165
+		}
166
+	
167
+	return nil;
168
+	
169
+}
170
+- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
171
+						 interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {
172
+	return self;
173
+}
174
+
175
+@end

+ 2
- 1
lib/ios/RNNModalManager.h View File

4
 
4
 
5
 @interface RNNModalManager : NSObject
5
 @interface RNNModalManager : NSObject
6
 
6
 
7
--(instancetype)initWithStore:(RNNStore*)store;
7
+@property (nonatomic, strong) UIViewController* toVC;
8
 
8
 
9
+-(instancetype)initWithStore:(RNNStore*)store;
9
 -(void)showModal:(UIViewController*)viewController;
10
 -(void)showModal:(UIViewController*)viewController;
10
 -(void)dismissModal:(NSString*)containerId;
11
 -(void)dismissModal:(NSString*)containerId;
11
 -(void)dismissAllModals;
12
 -(void)dismissAllModals;

+ 19
- 2
lib/ios/RNNModalManager.m View File

11
 	_store = store;
11
 	_store = store;
12
 	return self;
12
 	return self;
13
 }
13
 }
14
+-(void)waitForContentToAppearAndThen:(SEL)nameOfSelector {
15
+	[[NSNotificationCenter defaultCenter] addObserver:self
16
+											 selector:nameOfSelector
17
+												 name: @"RCTContentDidAppearNotification"
18
+											   object:nil];
19
+}
14
 
20
 
15
--(void)showModal:(UIViewController *)viewController {
21
+-(void)showModalAfterLoad:(NSDictionary*)notif {
22
+	[[NSNotificationCenter defaultCenter] removeObserver:self name:@"RCTContentDidAppearNotification" object:nil];
16
 	UIViewController *topVC = [self topPresentedVC];
23
 	UIViewController *topVC = [self topPresentedVC];
17
-	[topVC presentViewController:viewController animated:YES completion:nil];
24
+	[topVC presentViewController:self.toVC animated:YES completion:nil];
25
+}
26
+
27
+//-(void)prepareShowModal{
28
+//
29
+//}
30
+
31
+-(void)showModal:(UIViewController *)viewController {
32
+	self.toVC = viewController;
33
+//	[self prepareShowModal]
34
+	[self waitForContentToAppearAndThen:@selector(showModalAfterLoad:)];
18
 }
35
 }
19
 
36
 
20
 -(void)dismissModal:(NSString *)containerId {
37
 -(void)dismissModal:(NSString *)containerId {

+ 0
- 1
lib/ios/RNNNavigationController.h View File

1
-
2
 #import <UIKit/UIKit.h>
1
 #import <UIKit/UIKit.h>
3
 
2
 
4
 @interface RNNNavigationController : UINavigationController
3
 @interface RNNNavigationController : UINavigationController

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

5
 
5
 
6
 extern const NSInteger BLUR_STATUS_TAG;
6
 extern const NSInteger BLUR_STATUS_TAG;
7
 extern const NSInteger BLUR_TOPBAR_TAG;
7
 extern const NSInteger BLUR_TOPBAR_TAG;
8
+extern const NSInteger TOP_BAR_TRANSPARENT_TAG;
8
 
9
 
9
 @interface RNNNavigationOptions : NSObject
10
 @interface RNNNavigationOptions : NSObject
10
 
11
 
11
 @property (nonatomic, strong) NSNumber* statusBarHidden;
12
 @property (nonatomic, strong) NSNumber* statusBarHidden;
12
 @property (nonatomic, strong) NSNumber* screenBackgroundColor;
13
 @property (nonatomic, strong) NSNumber* screenBackgroundColor;
14
+@property (nonatomic, strong) NSMutableDictionary* originalTopBarImages;
15
+@property (nonatomic, strong) NSString* backButtonTransition;
13
 @property (nonatomic, strong) id orientation;
16
 @property (nonatomic, strong) id orientation;
14
 @property (nonatomic, strong) NSArray* leftButtons;
17
 @property (nonatomic, strong) NSArray* leftButtons;
15
 @property (nonatomic, strong) NSArray* rightButtons;
18
 @property (nonatomic, strong) NSArray* rightButtons;
27
 
30
 
28
 -(void)applyOn:(UIViewController*)viewController;
31
 -(void)applyOn:(UIViewController*)viewController;
29
 -(void)mergeWith:(NSDictionary*)otherOptions;
32
 -(void)mergeWith:(NSDictionary*)otherOptions;
33
+-(void)storeOriginalTopBarImages:(UIViewController*)viewController;
30
 
34
 
31
 @end
35
 @end

+ 59
- 7
lib/ios/RNNNavigationOptions.m View File

6
 
6
 
7
 const NSInteger BLUR_STATUS_TAG = 78264801;
7
 const NSInteger BLUR_STATUS_TAG = 78264801;
8
 const NSInteger BLUR_TOPBAR_TAG = 78264802;
8
 const NSInteger BLUR_TOPBAR_TAG = 78264802;
9
+const NSInteger TOP_BAR_TRANSPARENT_TAG = 78264803;
9
 
10
 
10
 @implementation RNNNavigationOptions
11
 @implementation RNNNavigationOptions
11
 
12
 
13
+
14
+
12
 -(instancetype)init {
15
 -(instancetype)init {
13
 	return [self initWithDict:@{}];
16
 	return [self initWithDict:@{}];
14
 }
17
 }
17
 	self = [super init];
20
 	self = [super init];
18
 	self.statusBarHidden = [navigationOptions objectForKey:@"statusBarHidden"];
21
 	self.statusBarHidden = [navigationOptions objectForKey:@"statusBarHidden"];
19
 	self.screenBackgroundColor = [navigationOptions objectForKey:@"screenBackgroundColor"];
22
 	self.screenBackgroundColor = [navigationOptions objectForKey:@"screenBackgroundColor"];
23
+	self.backButtonTransition = [navigationOptions objectForKey:@"backButtonTransition"];
20
 	self.orientation = [navigationOptions objectForKey:@"orientation"];
24
 	self.orientation = [navigationOptions objectForKey:@"orientation"];
21
 	self.leftButtons = [navigationOptions objectForKey:@"leftButtons"];
25
 	self.leftButtons = [navigationOptions objectForKey:@"leftButtons"];
22
 	self.rightButtons = [navigationOptions objectForKey:@"rightButtons"];
26
 	self.rightButtons = [navigationOptions objectForKey:@"rightButtons"];
51
 			viewController.navigationItem.title = self.topBar.title;
55
 			viewController.navigationItem.title = self.topBar.title;
52
 		}
56
 		}
53
 		
57
 		
58
+		if (@available(iOS 11.0, *)) {
59
+			if (self.topBar.largeTitle){
60
+				if ([self.topBar.largeTitle boolValue]) {
61
+					viewController.navigationController.navigationBar.prefersLargeTitles = YES;
62
+					viewController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeAlways;
63
+				} else {
64
+					viewController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeNever;
65
+				}
66
+			} else {
67
+				viewController.navigationController.navigationBar.prefersLargeTitles = NO;
68
+				viewController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeNever;
69
+			}
70
+		}
71
+		
72
+		
54
 		if (self.topBar.textFontFamily || self.topBar.textFontSize || self.topBar.textColor) {
73
 		if (self.topBar.textFontFamily || self.topBar.textFontSize || self.topBar.textColor) {
55
 			NSMutableDictionary* navigationBarTitleTextAttributes = [NSMutableDictionary new];
74
 			NSMutableDictionary* navigationBarTitleTextAttributes = [NSMutableDictionary new];
56
 			if (self.topBar.textColor) {
75
 			if (self.topBar.textColor) {
106
 			}
125
 			}
107
 		}
126
 		}
108
 		
127
 		
128
+		void (^disableTopBarTransparent)() = ^void(){
129
+			UIView *transparentView = [viewController.navigationController.navigationBar viewWithTag:TOP_BAR_TRANSPARENT_TAG];
130
+			if (transparentView){
131
+				[transparentView removeFromSuperview];
132
+				[viewController.navigationController.navigationBar setBackgroundImage:self.originalTopBarImages[@"backgroundImage"] forBarMetrics:UIBarMetricsDefault];
133
+				viewController.navigationController.navigationBar.shadowImage = self.originalTopBarImages[@"shadowImage"];
134
+				self.originalTopBarImages = nil;
135
+			}
136
+		};
137
+	
138
+		if (self.topBar.transparent) {
139
+			if ([self.topBar.transparent boolValue]) {
140
+				if (![viewController.navigationController.navigationBar viewWithTag:TOP_BAR_TRANSPARENT_TAG]){
141
+					[self storeOriginalTopBarImages:viewController];
142
+					[viewController.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
143
+					viewController.navigationController.navigationBar.shadowImage = [UIImage new];
144
+					UIView *transparentView = [[UIView alloc] initWithFrame:CGRectZero];
145
+					transparentView.tag = TOP_BAR_TRANSPARENT_TAG;
146
+					[viewController.navigationController.navigationBar insertSubview:transparentView atIndex:0];
147
+				}
148
+			} else {
149
+				disableTopBarTransparent();
150
+			}
151
+		} else {
152
+			disableTopBarTransparent();
153
+		}
154
+
109
 		if (self.topBar.translucent) {
155
 		if (self.topBar.translucent) {
110
 			viewController.navigationController.navigationBar.translucent = [self.topBar.translucent boolValue];
156
 			viewController.navigationController.navigationBar.translucent = [self.topBar.translucent boolValue];
111
 		}
157
 		}
112
 		
158
 		
113
-		if (self.topBar.transparent) {
114
-			[viewController.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
115
-			viewController.navigationController.navigationBar.shadowImage = [UIImage new];
116
-			UIView *transparentView = [[UIView alloc] initWithFrame:CGRectZero];
117
-			[viewController.navigationController.navigationBar insertSubview:transparentView atIndex:0];
118
-		}
119
-		
120
 		if (self.topBar.noBorder) {
159
 		if (self.topBar.noBorder) {
121
 			if ([self.topBar.noBorder boolValue]) {
160
 			if ([self.topBar.noBorder boolValue]) {
122
 				viewController.navigationController.navigationBar
161
 				viewController.navigationController.navigationBar
194
 	return supportedOrientationsMask;
233
 	return supportedOrientationsMask;
195
 }
234
 }
196
 
235
 
236
+-(void)storeOriginalTopBarImages:(UIViewController*)viewController {
237
+	NSMutableDictionary *originalTopBarImages = [@{} mutableCopy];
238
+	UIImage *bgImage = [viewController.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault];
239
+	if (bgImage != nil) {
240
+		originalTopBarImages[@"backgroundImage"] = bgImage;
241
+	}
242
+	UIImage *shadowImage = viewController.navigationController.navigationBar.shadowImage;
243
+	if (shadowImage != nil) {
244
+		originalTopBarImages[@"shadowImage"] = shadowImage;
245
+	}
246
+	self.originalTopBarImages = originalTopBarImages;
247
+}
248
+
197
 
249
 
198
 @end
250
 @end

+ 6
- 2
lib/ios/RNNNavigationStackManager.h View File

4
 
4
 
5
 @interface RNNNavigationStackManager : NSObject
5
 @interface RNNNavigationStackManager : NSObject
6
 
6
 
7
+@property (nonatomic, strong) UIViewController* fromVC;
8
+@property (nonatomic, strong) RNNRootViewController* toVC;
9
+@property (nonatomic) int loadCount;
7
 -(instancetype)initWithStore:(RNNStore*)store;
10
 -(instancetype)initWithStore:(RNNStore*)store;
8
 
11
 
9
--(void)push:(UIViewController*)newTop onTop:(NSString*)containerId;
10
--(void)pop:(NSString*)containerId;
12
+
13
+-(void)push:(UIViewController*)newTop onTop:(NSString*)containerId customAnimationData:(NSDictionary*)customAnimationData bridge:(RCTBridge*)bridge;
14
+-(void)pop:(NSString*)containerId withAnimationData:(NSDictionary*)animationData;
11
 -(void)popTo:(NSString*)containerId;
15
 -(void)popTo:(NSString*)containerId;
12
 -(void)popToRoot:(NSString*)containerId;
16
 -(void)popToRoot:(NSString*)containerId;
13
 
17
 

+ 52
- 4
lib/ios/RNNNavigationStackManager.m View File

1
 #import "RNNNavigationStackManager.h"
1
 #import "RNNNavigationStackManager.h"
2
 #import "RNNRootViewController.h"
2
 #import "RNNRootViewController.h"
3
+#import "React/RCTUIManager.h"
4
+#import "RNNAnimator.h"
3
 
5
 
6
+
7
+dispatch_queue_t RCTGetUIManagerQueue(void);
4
 @implementation RNNNavigationStackManager {
8
 @implementation RNNNavigationStackManager {
5
 	RNNStore *_store;
9
 	RNNStore *_store;
6
 }
10
 }
11
 	return self;
15
 	return self;
12
 }
16
 }
13
 
17
 
14
--(void)push:(UIViewController *)newTop onTop:(NSString *)containerId {
18
+
19
+-(void)push:(UIViewController *)newTop onTop:(NSString *)containerId customAnimationData:(NSDictionary*)customAnimationData bridge:(RCTBridge*)bridge {
15
 	UIViewController *vc = [_store findContainerForId:containerId];
20
 	UIViewController *vc = [_store findContainerForId:containerId];
16
-	[[vc navigationController] pushViewController:newTop animated:YES];
21
+	[self preparePush:newTop onTopVC:vc customAnimationData:customAnimationData bridge:bridge];
22
+	[self waitForContentToAppearAndThen:@selector(pushAfterLoad:)];
23
+}
24
+
25
+-(void)preparePush:(UIViewController *)newTop onTopVC:(UIViewController*)vc customAnimationData:(NSDictionary*)customAnimationData bridge:(RCTBridge*)bridge {
26
+	if (customAnimationData) {
27
+		RNNRootViewController* newTopRootView = (RNNRootViewController*)newTop;
28
+		self.fromVC = vc;
29
+		self.toVC = newTopRootView;
30
+		vc.navigationController.delegate = newTopRootView;
31
+		[newTopRootView.animator setupTransition:customAnimationData];
32
+		RCTUIManager *uiManager = bridge.uiManager;
33
+		CGRect screenBound = [vc.view bounds];
34
+		CGSize screenSize = screenBound.size;
35
+		[uiManager setAvailableSize:screenSize forRootView:self.toVC.view];
36
+	} else {
37
+		self.fromVC = vc;
38
+		self.toVC = (RNNRootViewController*)newTop;
39
+		vc.navigationController.delegate = nil;
40
+		self.fromVC.navigationController.interactivePopGestureRecognizer.delegate = nil;
41
+	}
17
 }
42
 }
18
 
43
 
19
--(void)pop:(NSString *)containerId {
44
+-(void)waitForContentToAppearAndThen:(SEL)nameOfSelector {
45
+	[[NSNotificationCenter defaultCenter] addObserver:self
46
+											 selector:nameOfSelector
47
+												 name: @"RCTContentDidAppearNotification"
48
+											   object:nil];
49
+}
50
+
51
+-(void)pushAfterLoad:(NSDictionary*)notif {
52
+	[[NSNotificationCenter defaultCenter] removeObserver:self name:@"RCTContentDidAppearNotification" object:nil];
53
+	[[self.fromVC navigationController] pushViewController:self.toVC animated:YES];
54
+	self.toVC = nil;
55
+	self.fromVC.navigationController.interactivePopGestureRecognizer.delegate = nil;
56
+	self.fromVC = nil;
57
+}
58
+
59
+-(void)pop:(NSString *)containerId withAnimationData:(NSDictionary *)animationData {
20
 	UIViewController* vc = [_store findContainerForId:containerId];
60
 	UIViewController* vc = [_store findContainerForId:containerId];
21
 	UINavigationController* nvc = [vc navigationController];
61
 	UINavigationController* nvc = [vc navigationController];
22
 	if ([nvc topViewController] == vc) {
62
 	if ([nvc topViewController] == vc) {
23
-		[nvc popViewControllerAnimated:YES];
63
+		if (animationData) {
64
+			RNNRootViewController* RNNVC = (RNNRootViewController*)vc;
65
+			nvc.delegate = RNNVC;
66
+			[RNNVC.animator setupTransition:animationData];
67
+			[nvc popViewControllerAnimated:YES];
68
+		} else {
69
+			nvc.delegate = nil;
70
+			[nvc popViewControllerAnimated:YES];
71
+		}
24
 	} else {
72
 	} else {
25
 		NSMutableArray * vcs = nvc.viewControllers.mutableCopy;
73
 		NSMutableArray * vcs = nvc.viewControllers.mutableCopy;
26
 		[vcs removeObject:vc];
74
 		[vcs removeObject:vc];

+ 3
- 3
lib/ios/RNNRootViewController.h View File

5
 #import "RNNRootViewCreator.h"
5
 #import "RNNRootViewCreator.h"
6
 #import "RNNEventEmitter.h"
6
 #import "RNNEventEmitter.h"
7
 #import "RNNNavigationOptions.h"
7
 #import "RNNNavigationOptions.h"
8
-
9
-@interface RNNRootViewController : UIViewController
10
-
8
+#import "RNNAnimator.h"
9
+@interface RNNRootViewController : UIViewController	<UINavigationControllerDelegate>
11
 @property (nonatomic, strong) RNNNavigationOptions* navigationOptions;
10
 @property (nonatomic, strong) RNNNavigationOptions* navigationOptions;
11
+@property (nonatomic, strong) RNNAnimator* animator;
12
 @property (nonatomic, strong) RNNEventEmitter *eventEmitter;
12
 @property (nonatomic, strong) RNNEventEmitter *eventEmitter;
13
 @property (nonatomic, strong) NSString* containerId;
13
 @property (nonatomic, strong) NSString* containerId;
14
 
14
 

+ 35
- 3
lib/ios/RNNRootViewController.m View File

1
 
1
 
2
 #import "RNNRootViewController.h"
2
 #import "RNNRootViewController.h"
3
 #import <React/RCTConvert.h>
3
 #import <React/RCTConvert.h>
4
+#import "RNNAnimator.h"
4
 #import "RNNNavigationButtons.h"
5
 #import "RNNNavigationButtons.h"
5
 
6
 
6
 @interface RNNRootViewController()
7
 @interface RNNRootViewController()
28
 											 selector:@selector(onJsReload)
29
 											 selector:@selector(onJsReload)
29
 												 name:RCTJavaScriptWillStartLoadingNotification
30
 												 name:RCTJavaScriptWillStartLoadingNotification
30
 											   object:nil];
31
 											   object:nil];
31
-	
32
+	self.animator = [[RNNAnimator alloc] init];
33
+	self.navigationController.modalPresentationStyle = UIModalPresentationCustom;
34
+	self.navigationController.delegate = self;
32
 	self.navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self];
35
 	self.navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self];
33
-	
34
 	return self;
36
 	return self;
35
 }
37
 }
36
-
38
+	
37
 -(void)viewWillAppear:(BOOL)animated{
39
 -(void)viewWillAppear:(BOOL)animated{
38
 	[super viewWillAppear:animated];
40
 	[super viewWillAppear:animated];
39
 	[self.navigationOptions applyOn:self];
41
 	[self.navigationOptions applyOn:self];
40
 	[self applyNavigationButtons];
42
 	[self applyNavigationButtons];
41
 }
43
 }
42
 
44
 
45
+- (void)viewDidLoad {
46
+	[super viewDidLoad];
47
+}
48
+
43
 - (BOOL)prefersStatusBarHidden {
49
 - (BOOL)prefersStatusBarHidden {
44
 	if ([self.navigationOptions.statusBarHidden boolValue]) {
50
 	if ([self.navigationOptions.statusBarHidden boolValue]) {
45
 		return YES;
51
 		return YES;
71
 	[self.eventEmitter sendContainerDidDisappear:self.containerId];
77
 	[self.eventEmitter sendContainerDidDisappear:self.containerId];
72
 }
78
 }
73
 
79
 
80
+- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
81
+	RNNRootViewController* vc =  (RNNRootViewController*)viewController;
82
+	if (![vc.navigationOptions.backButtonTransition isEqualToString:@"custom"]){
83
+		navigationController.delegate = nil;
84
+	}
85
+}
86
+
87
+- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
88
+								  animationControllerForOperation:(UINavigationControllerOperation)operation
89
+											   fromViewController:(UIViewController*)fromVC
90
+												 toViewController:(UIViewController*)toVC {
91
+{
92
+	if (operation == UINavigationControllerOperationPush) {
93
+		return self.animator;
94
+	} else if (operation == UINavigationControllerOperationPop) {
95
+		return self.animator;
96
+	} else {
97
+		return nil;
98
+	}
99
+}
100
+	return nil;
101
+
102
+}
103
+
104
+
105
+
74
 -(void) applyNavigationButtons{
106
 -(void) applyNavigationButtons{
75
 	[self.navigationButtons applyLeftButtons:self.navigationOptions.leftButtons rightButtons:self.navigationOptions.rightButtons];
107
 	[self.navigationButtons applyLeftButtons:self.navigationOptions.leftButtons rightButtons:self.navigationOptions.rightButtons];
76
 }
108
 }

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

17
 @property (nonatomic, strong) NSNumber* noBorder;
17
 @property (nonatomic, strong) NSNumber* noBorder;
18
 @property (nonatomic, strong) NSNumber* blur;
18
 @property (nonatomic, strong) NSNumber* blur;
19
 @property (nonatomic, strong) NSNumber* animateHide;
19
 @property (nonatomic, strong) NSNumber* animateHide;
20
+@property (nonatomic, strong) NSNumber* largeTitle;
20
 
21
 
21
 -(instancetype)init;
22
 -(instancetype)init;
22
 -(instancetype)initWithDict:(NSDictionary *)topBarOptions;
23
 -(instancetype)initWithDict:(NSDictionary *)topBarOptions;

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

22
 	self.transparent = [topBarOptions valueForKey:@"transparent"];
22
 	self.transparent = [topBarOptions valueForKey:@"transparent"];
23
 	self.noBorder = [topBarOptions valueForKey:@"noBorder"];
23
 	self.noBorder = [topBarOptions valueForKey:@"noBorder"];
24
 	self.animateHide =[topBarOptions valueForKey:@"animateHide"];
24
 	self.animateHide =[topBarOptions valueForKey:@"animateHide"];
25
+	self.largeTitle =[topBarOptions valueForKey:@"largeTitle"];
25
 	
26
 	
26
 	return self;
27
 	return self;
27
 }
28
 }

+ 33
- 0
lib/ios/RNNTransitionStateHolder.h View File

1
+#import <Foundation/Foundation.h>
2
+#import "RNNElementView.h"
3
+#import "RNNViewLocation.h"
4
+#import "RNNAnimatedView.h"
5
+
6
+@class RNNAnimatedView;
7
+@class RNNViewLocation;
8
+@interface RNNTransitionStateHolder : NSObject
9
+
10
+@property (nonatomic) double startAlpha;
11
+@property (nonatomic) double endAlpha;
12
+@property (nonatomic) BOOL interactivePop;
13
+@property (nonatomic) double duration;
14
+@property (nonatomic) double springVelocity;
15
+@property (nonatomic) double springDamping;
16
+@property (nonatomic) double startDelay;
17
+@property (nonatomic, strong) RNNElementView* fromElement;
18
+@property (nonatomic, strong) NSString* fromElementType;
19
+@property (nonatomic) UIViewContentMode fromElementResizeMode;
20
+@property (nonatomic, strong) RNNElementView* toElement;
21
+@property (nonatomic, strong) NSString* fromId;
22
+@property (nonatomic, strong) NSString* toId;
23
+@property (nonatomic, strong) RNNAnimatedView* animatedView;
24
+@property (nonatomic, strong) NSString* isSharedElementTransition;
25
+@property (nonatomic, strong) RNNViewLocation* locations;
26
+@property (nonatomic) BOOL isFromVC;
27
+@property (nonatomic) double startY;
28
+@property (nonatomic) double endY;
29
+@property (nonatomic) double startX;
30
+@property (nonatomic) double endX;
31
+
32
+-(instancetype)initWithTransition:(NSDictionary*)transition;
33
+@end

+ 32
- 0
lib/ios/RNNTransitionStateHolder.m View File

1
+#import "RNNTransitionStateHolder.h"
2
+#import "RNNUtils.h"
3
+#import "RNNElementFinder.h"
4
+
5
+@implementation RNNTransitionStateHolder
6
+
7
+-(instancetype)initWithTransition:(NSDictionary *)transition {
8
+	self = [super init];
9
+	self.springDamping = [RNNUtils getDoubleOrKey:transition withKey:@"springDamping" withDefault:0.85];
10
+	self.springVelocity = [RNNUtils getDoubleOrKey:transition withKey:@"springVelocity" withDefault:0.8];
11
+	self.startDelay = [RNNUtils getDoubleOrKey:transition withKey:@"startDelay" withDefault:0];
12
+	self.duration = [RNNUtils getDoubleOrKey:transition withKey:@"duration" withDefault:1];
13
+	self.startAlpha = [RNNUtils getDoubleOrKey:transition withKey:@"startAlpha" withDefault:1];
14
+	self.endAlpha = [RNNUtils getDoubleOrKey:transition withKey:@"endAlpha" withDefault:1];
15
+	self.interactivePop = [RNNUtils getBoolOrKey:transition withKey:@"interactivePop" withDefault:NO];
16
+	self.startX = [RNNUtils getDoubleOrKey:transition withKey:@"startX" withDefault:0];
17
+	self.startY = [RNNUtils getDoubleOrKey:transition withKey:@"startY" withDefault:0];
18
+	self.endX = [RNNUtils getDoubleOrKey:transition withKey:@"endX" withDefault:0];
19
+	self.endY = [RNNUtils getDoubleOrKey:transition withKey:@"endY" withDefault:0];
20
+	self.fromId = [transition objectForKey:@"fromId"];
21
+	self.toId = [transition objectForKey:@"toId"];
22
+	self.fromElement = nil;
23
+	self.fromElementType = nil;
24
+	self.fromElementResizeMode = UIViewContentModeScaleAspectFill;
25
+	self.toElement = nil;
26
+	self.animatedView = nil;
27
+	self.locations  = nil; 
28
+	self.isSharedElementTransition = [transition objectForKey:@"type"];
29
+	return self;
30
+}
31
+
32
+@end

+ 8
- 0
lib/ios/RNNUtils.h View File

1
+#import <Foundation/Foundation.h>
2
+
3
+@interface RNNUtils : NSObject
4
+
5
++(double)getDoubleOrKey:(NSDictionary*)dict withKey:(NSString*)key withDefault:(double)defaultResult;
6
++(BOOL)getBoolOrKey:(NSDictionary*)dict withKey:(NSString*)key withDefault:(BOOL)defaultResult;
7
++(id)getObjectOrKey:(NSDictionary*)dict withKey:(NSString*)key withDefault:(id)defaultResult;
8
+@end

+ 25
- 0
lib/ios/RNNUtils.m View File

1
+#import "RNNUtils.h"
2
+
3
+@implementation RNNUtils
4
++(double)getDoubleOrKey:(NSDictionary*)dict withKey:(NSString*)key withDefault:(double)defaultResult {
5
+	if ([dict objectForKey:key]) {
6
+		return [dict[key] doubleValue];
7
+	} else {
8
+		return defaultResult;
9
+	}
10
+}
11
++(BOOL)getBoolOrKey:(NSDictionary*)dict withKey:(NSString*)key withDefault:(BOOL)defaultResult {
12
+	if ([dict objectForKey:key]) {
13
+		return [dict[key] boolValue];
14
+	} else {
15
+		return defaultResult;
16
+	}
17
+}
18
++(id)getObjectOrKey:(NSDictionary*)dict withKey:(NSString*)key withDefault:(id)defaultResult {
19
+	if ([dict objectForKey:key]) {
20
+		return dict[key];
21
+	} else {
22
+		return defaultResult;
23
+	}
24
+}
25
+@end

+ 27
- 0
lib/ios/RNNViewLocation.h View File

1
+//
2
+//  RNNViewLocation.h
3
+//  ReactNativeNavigation
4
+//
5
+//  Created by Elad Bogomolny on 03/10/2017.
6
+//  Copyright © 2017 Wix. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import <UIKit/UIKit.h>
11
+#import "RNNTransitionStateHolder.h"
12
+
13
+@class RNNTransitionStateHolder;
14
+@interface RNNViewLocation : NSObject
15
+@property (nonatomic) CGRect fromFrame;
16
+@property (nonatomic) CGPoint fromCenter;
17
+@property (nonatomic) CGSize fromSize;
18
+@property (nonatomic) CGRect toFrame;
19
+@property (nonatomic) CGPoint toCenter;
20
+@property (nonatomic) CGSize toSize;
21
+@property (nonatomic) CGAffineTransform transform;
22
+@property (nonatomic) CGAffineTransform transformBack;
23
+
24
+-(instancetype)initWithTransition:(RNNTransitionStateHolder*)transition andVC:(UIViewController*)vc;
25
+-(CGRect)frameFromSuperViewController:(UIView*)view andVC:(UIViewController*)vc;
26
+-(CGPoint)centerFromSuperViewController:(UIView*)view andVC:(UIViewController*)vc;
27
+@end

+ 49
- 0
lib/ios/RNNViewLocation.m View File

1
+#import "RNNViewLocation.h"
2
+
3
+@implementation RNNViewLocation
4
+-(instancetype)initWithTransition:(RNNTransitionStateHolder*)transition andVC:(UIViewController*)vc {
5
+	self = [super init];
6
+	self.fromFrame = [self frameFromSuperViewController:[transition.fromElement subviews][0] andVC:vc];
7
+	CGSize fromSize = self.fromFrame.size;
8
+	CGPoint fromCenter = [self centerFromSuperViewController:[transition.fromElement subviews][0] andVC:vc];
9
+	fromCenter.x = fromCenter.x + transition.startX;
10
+	fromCenter.y = fromCenter.y + transition.startY;
11
+	self.fromCenter = fromCenter;
12
+	CGRect toFrame = [self frameFromSuperViewController:[transition.fromElement subviews][0] andVC:vc];
13
+	CGSize toSize = self.fromFrame.size;
14
+	CGPoint toCenter = [self centerFromSuperViewController:[transition.fromElement subviews][0] andVC:vc];
15
+	if (transition.toElement) {
16
+	   toFrame = [self frameFromSuperViewController:[transition.toElement subviews][0] andVC:vc];
17
+		toSize = toFrame.size;
18
+		toCenter = [self centerFromSuperViewController:[transition.toElement subviews][0] andVC:vc];
19
+	}
20
+	toCenter.x = toCenter.x + transition.endX;
21
+	toCenter.y = toCenter.y + transition.endY;
22
+	
23
+	CGAffineTransform transform = CGAffineTransformMakeScale(toSize.width/fromSize.width ,toSize.height/fromSize.height);
24
+	CGAffineTransform transformBack = CGAffineTransformMakeScale(fromSize.width/toSize.width ,fromSize.height/toSize.height);
25
+	self.toFrame = toFrame;
26
+	self.fromSize = fromSize;
27
+	self.toSize = toSize;
28
+	self.toCenter = toCenter;
29
+	self.transform = transform;
30
+	self.transformBack = transformBack;
31
+	return self;
32
+}
33
+
34
+-(CGRect)frameFromSuperViewController:(UIView*)view andVC:(UIViewController*)vc{
35
+	CGPoint sharedViewFrameOrigin = [view.superview convertPoint:view.frame.origin toView:vc.view];
36
+	CGRect originRect = CGRectMake(sharedViewFrameOrigin.x, sharedViewFrameOrigin.y, view.frame.size.width, view.frame.size.height);
37
+	return originRect;
38
+}
39
+
40
+-(CGPoint)centerFromSuperViewController:(UIView*)view andVC:(UIViewController*)vc{
41
+	CGPoint sharedViewFrameOrigin = [view.superview convertPoint:view.frame.origin toView:vc.view];
42
+	CGRect originRect = CGRectMake(sharedViewFrameOrigin.x, sharedViewFrameOrigin.y, view.frame.size.width, view.frame.size.height);
43
+	CGFloat x = originRect.origin.x + view.frame.size.width/2;
44
+	CGFloat y = originRect.origin.y + view.frame.size.height/2;
45
+	CGPoint center = CGPointMake(x, y);
46
+	return center;
47
+}
48
+
49
+@end

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

70
 	
70
 	
71
 	id<RNNRootViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
71
 	id<RNNRootViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
72
 	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator store:_store eventEmitter:eventEmitter];
72
 	RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator store:_store eventEmitter:eventEmitter];
73
-	_commandsHandler = [[RNNCommandsHandler alloc] initWithStore:_store controllerFactory:controllerFactory];
73
+	_commandsHandler = [[RNNCommandsHandler alloc] initWithStore:_store controllerFactory:controllerFactory andBridge:bridge];
74
 	RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
74
 	RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
75
 	
75
 	
76
 	return @[bridgeModule,eventEmitter];
76
 	return @[bridgeModule,eventEmitter];

+ 122
- 1
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj View File

99
 		7BEF0D1D1E43771B003E96B0 /* RNNLayoutNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BEF0D1B1E43771B003E96B0 /* RNNLayoutNode.m */; };
99
 		7BEF0D1D1E43771B003E96B0 /* RNNLayoutNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BEF0D1B1E43771B003E96B0 /* RNNLayoutNode.m */; };
100
 		A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = A7626BFC1FC2FB2C00492FB8 /* RNNTopBarOptions.m */; };
100
 		A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = A7626BFC1FC2FB2C00492FB8 /* RNNTopBarOptions.m */; };
101
 		A7626C011FC5796200492FB8 /* RNNTabBarOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = A7626C001FC5796200492FB8 /* RNNTabBarOptions.m */; };
101
 		A7626C011FC5796200492FB8 /* RNNTabBarOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = A7626C001FC5796200492FB8 /* RNNTabBarOptions.m */; };
102
-		A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = A7626BFC1FC2FB2C00492FB8 /* RNNTopBarOptions.m */; };
102
+		E8367B801F7A8A4700675C05 /* VICMAImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = E8367B7E1F7A8A4700675C05 /* VICMAImageView.h */; };
103
+		E8367B811F7A8A4700675C05 /* VICMAImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = E8367B7F1F7A8A4700675C05 /* VICMAImageView.m */; };
103
 		E83BAD681F2734B500A9F3DD /* RNNNavigationOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD671F2734B500A9F3DD /* RNNNavigationOptionsTest.m */; };
104
 		E83BAD681F2734B500A9F3DD /* RNNNavigationOptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD671F2734B500A9F3DD /* RNNNavigationOptionsTest.m */; };
104
 		E83BAD6B1F27363A00A9F3DD /* RNNNavigationOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD6A1F27363A00A9F3DD /* RNNNavigationOptions.m */; };
105
 		E83BAD6B1F27363A00A9F3DD /* RNNNavigationOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD6A1F27363A00A9F3DD /* RNNNavigationOptions.m */; };
105
 		E83BAD791F27416B00A9F3DD /* RNNRootViewControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD781F27416B00A9F3DD /* RNNRootViewControllerTest.m */; };
106
 		E83BAD791F27416B00A9F3DD /* RNNRootViewControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD781F27416B00A9F3DD /* RNNRootViewControllerTest.m */; };
106
 		E83BAD7C1F27643000A9F3DD /* RNNTestRootViewCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */; };
107
 		E83BAD7C1F27643000A9F3DD /* RNNTestRootViewCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */; };
108
+		E8A430111F9CB87B00B61A20 /* RNNAnimatedView.h in Headers */ = {isa = PBXBuildFile; fileRef = E8A4300F1F9CB87B00B61A20 /* RNNAnimatedView.h */; };
109
+		E8A430121F9CB87B00B61A20 /* RNNAnimatedView.m in Sources */ = {isa = PBXBuildFile; fileRef = E8A430101F9CB87B00B61A20 /* RNNAnimatedView.m */; };
110
+		E8A5CD521F464F0400E89D0D /* RNNAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = E8A5CD501F464F0400E89D0D /* RNNAnimator.h */; };
111
+		E8A5CD531F464F0400E89D0D /* RNNAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = E8A5CD511F464F0400E89D0D /* RNNAnimator.m */; };
112
+		E8A5CD5A1F48CCC300E89D0D /* RNNNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = E8A5CD581F48CCC300E89D0D /* RNNNavigationController.h */; };
113
+		E8A5CD621F49114F00E89D0D /* RNNElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E8A5CD601F49114F00E89D0D /* RNNElement.h */; };
114
+		E8A5CD631F49114F00E89D0D /* RNNElement.m in Sources */ = {isa = PBXBuildFile; fileRef = E8A5CD611F49114F00E89D0D /* RNNElement.m */; };
115
+		E8AEDB3C1F55A1C2000F5A6A /* RNNElementView.h in Headers */ = {isa = PBXBuildFile; fileRef = E8AEDB3A1F55A1C2000F5A6A /* RNNElementView.h */; };
116
+		E8AEDB3D1F55A1C2000F5A6A /* RNNElementView.m in Sources */ = {isa = PBXBuildFile; fileRef = E8AEDB3B1F55A1C2000F5A6A /* RNNElementView.m */; };
117
+		E8AEDB4A1F5C0BAF000F5A6A /* RNNInteractivePopAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = E8AEDB481F5C0BAF000F5A6A /* RNNInteractivePopAnimator.h */; };
118
+		E8AEDB4B1F5C0BAF000F5A6A /* RNNInteractivePopAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = E8AEDB491F5C0BAF000F5A6A /* RNNInteractivePopAnimator.m */; };
119
+		E8DA243D1F973C1900CD552B /* RNNTransitionStateHolderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E8DA243C1F973C1900CD552B /* RNNTransitionStateHolderTest.m */; };
120
+		E8DA24401F97459B00CD552B /* RNNElementFinder.h in Headers */ = {isa = PBXBuildFile; fileRef = E8DA243E1F97459B00CD552B /* RNNElementFinder.h */; };
121
+		E8DA24411F97459B00CD552B /* RNNElementFinder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8DA243F1F97459B00CD552B /* RNNElementFinder.m */; };
122
+		E8E5182E1F83A48B000467AC /* RNNTransitionStateHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = E8E5182C1F83A48B000467AC /* RNNTransitionStateHolder.h */; };
123
+		E8E5182F1F83A48B000467AC /* RNNTransitionStateHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8E5182D1F83A48B000467AC /* RNNTransitionStateHolder.m */; };
124
+		E8E518321F83B3E0000467AC /* RNNUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = E8E518301F83B3E0000467AC /* RNNUtils.h */; };
125
+		E8E518331F83B3E0000467AC /* RNNUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E8E518311F83B3E0000467AC /* RNNUtils.m */; };
126
+		E8E518361F83B94A000467AC /* RNNViewLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = E8E518341F83B94A000467AC /* RNNViewLocation.h */; };
127
+		E8E518371F83B94A000467AC /* RNNViewLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = E8E518351F83B94A000467AC /* RNNViewLocation.m */; };
107
 /* End PBXBuildFile section */
128
 /* End PBXBuildFile section */
108
 
129
 
109
 /* Begin PBXContainerItemProxy section */
130
 /* Begin PBXContainerItemProxy section */
228
 		A7626BFF1FC578AB00492FB8 /* RNNTabBarOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTabBarOptions.h; sourceTree = "<group>"; };
249
 		A7626BFF1FC578AB00492FB8 /* RNNTabBarOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTabBarOptions.h; sourceTree = "<group>"; };
229
 		A7626C001FC5796200492FB8 /* RNNTabBarOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTabBarOptions.m; sourceTree = "<group>"; };
250
 		A7626C001FC5796200492FB8 /* RNNTabBarOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTabBarOptions.m; sourceTree = "<group>"; };
230
 		D8AFADBD1BEE6F3F00A4592D /* libReactNativeNavigation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativeNavigation.a; sourceTree = BUILT_PRODUCTS_DIR; };
251
 		D8AFADBD1BEE6F3F00A4592D /* libReactNativeNavigation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativeNavigation.a; sourceTree = BUILT_PRODUCTS_DIR; };
252
+		E8367B7E1F7A8A4700675C05 /* VICMAImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VICMAImageView.h; sourceTree = "<group>"; };
253
+		E8367B7F1F7A8A4700675C05 /* VICMAImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VICMAImageView.m; sourceTree = "<group>"; };
231
 		E83BAD671F2734B500A9F3DD /* RNNNavigationOptionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNNavigationOptionsTest.m; sourceTree = "<group>"; };
254
 		E83BAD671F2734B500A9F3DD /* RNNNavigationOptionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNNavigationOptionsTest.m; sourceTree = "<group>"; };
232
 		E83BAD691F27362500A9F3DD /* RNNNavigationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNNavigationOptions.h; sourceTree = "<group>"; };
255
 		E83BAD691F27362500A9F3DD /* RNNNavigationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNNavigationOptions.h; sourceTree = "<group>"; };
233
 		E83BAD6A1F27363A00A9F3DD /* RNNNavigationOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNNavigationOptions.m; sourceTree = "<group>"; };
256
 		E83BAD6A1F27363A00A9F3DD /* RNNNavigationOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNNavigationOptions.m; sourceTree = "<group>"; };
234
 		E83BAD781F27416B00A9F3DD /* RNNRootViewControllerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNRootViewControllerTest.m; sourceTree = "<group>"; };
257
 		E83BAD781F27416B00A9F3DD /* RNNRootViewControllerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNRootViewControllerTest.m; sourceTree = "<group>"; };
235
 		E83BAD7A1F27643000A9F3DD /* RNNTestRootViewCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNTestRootViewCreator.h; sourceTree = "<group>"; };
258
 		E83BAD7A1F27643000A9F3DD /* RNNTestRootViewCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNTestRootViewCreator.h; sourceTree = "<group>"; };
236
 		E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNTestRootViewCreator.m; sourceTree = "<group>"; };
259
 		E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNTestRootViewCreator.m; sourceTree = "<group>"; };
260
+		E8A4300F1F9CB87B00B61A20 /* RNNAnimatedView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNAnimatedView.h; sourceTree = "<group>"; };
261
+		E8A430101F9CB87B00B61A20 /* RNNAnimatedView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNAnimatedView.m; sourceTree = "<group>"; };
262
+		E8A5CD501F464F0400E89D0D /* RNNAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNAnimator.h; sourceTree = "<group>"; };
263
+		E8A5CD511F464F0400E89D0D /* RNNAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNAnimator.m; sourceTree = "<group>"; };
264
+		E8A5CD581F48CCC300E89D0D /* RNNNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNNavigationController.h; sourceTree = "<group>"; };
265
+		E8A5CD601F49114F00E89D0D /* RNNElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNElement.h; sourceTree = "<group>"; };
266
+		E8A5CD611F49114F00E89D0D /* RNNElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNElement.m; sourceTree = "<group>"; };
267
+		E8AEDB3A1F55A1C2000F5A6A /* RNNElementView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNElementView.h; sourceTree = "<group>"; };
268
+		E8AEDB3B1F55A1C2000F5A6A /* RNNElementView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNElementView.m; sourceTree = "<group>"; };
269
+		E8AEDB481F5C0BAF000F5A6A /* RNNInteractivePopAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNInteractivePopAnimator.h; sourceTree = "<group>"; };
270
+		E8AEDB491F5C0BAF000F5A6A /* RNNInteractivePopAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNInteractivePopAnimator.m; sourceTree = "<group>"; };
271
+		E8DA243C1F973C1900CD552B /* RNNTransitionStateHolderTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTransitionStateHolderTest.m; sourceTree = "<group>"; };
272
+		E8DA243E1F97459B00CD552B /* RNNElementFinder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNElementFinder.h; sourceTree = "<group>"; };
273
+		E8DA243F1F97459B00CD552B /* RNNElementFinder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNElementFinder.m; sourceTree = "<group>"; };
274
+		E8E5182C1F83A48B000467AC /* RNNTransitionStateHolder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTransitionStateHolder.h; sourceTree = "<group>"; };
275
+		E8E5182D1F83A48B000467AC /* RNNTransitionStateHolder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTransitionStateHolder.m; sourceTree = "<group>"; };
276
+		E8E518301F83B3E0000467AC /* RNNUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNUtils.h; sourceTree = "<group>"; };
277
+		E8E518311F83B3E0000467AC /* RNNUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNUtils.m; sourceTree = "<group>"; };
278
+		E8E518341F83B94A000467AC /* RNNViewLocation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNViewLocation.h; sourceTree = "<group>"; };
279
+		E8E518351F83B94A000467AC /* RNNViewLocation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNViewLocation.m; sourceTree = "<group>"; };
237
 /* End PBXFileReference section */
280
 /* End PBXFileReference section */
238
 
281
 
239
 /* Begin PBXFrameworksBuildPhase section */
282
 /* Begin PBXFrameworksBuildPhase section */
272
 		214545271F4DC7ED006E8DA1 /* Helpers */ = {
315
 		214545271F4DC7ED006E8DA1 /* Helpers */ = {
273
 			isa = PBXGroup;
316
 			isa = PBXGroup;
274
 			children = (
317
 			children = (
318
+				E8E518301F83B3E0000467AC /* RNNUtils.h */,
319
+				E8E518311F83B3E0000467AC /* RNNUtils.m */,
275
 				214545281F4DC81F006E8DA1 /* RCTHelpers.h */,
320
 				214545281F4DC81F006E8DA1 /* RCTHelpers.h */,
276
 				214545291F4DC85F006E8DA1 /* RCTHelpers.m */,
321
 				214545291F4DC85F006E8DA1 /* RCTHelpers.m */,
277
 			);
322
 			);
346
 		7B1E4C4B1E2D173700C3A525 /* Controllers */ = {
391
 		7B1E4C4B1E2D173700C3A525 /* Controllers */ = {
347
 			isa = PBXGroup;
392
 			isa = PBXGroup;
348
 			children = (
393
 			children = (
394
+				E8AEDB471F584175000F5A6A /* Components */,
395
+				E8AEDB461F58414D000F5A6A /* Animations */,
349
 				261F0E621E6EC94900989DE2 /* RNNModalManager.h */,
396
 				261F0E621E6EC94900989DE2 /* RNNModalManager.h */,
350
 				261F0E631E6EC94900989DE2 /* RNNModalManager.m */,
397
 				261F0E631E6EC94900989DE2 /* RNNModalManager.m */,
351
 				261F0E681E6F028A00989DE2 /* RNNNavigationStackManager.h */,
398
 				261F0E681E6F028A00989DE2 /* RNNNavigationStackManager.h */,
396
 				E83BAD781F27416B00A9F3DD /* RNNRootViewControllerTest.m */,
443
 				E83BAD781F27416B00A9F3DD /* RNNRootViewControllerTest.m */,
397
 				E83BAD7A1F27643000A9F3DD /* RNNTestRootViewCreator.h */,
444
 				E83BAD7A1F27643000A9F3DD /* RNNTestRootViewCreator.h */,
398
 				E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */,
445
 				E83BAD7B1F27643000A9F3DD /* RNNTestRootViewCreator.m */,
446
+				E8DA243C1F973C1900CD552B /* RNNTransitionStateHolderTest.m */,
399
 			);
447
 			);
400
 			path = ReactNativeNavigationTests;
448
 			path = ReactNativeNavigationTests;
401
 			sourceTree = "<group>";
449
 			sourceTree = "<group>";
448
 				7B49FEBC1E95090800DEB3EA /* ReactNativeNavigationTests */,
496
 				7B49FEBC1E95090800DEB3EA /* ReactNativeNavigationTests */,
449
 				D8AFADBE1BEE6F3F00A4592D /* Products */,
497
 				D8AFADBE1BEE6F3F00A4592D /* Products */,
450
 				7B49FED01E950A7A00DEB3EA /* Frameworks */,
498
 				7B49FED01E950A7A00DEB3EA /* Frameworks */,
499
+				E8367B791F77BA1F00675C05 /* Recovered References */,
451
 			);
500
 			);
452
 			sourceTree = "<group>";
501
 			sourceTree = "<group>";
453
 			tabWidth = 4;
502
 			tabWidth = 4;
463
 			name = Products;
512
 			name = Products;
464
 			sourceTree = "<group>";
513
 			sourceTree = "<group>";
465
 		};
514
 		};
515
+		E8367B791F77BA1F00675C05 /* Recovered References */ = {
516
+			isa = PBXGroup;
517
+			children = (
518
+				E8A5CD581F48CCC300E89D0D /* RNNNavigationController.h */,
519
+			);
520
+			name = "Recovered References";
521
+			sourceTree = "<group>";
522
+		};
523
+		E8AEDB461F58414D000F5A6A /* Animations */ = {
524
+			isa = PBXGroup;
525
+			children = (
526
+				E8A5CD501F464F0400E89D0D /* RNNAnimator.h */,
527
+				E8A5CD511F464F0400E89D0D /* RNNAnimator.m */,
528
+				E8AEDB481F5C0BAF000F5A6A /* RNNInteractivePopAnimator.h */,
529
+				E8AEDB491F5C0BAF000F5A6A /* RNNInteractivePopAnimator.m */,
530
+				E8E5182C1F83A48B000467AC /* RNNTransitionStateHolder.h */,
531
+				E8E5182D1F83A48B000467AC /* RNNTransitionStateHolder.m */,
532
+				E8E518341F83B94A000467AC /* RNNViewLocation.h */,
533
+				E8E518351F83B94A000467AC /* RNNViewLocation.m */,
534
+				E8DA243E1F97459B00CD552B /* RNNElementFinder.h */,
535
+				E8DA243F1F97459B00CD552B /* RNNElementFinder.m */,
536
+			);
537
+			name = Animations;
538
+			sourceTree = "<group>";
539
+		};
540
+		E8AEDB471F584175000F5A6A /* Components */ = {
541
+			isa = PBXGroup;
542
+			children = (
543
+				E8A5CD601F49114F00E89D0D /* RNNElement.h */,
544
+				E8A5CD611F49114F00E89D0D /* RNNElement.m */,
545
+				E8AEDB3A1F55A1C2000F5A6A /* RNNElementView.h */,
546
+				E8AEDB3B1F55A1C2000F5A6A /* RNNElementView.m */,
547
+				E8367B7E1F7A8A4700675C05 /* VICMAImageView.h */,
548
+				E8367B7F1F7A8A4700675C05 /* VICMAImageView.m */,
549
+				E8A4300F1F9CB87B00B61A20 /* RNNAnimatedView.h */,
550
+				E8A430101F9CB87B00B61A20 /* RNNAnimatedView.m */,
551
+			);
552
+			name = Components;
553
+			sourceTree = "<group>";
554
+		};
466
 /* End PBXGroup section */
555
 /* End PBXGroup section */
467
 
556
 
468
 /* Begin PBXHeadersBuildPhase section */
557
 /* Begin PBXHeadersBuildPhase section */
473
 				261F0E6A1E6F028A00989DE2 /* RNNNavigationStackManager.h in Headers */,
562
 				261F0E6A1E6F028A00989DE2 /* RNNNavigationStackManager.h in Headers */,
474
 				26916C981E4B9E7700D13680 /* RNNReactRootViewCreator.h in Headers */,
563
 				26916C981E4B9E7700D13680 /* RNNReactRootViewCreator.h in Headers */,
475
 				263905B01E4C6F440023D7D3 /* MMDrawerController+Subclass.h in Headers */,
564
 				263905B01E4C6F440023D7D3 /* MMDrawerController+Subclass.h in Headers */,
565
+				E8AEDB4A1F5C0BAF000F5A6A /* RNNInteractivePopAnimator.h in Headers */,
476
 				7B1126A41E2D2B6C00F9B03B /* ReactNativeNavigation.h in Headers */,
566
 				7B1126A41E2D2B6C00F9B03B /* ReactNativeNavigation.h in Headers */,
477
 				263905B71E4C6F440023D7D3 /* UIViewController+MMDrawerController.h in Headers */,
567
 				263905B71E4C6F440023D7D3 /* UIViewController+MMDrawerController.h in Headers */,
478
 				263905BB1E4C6F440023D7D3 /* RCCDrawerHelper.h in Headers */,
568
 				263905BB1E4C6F440023D7D3 /* RCCDrawerHelper.h in Headers */,
482
 				50F5DFC11F407A8C001A00BC /* RNNTabBarController.h in Headers */,
572
 				50F5DFC11F407A8C001A00BC /* RNNTabBarController.h in Headers */,
483
 				263905BD1E4C6F440023D7D3 /* RCCDrawerProtocol.h in Headers */,
573
 				263905BD1E4C6F440023D7D3 /* RCCDrawerProtocol.h in Headers */,
484
 				263905C21E4C6F440023D7D3 /* SidebarAnimation.h in Headers */,
574
 				263905C21E4C6F440023D7D3 /* SidebarAnimation.h in Headers */,
575
+				E8E518361F83B94A000467AC /* RNNViewLocation.h in Headers */,
485
 				263905B51E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.h in Headers */,
576
 				263905B51E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.h in Headers */,
486
 				263905C61E4C6F440023D7D3 /* SidebarFeedlyAnimation.h in Headers */,
577
 				263905C61E4C6F440023D7D3 /* SidebarFeedlyAnimation.h in Headers */,
487
 				7B1126A31E2D2B6C00F9B03B /* RNNSplashScreen.h in Headers */,
578
 				7B1126A31E2D2B6C00F9B03B /* RNNSplashScreen.h in Headers */,
488
 				261F0E641E6EC94900989DE2 /* RNNModalManager.h in Headers */,
579
 				261F0E641E6EC94900989DE2 /* RNNModalManager.h in Headers */,
489
 				263905C01E4C6F440023D7D3 /* SidebarAirbnbAnimation.h in Headers */,
580
 				263905C01E4C6F440023D7D3 /* SidebarAirbnbAnimation.h in Headers */,
581
+				E8367B801F7A8A4700675C05 /* VICMAImageView.h in Headers */,
490
 				263905E61E4CAC950023D7D3 /* RNNSideMenuChildVC.h in Headers */,
582
 				263905E61E4CAC950023D7D3 /* RNNSideMenuChildVC.h in Headers */,
491
 				263905C41E4C6F440023D7D3 /* SidebarFacebookAnimation.h in Headers */,
583
 				263905C41E4C6F440023D7D3 /* SidebarFacebookAnimation.h in Headers */,
492
 				50F5DFC51F407AA0001A00BC /* RNNNavigationController.h in Headers */,
584
 				50F5DFC51F407AA0001A00BC /* RNNNavigationController.h in Headers */,
493
 				21B85E5F1F44482A00B314B5 /* RNNNavigationButtons.h in Headers */,
585
 				21B85E5F1F44482A00B314B5 /* RNNNavigationButtons.h in Headers */,
494
 				7BEF0D181E437684003E96B0 /* RNNRootViewController.h in Headers */,
586
 				7BEF0D181E437684003E96B0 /* RNNRootViewController.h in Headers */,
587
+				E8A5CD5A1F48CCC300E89D0D /* RNNNavigationController.h in Headers */,
495
 				7B1126A61E2D2B6C00F9B03B /* RNNBridgeModule.h in Headers */,
588
 				7B1126A61E2D2B6C00F9B03B /* RNNBridgeModule.h in Headers */,
589
+				E8DA24401F97459B00CD552B /* RNNElementFinder.h in Headers */,
496
 				263905BE1E4C6F440023D7D3 /* RCCTheSideBarManagerViewController.h in Headers */,
590
 				263905BE1E4C6F440023D7D3 /* RCCTheSideBarManagerViewController.h in Headers */,
497
 				263905CE1E4C6F440023D7D3 /* TheSidebarController.h in Headers */,
591
 				263905CE1E4C6F440023D7D3 /* TheSidebarController.h in Headers */,
498
 				7B1126A71E2D2B6C00F9B03B /* RNNEventEmitter.h in Headers */,
592
 				7B1126A71E2D2B6C00F9B03B /* RNNEventEmitter.h in Headers */,
593
+				E8A430111F9CB87B00B61A20 /* RNNAnimatedView.h in Headers */,
499
 				268692821E5054F800E2C612 /* RNNStore.h in Headers */,
594
 				268692821E5054F800E2C612 /* RNNStore.h in Headers */,
595
+				E8AEDB3C1F55A1C2000F5A6A /* RNNElementView.h in Headers */,
596
+				E8E518321F83B3E0000467AC /* RNNUtils.h in Headers */,
500
 				263905CA1E4C6F440023D7D3 /* SidebarLuvocracyAnimation.h in Headers */,
597
 				263905CA1E4C6F440023D7D3 /* SidebarLuvocracyAnimation.h in Headers */,
501
 				263905B11E4C6F440023D7D3 /* MMDrawerController.h in Headers */,
598
 				263905B11E4C6F440023D7D3 /* MMDrawerController.h in Headers */,
502
 				263905B91E4C6F440023D7D3 /* RCCDrawerController.h in Headers */,
599
 				263905B91E4C6F440023D7D3 /* RCCDrawerController.h in Headers */,
503
 				263905B31E4C6F440023D7D3 /* MMDrawerVisualState.h in Headers */,
600
 				263905B31E4C6F440023D7D3 /* MMDrawerVisualState.h in Headers */,
601
+				E8A5CD621F49114F00E89D0D /* RNNElement.h in Headers */,
602
+				E8E5182E1F83A48B000467AC /* RNNTransitionStateHolder.h in Headers */,
504
 				7B1126A91E2D2B6C00F9B03B /* RNNControllerFactory.h in Headers */,
603
 				7B1126A91E2D2B6C00F9B03B /* RNNControllerFactory.h in Headers */,
505
 				263905D61E4C94970023D7D3 /* RNNSideMenuController.h in Headers */,
604
 				263905D61E4C94970023D7D3 /* RNNSideMenuController.h in Headers */,
506
 				263905C81E4C6F440023D7D3 /* SidebarFlipboardAnimation.h in Headers */,
605
 				263905C81E4C6F440023D7D3 /* SidebarFlipboardAnimation.h in Headers */,
507
 				7BEF0D1C1E43771B003E96B0 /* RNNLayoutNode.h in Headers */,
606
 				7BEF0D1C1E43771B003E96B0 /* RNNLayoutNode.h in Headers */,
607
+				E8A5CD521F464F0400E89D0D /* RNNAnimator.h in Headers */,
508
 			);
608
 			);
509
 			runOnlyForDeploymentPostprocessing = 0;
609
 			runOnlyForDeploymentPostprocessing = 0;
510
 		};
610
 		};
562
 					};
662
 					};
563
 					D8AFADBC1BEE6F3F00A4592D = {
663
 					D8AFADBC1BEE6F3F00A4592D = {
564
 						CreatedOnToolsVersion = 7.1;
664
 						CreatedOnToolsVersion = 7.1;
665
+						LastSwiftMigration = 0820;
565
 					};
666
 					};
566
 				};
667
 				};
567
 			};
668
 			};
605
 				7B49FECB1E95098500DEB3EA /* RNNControllerFactoryTest.m in Sources */,
706
 				7B49FECB1E95098500DEB3EA /* RNNControllerFactoryTest.m in Sources */,
606
 				7B49FECD1E95098500DEB3EA /* RNNModalManagerTest.m in Sources */,
707
 				7B49FECD1E95098500DEB3EA /* RNNModalManagerTest.m in Sources */,
607
 				E83BAD791F27416B00A9F3DD /* RNNRootViewControllerTest.m in Sources */,
708
 				E83BAD791F27416B00A9F3DD /* RNNRootViewControllerTest.m in Sources */,
709
+				E8DA243D1F973C1900CD552B /* RNNTransitionStateHolderTest.m in Sources */,
608
 				7B49FECC1E95098500DEB3EA /* RNNStoreTest.m in Sources */,
710
 				7B49FECC1E95098500DEB3EA /* RNNStoreTest.m in Sources */,
609
 			);
711
 			);
610
 			runOnlyForDeploymentPostprocessing = 0;
712
 			runOnlyForDeploymentPostprocessing = 0;
618
 				263905C51E4C6F440023D7D3 /* SidebarFacebookAnimation.m in Sources */,
720
 				263905C51E4C6F440023D7D3 /* SidebarFacebookAnimation.m in Sources */,
619
 				7BEF0D191E437684003E96B0 /* RNNRootViewController.m in Sources */,
721
 				7BEF0D191E437684003E96B0 /* RNNRootViewController.m in Sources */,
620
 				263905C31E4C6F440023D7D3 /* SidebarAnimation.m in Sources */,
722
 				263905C31E4C6F440023D7D3 /* SidebarAnimation.m in Sources */,
723
+				E8A5CD531F464F0400E89D0D /* RNNAnimator.m in Sources */,
621
 				261F0E6B1E6F028A00989DE2 /* RNNNavigationStackManager.m in Sources */,
724
 				261F0E6B1E6F028A00989DE2 /* RNNNavigationStackManager.m in Sources */,
725
+				E8DA24411F97459B00CD552B /* RNNElementFinder.m in Sources */,
622
 				263905BF1E4C6F440023D7D3 /* RCCTheSideBarManagerViewController.m in Sources */,
726
 				263905BF1E4C6F440023D7D3 /* RCCTheSideBarManagerViewController.m in Sources */,
623
 				7B1126A01E2D263F00F9B03B /* RNNEventEmitter.m in Sources */,
727
 				7B1126A01E2D263F00F9B03B /* RNNEventEmitter.m in Sources */,
624
 				A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */,
728
 				A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */,
626
 				263905E71E4CAC950023D7D3 /* RNNSideMenuChildVC.m in Sources */,
730
 				263905E71E4CAC950023D7D3 /* RNNSideMenuChildVC.m in Sources */,
627
 				7BA500751E2544B9001B9E1B /* ReactNativeNavigation.m in Sources */,
731
 				7BA500751E2544B9001B9E1B /* ReactNativeNavigation.m in Sources */,
628
 				263905B21E4C6F440023D7D3 /* MMDrawerController.m in Sources */,
732
 				263905B21E4C6F440023D7D3 /* MMDrawerController.m in Sources */,
733
+				E8AEDB3D1F55A1C2000F5A6A /* RNNElementView.m in Sources */,
629
 				E83BAD6B1F27363A00A9F3DD /* RNNNavigationOptions.m in Sources */,
734
 				E83BAD6B1F27363A00A9F3DD /* RNNNavigationOptions.m in Sources */,
630
 				7BBFE5441E25330E002A6182 /* RNNBridgeModule.m in Sources */,
735
 				7BBFE5441E25330E002A6182 /* RNNBridgeModule.m in Sources */,
631
 				261F0E651E6EC94900989DE2 /* RNNModalManager.m in Sources */,
736
 				261F0E651E6EC94900989DE2 /* RNNModalManager.m in Sources */,
737
+				E8A5CD631F49114F00E89D0D /* RNNElement.m in Sources */,
632
 				7BEF0D1D1E43771B003E96B0 /* RNNLayoutNode.m in Sources */,
738
 				7BEF0D1D1E43771B003E96B0 /* RNNLayoutNode.m in Sources */,
633
 				7BA500781E254908001B9E1B /* RNNSplashScreen.m in Sources */,
739
 				7BA500781E254908001B9E1B /* RNNSplashScreen.m in Sources */,
634
 				263905BA1E4C6F440023D7D3 /* RCCDrawerController.m in Sources */,
740
 				263905BA1E4C6F440023D7D3 /* RCCDrawerController.m in Sources */,
642
 				263905B81E4C6F440023D7D3 /* UIViewController+MMDrawerController.m in Sources */,
748
 				263905B81E4C6F440023D7D3 /* UIViewController+MMDrawerController.m in Sources */,
643
 				263905CD1E4C6F440023D7D3 /* SidebarWunderlistAnimation.m in Sources */,
749
 				263905CD1E4C6F440023D7D3 /* SidebarWunderlistAnimation.m in Sources */,
644
 				263905CF1E4C6F440023D7D3 /* TheSidebarController.m in Sources */,
750
 				263905CF1E4C6F440023D7D3 /* TheSidebarController.m in Sources */,
751
+				E8A430121F9CB87B00B61A20 /* RNNAnimatedView.m in Sources */,
752
+				E8367B811F7A8A4700675C05 /* VICMAImageView.m in Sources */,
645
 				A7626C011FC5796200492FB8 /* RNNTabBarOptions.m in Sources */,
753
 				A7626C011FC5796200492FB8 /* RNNTabBarOptions.m in Sources */,
646
 				263905AF1E4C6F440023D7D3 /* MMDrawerBarButtonItem.m in Sources */,
754
 				263905AF1E4C6F440023D7D3 /* MMDrawerBarButtonItem.m in Sources */,
755
+				E8AEDB4B1F5C0BAF000F5A6A /* RNNInteractivePopAnimator.m in Sources */,
647
 				7B4928091E70415400555040 /* RNNCommandsHandler.m in Sources */,
756
 				7B4928091E70415400555040 /* RNNCommandsHandler.m in Sources */,
648
 				268692831E5054F800E2C612 /* RNNStore.m in Sources */,
757
 				268692831E5054F800E2C612 /* RNNStore.m in Sources */,
649
 				7BC9346E1E26886E00EFA125 /* RNNControllerFactory.m in Sources */,
758
 				7BC9346E1E26886E00EFA125 /* RNNControllerFactory.m in Sources */,
759
+				E8E5182F1F83A48B000467AC /* RNNTransitionStateHolder.m in Sources */,
650
 				263905B61E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.m in Sources */,
760
 				263905B61E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.m in Sources */,
761
+				E8E518331F83B3E0000467AC /* RNNUtils.m in Sources */,
651
 				50F5DFC61F407AA0001A00BC /* RNNNavigationController.m in Sources */,
762
 				50F5DFC61F407AA0001A00BC /* RNNNavigationController.m in Sources */,
652
 				21B85E5D1F44480200B314B5 /* RNNNavigationButtons.m in Sources */,
763
 				21B85E5D1F44480200B314B5 /* RNNNavigationButtons.m in Sources */,
764
+				E8E518371F83B94A000467AC /* RNNViewLocation.m in Sources */,
653
 				263905C91E4C6F440023D7D3 /* SidebarFlipboardAnimation.m in Sources */,
765
 				263905C91E4C6F440023D7D3 /* SidebarFlipboardAnimation.m in Sources */,
654
 			);
766
 			);
655
 			runOnlyForDeploymentPostprocessing = 0;
767
 			runOnlyForDeploymentPostprocessing = 0;
788
 		D8AFADC71BEE6F3F00A4592D /* Debug */ = {
900
 		D8AFADC71BEE6F3F00A4592D /* Debug */ = {
789
 			isa = XCBuildConfiguration;
901
 			isa = XCBuildConfiguration;
790
 			buildSettings = {
902
 			buildSettings = {
903
+				CLANG_ENABLE_MODULES = YES;
791
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
904
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
905
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
792
 				OTHER_LDFLAGS = "-ObjC";
906
 				OTHER_LDFLAGS = "-ObjC";
793
 				PRODUCT_NAME = ReactNativeNavigation;
907
 				PRODUCT_NAME = ReactNativeNavigation;
794
 				PUBLIC_HEADERS_FOLDER_PATH = "include/${PRODUCT_NAME}";
908
 				PUBLIC_HEADERS_FOLDER_PATH = "include/${PRODUCT_NAME}";
795
 				SKIP_INSTALL = YES;
909
 				SKIP_INSTALL = YES;
910
+				SWIFT_OBJC_BRIDGING_HEADER = "ReactNativeNavigation-Bridging-Header.h";
911
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
912
+				SWIFT_VERSION = 3.0;
796
 			};
913
 			};
797
 			name = Debug;
914
 			name = Debug;
798
 		};
915
 		};
799
 		D8AFADC81BEE6F3F00A4592D /* Release */ = {
916
 		D8AFADC81BEE6F3F00A4592D /* Release */ = {
800
 			isa = XCBuildConfiguration;
917
 			isa = XCBuildConfiguration;
801
 			buildSettings = {
918
 			buildSettings = {
919
+				CLANG_ENABLE_MODULES = YES;
802
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
920
 				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
921
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
803
 				OTHER_LDFLAGS = "-ObjC";
922
 				OTHER_LDFLAGS = "-ObjC";
804
 				PRODUCT_NAME = ReactNativeNavigation;
923
 				PRODUCT_NAME = ReactNativeNavigation;
805
 				PUBLIC_HEADERS_FOLDER_PATH = "include/${PRODUCT_NAME}";
924
 				PUBLIC_HEADERS_FOLDER_PATH = "include/${PRODUCT_NAME}";
806
 				SKIP_INSTALL = YES;
925
 				SKIP_INSTALL = YES;
926
+				SWIFT_OBJC_BRIDGING_HEADER = "ReactNativeNavigation-Bridging-Header.h";
927
+				SWIFT_VERSION = 3.0;
807
 			};
928
 			};
808
 			name = Release;
929
 			name = Release;
809
 		};
930
 		};

+ 3
- 1
lib/ios/ReactNativeNavigation.xcodeproj/xcshareddata/xcschemes/ReactNativeNavigation.xcscheme View File

37
       </BuildActionEntries>
37
       </BuildActionEntries>
38
    </BuildAction>
38
    </BuildAction>
39
    <TestAction
39
    <TestAction
40
-      buildConfiguration = "Release"
40
+      buildConfiguration = "Debug"
41
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
41
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
42
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
42
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
43
+      language = ""
43
       shouldUseLaunchSchemeArgsEnv = "YES">
44
       shouldUseLaunchSchemeArgsEnv = "YES">
44
       <Testables>
45
       <Testables>
45
          <TestableReference
46
          <TestableReference
69
       buildConfiguration = "Debug"
70
       buildConfiguration = "Debug"
70
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
71
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
71
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
72
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
73
+      language = ""
72
       launchStyle = "0"
74
       launchStyle = "0"
73
       useCustomWorkingDirectory = "NO"
75
       useCustomWorkingDirectory = "NO"
74
       ignoresPersistentStateOnLaunch = "NO"
76
       ignoresPersistentStateOnLaunch = "NO"

+ 15
- 11
lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m View File

10
 
10
 
11
 @property (nonatomic, strong) RNNStore* store;
11
 @property (nonatomic, strong) RNNStore* store;
12
 @property (nonatomic, strong) RNNCommandsHandler* uut;
12
 @property (nonatomic, strong) RNNCommandsHandler* uut;
13
+@property (nonatomic, strong) RCTBridge* bridge;
13
 
14
 
14
 @end
15
 @end
15
 
16
 
17
 
18
 
18
 - (void)setUp {
19
 - (void)setUp {
19
 	[super setUp];
20
 	[super setUp];
21
+//	[self.store setReadyToReceiveCommands:true];
20
 	self.store = [[RNNStore alloc] init];
22
 	self.store = [[RNNStore alloc] init];
21
-	self.uut = [[RNNCommandsHandler alloc] initWithStore:self.store controllerFactory:nil];
23
+	self.bridge = nil;
24
+	self.uut = [[RNNCommandsHandler alloc] initWithStore:self.store controllerFactory:nil andBridge:self.bridge];
22
 }
25
 }
23
 
26
 
24
 
27
 
25
 - (void)testAssertReadyForEachMethodThrowsExceptoins {
28
 - (void)testAssertReadyForEachMethodThrowsExceptoins {
26
 	NSArray* methods = [self getPublicMethodNamesForObject:self.uut];
29
 	NSArray* methods = [self getPublicMethodNamesForObject:self.uut];
27
-	
30
+	[self.store setReadyToReceiveCommands:false];
28
 	for (NSString* methodName in methods) {
31
 	for (NSString* methodName in methods) {
29
 		SEL s = NSSelectorFromString(methodName);
32
 		SEL s = NSSelectorFromString(methodName);
30
 		NSMethodSignature* signature = [self.uut methodSignatureForSelector:s];
33
 		NSMethodSignature* signature = [self.uut methodSignatureForSelector:s];
36
 
39
 
37
 -(NSArray*) getPublicMethodNamesForObject:(NSObject*)obj{
40
 -(NSArray*) getPublicMethodNamesForObject:(NSObject*)obj{
38
 	NSMutableArray* skipMethods = [NSMutableArray new];
41
 	NSMutableArray* skipMethods = [NSMutableArray new];
39
-	[skipMethods addObject:@"initWithStore:controllerFactory:"];
42
+
43
+	[skipMethods addObject:@"initWithStore:controllerFactory:andBridge:"];
40
 	[skipMethods addObject:@"assertReady"];
44
 	[skipMethods addObject:@"assertReady"];
41
 	[skipMethods addObject:@".cxx_destruct"];
45
 	[skipMethods addObject:@".cxx_destruct"];
42
-	
46
+
43
 	NSMutableArray* result = [NSMutableArray new];
47
 	NSMutableArray* result = [NSMutableArray new];
44
-	
48
+
45
 	// count and names:
49
 	// count and names:
46
 	int i=0;
50
 	int i=0;
47
 	unsigned int mc = 0;
51
 	unsigned int mc = 0;
48
 	Method * mlist = class_copyMethodList(object_getClass(obj), &mc);
52
 	Method * mlist = class_copyMethodList(object_getClass(obj), &mc);
49
-	
53
+
50
 	for(i=0; i<mc; i++) {
54
 	for(i=0; i<mc; i++) {
51
 		NSString *methodName = [NSString stringWithUTF8String:sel_getName(method_getName(mlist[i]))];
55
 		NSString *methodName = [NSString stringWithUTF8String:sel_getName(method_getName(mlist[i]))];
52
-		
56
+
53
 		// filter skippedMethods
57
 		// filter skippedMethods
54
 		if (methodName && ![skipMethods containsObject:methodName]) {
58
 		if (methodName && ![skipMethods containsObject:methodName]) {
55
 			[result addObject:methodName];
59
 			[result addObject:methodName];
56
 		}
60
 		}
57
 	}
61
 	}
58
-	
62
+
59
 	return result;
63
 	return result;
60
 }
64
 }
61
 
65
 
70
 	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:vc];
74
 	RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:vc];
71
 	[vc viewWillAppear:false];
75
 	[vc viewWillAppear:false];
72
 	XCTAssertTrue([vc.navigationItem.title isEqual:@"the title"]);
76
 	XCTAssertTrue([vc.navigationItem.title isEqual:@"the title"]);
73
-	
77
+
74
 	[self.store setReadyToReceiveCommands:true];
78
 	[self.store setReadyToReceiveCommands:true];
75
 	[self.store setContainer:vc containerId:@"containerId"];
79
 	[self.store setContainer:vc containerId:@"containerId"];
76
 	
80
 	
77
 	NSDictionary* dictFromJs = @{@"topBar": @{@"backgroundColor" :@(0xFFFF0000)}};
81
 	NSDictionary* dictFromJs = @{@"topBar": @{@"backgroundColor" :@(0xFFFF0000)}};
78
 	UIColor* expectedColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
82
 	UIColor* expectedColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
79
-	
83
+
80
 	[self.uut setOptions:@"containerId" options:dictFromJs];
84
 	[self.uut setOptions:@"containerId" options:dictFromJs];
81
-	
85
+
82
 	XCTAssertTrue([vc.navigationItem.title isEqual:@"the title"]);
86
 	XCTAssertTrue([vc.navigationItem.title isEqual:@"the title"]);
83
 	XCTAssertTrue([nav.navigationBar.barTintColor isEqual:expectedColor]);
87
 	XCTAssertTrue([nav.navigationBar.barTintColor isEqual:expectedColor]);
84
 }
88
 }

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

53
 
53
 
54
 
54
 
55
 - (void)testPop_removeTopVCFromStore {
55
 - (void)testPop_removeTopVCFromStore {
56
-	[self.uut pop:@"vc3"];
57
-	
56
+	[self.uut pop:@"vc3" withAnimationData:(NSDictionary*)nil];
58
 	XCTAssertNil([self.store findContainerForId:@"vc3"]);
57
 	XCTAssertNil([self.store findContainerForId:@"vc3"]);
59
 	XCTAssertNotNil([self.store findContainerForId:@"vc2"]);
58
 	XCTAssertNotNil([self.store findContainerForId:@"vc2"]);
60
 	XCTAssertNotNil([self.store findContainerForId:@"vc1"]);
59
 	XCTAssertNotNil([self.store findContainerForId:@"vc1"]);

+ 43
- 11
lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m View File

172
 	XCTAssertFalse(self.uut.navigationController.navigationBar.translucent);
172
 	XCTAssertFalse(self.uut.navigationController.navigationBar.translucent);
173
 }
173
 }
174
 
174
 
175
--(void)testTopBarTransparent {
176
-	NSNumber* topBarTransparentInput = @(0);
177
-	self.options.topBar.transparent = topBarTransparentInput;
178
-	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
179
-	[self.uut viewWillAppear:false];
180
-	XCTAssertNotNil(self.uut.navigationController.navigationBar.shadowImage);
181
-	XCTAssertNotNil([self.uut.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault]);
182
-	XCTAssertTrue(CGRectEqualToRect(self.uut.navigationController.navigationBar.subviews.firstObject.frame, CGRectZero));
183
-}
184
-
185
 -(void)testTabBadge {
175
 -(void)testTabBadge {
186
 	NSString* tabBadgeInput = @"5";
176
 	NSString* tabBadgeInput = @"5";
187
 	self.options.tabBar.tabBadge = tabBadgeInput;
177
 	self.options.tabBar.tabBadge = tabBadgeInput;
196
 	
186
 	
197
 }
187
 }
198
 
188
 
189
+-(void)testTopBarTransparent_BOOL_True {
190
+	NSNumber* topBarTransparentInput = @(1);
191
+	self.options.topBar.transparent = topBarTransparentInput;
192
+	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
193
+	[self.uut viewWillAppear:false];
194
+	UIView* transparentView = [self.uut.navigationController.navigationBar viewWithTag:TOP_BAR_TRANSPARENT_TAG];
195
+	XCTAssertTrue(transparentView);
196
+	XCTAssertTrue([NSStringFromCGRect(transparentView.frame) isEqual: NSStringFromCGRect(CGRectZero)]);
197
+}
198
+
199
+-(void)testTopBarTransparent_BOOL_false {
200
+	NSNumber* topBarTransparentInput = @(0);
201
+	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
202
+	self.options.topBar.transparent = topBarTransparentInput;
203
+	[self.uut viewWillAppear:false];
204
+	UIView* transparentView = [self.uut.navigationController.navigationBar viewWithTag:TOP_BAR_TRANSPARENT_TAG];
205
+	XCTAssertFalse(transparentView);
206
+}
207
+
208
+
209
+-(void)testStoreOriginalTopBarImages {
210
+	
211
+}
199
 
212
 
200
 -(void)testTopBarTextFontSize_withoutTextFontFamily_withoutTextColor {
213
 -(void)testTopBarTextFontSize_withoutTextFontFamily_withoutTextColor {
201
 	NSNumber* topBarTextFontSizeInput = @(15);
214
 	NSNumber* topBarTextFontSizeInput = @(15);
464
 	XCTAssertNil([self.uut.navigationController.navigationBar viewWithTag:BLUR_TOPBAR_TAG]);
477
 	XCTAssertNil([self.uut.navigationController.navigationBar viewWithTag:BLUR_TOPBAR_TAG]);
465
 }
478
 }
466
 
479
 
467
-
480
+-(void)testTopBarLargeTitle_default {
481
+	__unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut];
482
+	[self.uut viewWillAppear:false];
483
+	
484
+	XCTAssertEqual(self.uut.navigationItem.largeTitleDisplayMode,  UINavigationItemLargeTitleDisplayModeNever);
485
+}
486
+-(void)testTopBarLargeTitle_true {
487
+	self.options.topBar.largeTitle = @(1);
488
+	__unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut];
489
+	[self.uut viewWillAppear:false];
490
+	
491
+	XCTAssertEqual(self.uut.navigationItem.largeTitleDisplayMode, UINavigationItemLargeTitleDisplayModeAlways);
492
+}
493
+-(void)testTopBarLargeTitle_false {
494
+	self.options.tabBar.hidden = @(0);
495
+	__unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut];
496
+	[self.uut viewWillAppear:false];
497
+	
498
+	XCTAssertEqual(self.uut.navigationItem.largeTitleDisplayMode, UINavigationItemLargeTitleDisplayModeNever);
499
+}
468
 -(void)testTopBarBlur_false {
500
 -(void)testTopBarBlur_false {
469
 	NSNumber* topBarBlurInput = @(0);
501
 	NSNumber* topBarBlurInput = @(0);
470
 	self.options.topBar.blur = topBarBlurInput;
502
 	self.options.topBar.blur = topBarBlurInput;

+ 26
- 0
lib/ios/ReactNativeNavigationTests/RNNTransitionStateHolderTest.m View File

1
+#import <XCTest/XCTest.h>
2
+#import "RNNTransitionStateHolder.h"
3
+
4
+@interface RNNTransitionStateHolderTest : XCTestCase
5
+
6
+@end
7
+
8
+@implementation RNNTransitionStateHolderTest
9
+
10
+- (void)testDefaultObjectProperties {
11
+	RNNTransitionStateHolder* defaultTransitionObject = [[RNNTransitionStateHolder alloc] initWithTransition:@{@"fromId": @"hello"}];
12
+	XCTAssertEqual(defaultTransitionObject.springDamping,  0.85);
13
+	XCTAssertEqual(defaultTransitionObject.springVelocity,  0.8);
14
+	XCTAssertEqual(defaultTransitionObject.startDelay,  0);
15
+	XCTAssertEqual(defaultTransitionObject.startAlpha,  1);
16
+	XCTAssertEqual(defaultTransitionObject.endAlpha,  1);
17
+	XCTAssertEqual(defaultTransitionObject.startX,  0);
18
+	XCTAssertEqual(defaultTransitionObject.startY,  0);
19
+	XCTAssertEqual(defaultTransitionObject.endX,  0);
20
+	XCTAssertEqual(defaultTransitionObject.endY,  0);
21
+	XCTAssertEqual(defaultTransitionObject.duration,  1);
22
+	XCTAssertEqual(defaultTransitionObject.interactivePop,  false);
23
+}
24
+
25
+
26
+@end

+ 24
- 0
lib/ios/VICMAImageView.h View File

1
+//
2
+//  VIAnimatableImageView.h
3
+//  VIAnimatableImageViewDemo
4
+//
5
+//  Created by Vito on 12/30/14.
6
+//  Copyright (c) 2014 Vito. All rights reserved.
7
+//
8
+
9
+#import <UIKit/UIKit.h>
10
+
11
+
12
+/**
13
+ *  Content mode animatable image view.
14
+ */
15
+@interface VICMAImageView : UIView
16
+
17
+@property (nonatomic, strong) UIImage *image;
18
+
19
+- (instancetype)initWithImage:(UIImage *)image;
20
+
21
+// The image presentation size
22
+- (CGSize)presentationImageSize;
23
+
24
+@end

+ 280
- 0
lib/ios/VICMAImageView.m View File

1
+//
2
+//  VIAnimatableImageView.m
3
+//  VIAnimatableImageViewDemo
4
+//
5
+//  Created by Vito on 12/30/14.
6
+//  Copyright (c) 2014 Vito. All rights reserved.
7
+// 	project can be found at: https://github.com/vitoziv/VICMAImageView
8
+
9
+#import "VICMAImageView.h"
10
+
11
+@interface VICMAImageView ()
12
+
13
+@property (nonatomic, strong) UIImageView *imageView;
14
+
15
+@end
16
+
17
+@implementation VICMAImageView
18
+
19
+- (void)commonInit
20
+{
21
+	self.clipsToBounds = YES;
22
+	self.contentMode = UIViewContentModeScaleAspectFit;
23
+	
24
+	if (!_imageView) {
25
+		UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.frame];
26
+		imageView.contentMode = UIViewContentModeScaleToFill;
27
+		[self addSubview:imageView];
28
+		_imageView = imageView;
29
+	}
30
+}
31
+
32
+- (instancetype)initWithImage:(UIImage *)image
33
+{
34
+	self = [super init];
35
+	if (self) {
36
+		[self commonInit];
37
+		_imageView.image = image;
38
+	}
39
+	
40
+	return self;
41
+}
42
+
43
+- (instancetype)initWithFrame:(CGRect)frame
44
+{
45
+	self = [super initWithFrame:frame];
46
+	if (self) {
47
+		[self commonInit];
48
+	}
49
+	
50
+	return self;
51
+}
52
+
53
+- (instancetype)initWithCoder:(NSCoder *)aDecoder
54
+{
55
+	self = [super initWithCoder:aDecoder];
56
+	if (self) {
57
+		[self commonInit];
58
+	}
59
+	
60
+	return self;
61
+}
62
+
63
+- (CGSize)presentationImageSize
64
+{
65
+	return self.imageView.bounds.size;
66
+}
67
+
68
+- (void)setImage:(UIImage *)image
69
+{
70
+	self.imageView.image = image;
71
+	[self updateView];
72
+}
73
+
74
+- (UIImage *)image
75
+{
76
+	return self.imageView.image;
77
+}
78
+
79
+- (void)setFrame:(CGRect)frame
80
+{
81
+	[super setFrame:frame];
82
+	[self updateView];
83
+}
84
+
85
+- (void)setContentMode:(UIViewContentMode)contentMode
86
+{
87
+	[super setContentMode:contentMode];
88
+	[self updateView];
89
+}
90
+
91
+- (void)updateView
92
+{
93
+	if (self.bounds.size.width == 0 || self.bounds.size.height == 0 ||
94
+		self.image.size.width == 0 || self.image.size.height == 0) {
95
+		return;
96
+	}
97
+	
98
+	switch (self.contentMode) {
99
+		case UIViewContentModeScaleAspectFit:
100
+			[self updateViewToAspectFit];
101
+			break;
102
+			
103
+		case UIViewContentModeScaleAspectFill:
104
+			[self updateViewToAspectFill];
105
+			break;
106
+			
107
+		case UIViewContentModeScaleToFill:
108
+			[self updateViewToScaleToFill];
109
+			break;
110
+			
111
+		case UIViewContentModeCenter:
112
+			[self updateViewToCenter];
113
+			break;
114
+			
115
+		case UIViewContentModeBottom:
116
+			[self updateViewToBottom];
117
+			break;
118
+			
119
+		case UIViewContentModeBottomLeft:
120
+			[self updateViewToBottomLeft];
121
+			break;
122
+			
123
+		case UIViewContentModeBottomRight:
124
+			[self updateViewToBottomRight];
125
+			break;
126
+			
127
+		case UIViewContentModeLeft:
128
+			[self updateViewToLeft];
129
+			break;
130
+			
131
+		case UIViewContentModeRight:
132
+			[self updateViewToRight];
133
+			break;
134
+			
135
+		case UIViewContentModeTop:
136
+			[self updateViewToTop];
137
+			break;
138
+			
139
+		case UIViewContentModeTopLeft:
140
+			[self updateViewToTopLeft];
141
+			break;
142
+			
143
+		case UIViewContentModeTopRight:
144
+			[self updateViewToTopRight];
145
+			break;
146
+			
147
+		case UIViewContentModeRedraw:
148
+			[self updateViewToScaleToFill];
149
+			break;
150
+			
151
+		default:
152
+			break;
153
+	}
154
+}
155
+
156
+- (void)updateViewToAspectFit
157
+{
158
+	CGSize imageSize = CGSizeMake(self.imageView.image.size.width / self.imageView.image.scale,
159
+								  self.imageView.image.size.height / self.imageView.image.scale);
160
+	
161
+	CGFloat widthRatio = imageSize.width / self.bounds.size.width;
162
+	CGFloat heightRatio = imageSize.height / self.bounds.size.height;
163
+	
164
+	if (widthRatio > heightRatio) {
165
+		imageSize = CGSizeMake(imageSize.width / widthRatio, imageSize.height / widthRatio);
166
+	} else {
167
+		imageSize = CGSizeMake(imageSize.width / heightRatio, imageSize.height / heightRatio);
168
+	}
169
+	
170
+	self.imageView.bounds = CGRectMake(0, 0, imageSize.width, imageSize.height);
171
+	self.imageView.center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
172
+}
173
+
174
+- (void)updateViewToAspectFill
175
+{
176
+	CGSize imageSize = CGSizeMake(self.imageView.image.size.width / self.imageView.image.scale,
177
+								  self.imageView.image.size.height / self.imageView.image.scale);
178
+	
179
+	CGFloat widthRatio = imageSize.width / self.bounds.size.width;
180
+	CGFloat heightRatio = imageSize.height / self.bounds.size.height;
181
+	
182
+	if (widthRatio > heightRatio) {
183
+		imageSize = CGSizeMake(imageSize.width / heightRatio, imageSize.height / heightRatio);
184
+	} else {
185
+		imageSize = CGSizeMake(imageSize.width / widthRatio, imageSize.height / widthRatio);
186
+	}
187
+	
188
+	self.imageView.bounds = CGRectMake(0, 0, imageSize.width, imageSize.height);
189
+	[self centerImageViewToSuperView];
190
+}
191
+
192
+- (void)updateViewToScaleToFill
193
+{
194
+	self.imageView.bounds = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
195
+	[self centerImageViewToSuperView];
196
+}
197
+
198
+- (void)updateViewToCenter
199
+{
200
+	[self fitImageViewSizeToImageSize];
201
+	[self centerImageViewToSuperView];
202
+}
203
+
204
+- (void)updateViewToBottom
205
+{
206
+	[self fitImageViewSizeToImageSize];
207
+	self.imageView.center = CGPointMake(self.bounds.size.width / 2,
208
+										self.bounds.size.height - self.image.size.height / 2);
209
+}
210
+
211
+- (void)updateViewToBottomLeft
212
+{
213
+	[self fitImageViewSizeToImageSize];
214
+	
215
+	self.imageView.center = CGPointMake(self.image.size.width / 2,
216
+										self.bounds.size.height - self.image.size.height / 2);
217
+}
218
+
219
+- (void)updateViewToBottomRight
220
+{
221
+	[self fitImageViewSizeToImageSize];
222
+	self.imageView.center = CGPointMake(self.bounds.size.width - self.image.size.width / 2,
223
+										self.bounds.size.height - self.image.size.height / 2);
224
+}
225
+
226
+- (void)updateViewToLeft
227
+{
228
+	[self fitImageViewSizeToImageSize];
229
+	
230
+	self.imageView.center = CGPointMake(self.image.size.width / 2,
231
+										self.bounds.size.height / 2);
232
+}
233
+
234
+- (void)updateViewToRight
235
+{
236
+	[self fitImageViewSizeToImageSize];
237
+	
238
+	self.imageView.center = CGPointMake(self.bounds.size.width - self.image.size.width / 2,
239
+										self.bounds.size.height / 2);
240
+}
241
+
242
+- (void)updateViewToTop
243
+{
244
+	[self fitImageViewSizeToImageSize];
245
+	
246
+	self.imageView.center = CGPointMake(self.bounds.size.width / 2,
247
+										self.image.size.height / 2);
248
+}
249
+
250
+- (void)updateViewToTopLeft
251
+{
252
+	[self fitImageViewSizeToImageSize];
253
+	
254
+	self.imageView.center = CGPointMake(self.image.size.width / 2,
255
+										self.image.size.height / 2);
256
+}
257
+
258
+- (void)updateViewToTopRight
259
+{
260
+	[self fitImageViewSizeToImageSize];
261
+	self.imageView.center = CGPointMake(self.bounds.size.width - self.image.size.width / 2,
262
+										self.image.size.height / 2);
263
+}
264
+
265
+#pragma mark - Helper
266
+
267
+- (void)fitImageViewSizeToImageSize
268
+{
269
+	CGSize imageSize = CGSizeMake(self.imageView.image.size.width / self.imageView.image.scale,
270
+								  self.imageView.image.size.height / self.imageView.image.scale);
271
+	
272
+	self.imageView.bounds = CGRectMake(0, 0, imageSize.width, imageSize.height);
273
+}
274
+
275
+- (void)centerImageViewToSuperView
276
+{
277
+	self.imageView.center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
278
+}
279
+
280
+@end

+ 4
- 3
lib/src/Navigation.js View File

8
 const LayoutTreeCrawler = require('./commands/LayoutTreeCrawler');
8
 const LayoutTreeCrawler = require('./commands/LayoutTreeCrawler');
9
 const PrivateEventsListener = require('./events/PrivateEventsListener');
9
 const PrivateEventsListener = require('./events/PrivateEventsListener');
10
 const PublicEventsRegistry = require('./events/PublicEventsRegistry');
10
 const PublicEventsRegistry = require('./events/PublicEventsRegistry');
11
+const Element = require('./adapters/Element');
11
 
12
 
12
 class Navigation {
13
 class Navigation {
13
   constructor() {
14
   constructor() {
22
     this.publicEventsRegistry = new PublicEventsRegistry(this.nativeEventsReceiver);
23
     this.publicEventsRegistry = new PublicEventsRegistry(this.nativeEventsReceiver);
23
     this.privateEventsListener = new PrivateEventsListener(this.nativeEventsReceiver, this.store);
24
     this.privateEventsListener = new PrivateEventsListener(this.nativeEventsReceiver, this.store);
24
     this.privateEventsListener.listenAndHandlePrivateEvents();
25
     this.privateEventsListener.listenAndHandlePrivateEvents();
26
+    this.Element = Element;
25
   }
27
   }
26
-
27
   registerContainer(containerName, getContainerFunc) {
28
   registerContainer(containerName, getContainerFunc) {
28
     this.containerRegistry.registerContainer(containerName, getContainerFunc);
29
     this.containerRegistry.registerContainer(containerName, getContainerFunc);
29
   }
30
   }
56
     return this.commands.push(onContainerId, params);
57
     return this.commands.push(onContainerId, params);
57
   }
58
   }
58
 
59
 
59
-  pop(containerId) {
60
-    return this.commands.pop(containerId);
60
+  pop(containerId, params) {
61
+    return this.commands.pop(containerId, params);
61
   }
62
   }
62
 
63
 
63
   popTo(containerId) {
64
   popTo(containerId) {

+ 20
- 0
lib/src/adapters/Element.js View File

1
+import PropTypes from 'prop-types';
2
+import React from 'react';
3
+import { requireNativeComponent } from 'react-native';
4
+
5
+class Element extends React.Component {
6
+  render() {
7
+    return <RNNElement {...this.props} />;
8
+  }
9
+}
10
+
11
+Element.propTypes = {
12
+  elementId: PropTypes.string.isRequired,
13
+  resizeMode: PropTypes.string
14
+};
15
+Element.defaultProps = {
16
+  resizeMode: ''
17
+};
18
+const RNNElement = requireNativeComponent('RNNElement', Element);
19
+
20
+module.exports = Element;

+ 2
- 2
lib/src/adapters/NativeCommandsSender.js View File

21
     return this.nativeCommandsModule.push(onContainerId, layout);
21
     return this.nativeCommandsModule.push(onContainerId, layout);
22
   }
22
   }
23
 
23
 
24
-  pop(containerId) {
25
-    return this.nativeCommandsModule.pop(containerId);
24
+  pop(containerId, options) {
25
+    return this.nativeCommandsModule.pop(containerId, options);
26
   }
26
   }
27
 
27
 
28
   popTo(containerId) {
28
   popTo(containerId) {

+ 2
- 2
lib/src/commands/Commands.js View File

49
     return this.nativeCommandsSender.push(onContainerId, layout);
49
     return this.nativeCommandsSender.push(onContainerId, layout);
50
   }
50
   }
51
 
51
 
52
-  pop(containerId) {
53
-    return this.nativeCommandsSender.pop(containerId);
52
+  pop(containerId, options) {
53
+    return this.nativeCommandsSender.pop(containerId, options);
54
   }
54
   }
55
 
55
 
56
   popTo(containerId) {
56
   popTo(containerId) {

+ 13
- 1
lib/src/commands/Commands.test.js View File

193
     it('pops a container, passing containerId', () => {
193
     it('pops a container, passing containerId', () => {
194
       uut.pop('theContainerId');
194
       uut.pop('theContainerId');
195
       expect(mockCommandsSender.pop).toHaveBeenCalledTimes(1);
195
       expect(mockCommandsSender.pop).toHaveBeenCalledTimes(1);
196
-      expect(mockCommandsSender.pop).toHaveBeenCalledWith('theContainerId');
196
+      expect(mockCommandsSender.pop).toHaveBeenCalledWith('theContainerId', undefined);
197
+    });
198
+    it('pops a container, passing containerId and options', () => {
199
+      const options = {
200
+        customTransition: {
201
+          animations: [
202
+            { type: 'sharedElement', fromId: 'title2', toId: 'title1', startDelay: 0, springVelocity: 0.2, duration: 0.5 }
203
+          ],
204
+          duration: 0.8
205
+        } };
206
+      uut.pop('theContainerId', options);
207
+      expect(mockCommandsSender.pop).toHaveBeenCalledTimes(1);
208
+      expect(mockCommandsSender.pop).toHaveBeenCalledWith('theContainerId', options);
197
     });
209
     });
198
 
210
 
199
     it('pop returns a promise that resolves to containerId', async () => {
211
     it('pop returns a promise that resolves to containerId', async () => {

+ 26
- 42
package-lock.json View File

303
     "asap": {
303
     "asap": {
304
       "version": "2.0.6",
304
       "version": "2.0.6",
305
       "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
305
       "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
306
-      "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
307
-      "dev": true
306
+      "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
308
     },
307
     },
309
     "asn1": {
308
     "asn1": {
310
       "version": "0.2.3",
309
       "version": "0.2.3",
1851
     "core-js": {
1850
     "core-js": {
1852
       "version": "1.2.7",
1851
       "version": "1.2.7",
1853
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
1852
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
1854
-      "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=",
1855
-      "dev": true
1853
+      "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
1856
     },
1854
     },
1857
     "core-util-is": {
1855
     "core-util-is": {
1858
       "version": "1.0.2",
1856
       "version": "1.0.2",
2244
       "version": "0.1.12",
2242
       "version": "0.1.12",
2245
       "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
2243
       "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
2246
       "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
2244
       "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
2247
-      "dev": true,
2248
       "requires": {
2245
       "requires": {
2249
         "iconv-lite": "0.4.19"
2246
         "iconv-lite": "0.4.19"
2250
       }
2247
       }
3058
       "version": "0.8.16",
3055
       "version": "0.8.16",
3059
       "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz",
3056
       "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz",
3060
       "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=",
3057
       "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=",
3061
-      "dev": true,
3062
       "requires": {
3058
       "requires": {
3063
         "core-js": "1.2.7",
3059
         "core-js": "1.2.7",
3064
         "isomorphic-fetch": "2.2.1",
3060
         "isomorphic-fetch": "2.2.1",
4069
             }
4065
             }
4070
           }
4066
           }
4071
         },
4067
         },
4072
-        "string-width": {
4073
-          "version": "1.0.2",
4068
+        "string_decoder": {
4069
+          "version": "1.0.1",
4074
           "bundled": true,
4070
           "bundled": true,
4075
           "dev": true,
4071
           "dev": true,
4076
           "requires": {
4072
           "requires": {
4077
-            "code-point-at": "1.1.0",
4078
-            "is-fullwidth-code-point": "1.0.0",
4079
-            "strip-ansi": "3.0.1"
4073
+            "safe-buffer": "5.0.1"
4080
           }
4074
           }
4081
         },
4075
         },
4082
-        "string_decoder": {
4083
-          "version": "1.0.1",
4076
+        "string-width": {
4077
+          "version": "1.0.2",
4084
           "bundled": true,
4078
           "bundled": true,
4085
           "dev": true,
4079
           "dev": true,
4086
           "requires": {
4080
           "requires": {
4087
-            "safe-buffer": "5.0.1"
4081
+            "code-point-at": "1.1.0",
4082
+            "is-fullwidth-code-point": "1.0.0",
4083
+            "strip-ansi": "3.0.1"
4088
           }
4084
           }
4089
         },
4085
         },
4090
         "stringstream": {
4086
         "stringstream": {
4640
     "iconv-lite": {
4636
     "iconv-lite": {
4641
       "version": "0.4.19",
4637
       "version": "0.4.19",
4642
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
4638
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
4643
-      "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
4644
-      "dev": true
4639
+      "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
4645
     },
4640
     },
4646
     "ignore": {
4641
     "ignore": {
4647
       "version": "3.3.7",
4642
       "version": "3.3.7",
5056
     "is-stream": {
5051
     "is-stream": {
5057
       "version": "1.1.0",
5052
       "version": "1.1.0",
5058
       "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
5053
       "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
5059
-      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
5060
-      "dev": true
5054
+      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
5061
     },
5055
     },
5062
     "is-symbol": {
5056
     "is-symbol": {
5063
       "version": "1.0.1",
5057
       "version": "1.0.1",
5108
       "version": "2.2.1",
5102
       "version": "2.2.1",
5109
       "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
5103
       "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
5110
       "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
5104
       "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
5111
-      "dev": true,
5112
       "requires": {
5105
       "requires": {
5113
         "node-fetch": "1.7.3",
5106
         "node-fetch": "1.7.3",
5114
         "whatwg-fetch": "2.0.3"
5107
         "whatwg-fetch": "2.0.3"
5566
     "js-tokens": {
5559
     "js-tokens": {
5567
       "version": "3.0.2",
5560
       "version": "3.0.2",
5568
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
5561
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
5569
-      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
5570
-      "dev": true
5562
+      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
5571
     },
5563
     },
5572
     "js-types": {
5564
     "js-types": {
5573
       "version": "1.0.0",
5565
       "version": "1.0.0",
5998
       "version": "1.3.1",
5990
       "version": "1.3.1",
5999
       "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
5991
       "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
6000
       "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
5992
       "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
6001
-      "dev": true,
6002
       "requires": {
5993
       "requires": {
6003
         "js-tokens": "3.0.2"
5994
         "js-tokens": "3.0.2"
6004
       }
5995
       }
6391
       "version": "1.7.3",
6382
       "version": "1.7.3",
6392
       "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
6383
       "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
6393
       "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
6384
       "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
6394
-      "dev": true,
6395
       "requires": {
6385
       "requires": {
6396
         "encoding": "0.1.12",
6386
         "encoding": "0.1.12",
6397
         "is-stream": "1.1.0"
6387
         "is-stream": "1.1.0"
6490
     "object-assign": {
6480
     "object-assign": {
6491
       "version": "4.1.1",
6481
       "version": "4.1.1",
6492
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
6482
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
6493
-      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
6494
-      "dev": true
6483
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
6495
     },
6484
     },
6496
     "object-keys": {
6485
     "object-keys": {
6497
       "version": "1.0.11",
6486
       "version": "1.0.11",
6943
       "version": "7.3.1",
6932
       "version": "7.3.1",
6944
       "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
6933
       "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
6945
       "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
6934
       "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
6946
-      "dev": true,
6947
       "requires": {
6935
       "requires": {
6948
         "asap": "2.0.6"
6936
         "asap": "2.0.6"
6949
       }
6937
       }
6958
       "version": "15.6.0",
6946
       "version": "15.6.0",
6959
       "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz",
6947
       "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz",
6960
       "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=",
6948
       "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=",
6961
-      "dev": true,
6962
       "requires": {
6949
       "requires": {
6963
         "fbjs": "0.8.16",
6950
         "fbjs": "0.8.16",
6964
         "loose-envify": "1.3.1",
6951
         "loose-envify": "1.3.1",
8196
     "setimmediate": {
8183
     "setimmediate": {
8197
       "version": "1.0.5",
8184
       "version": "1.0.5",
8198
       "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
8185
       "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
8199
-      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
8200
-      "dev": true
8186
+      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
8201
     },
8187
     },
8202
     "shebang-command": {
8188
     "shebang-command": {
8203
       "version": "1.2.0",
8189
       "version": "1.2.0",
8447
         }
8433
         }
8448
       }
8434
       }
8449
     },
8435
     },
8436
+    "string_decoder": {
8437
+      "version": "1.0.3",
8438
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
8439
+      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
8440
+      "dev": true,
8441
+      "requires": {
8442
+        "safe-buffer": "5.1.1"
8443
+      }
8444
+    },
8450
     "string-length": {
8445
     "string-length": {
8451
       "version": "2.0.0",
8446
       "version": "2.0.0",
8452
       "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz",
8447
       "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz",
8485
         "strip-ansi": "3.0.1"
8480
         "strip-ansi": "3.0.1"
8486
       }
8481
       }
8487
     },
8482
     },
8488
-    "string_decoder": {
8489
-      "version": "1.0.3",
8490
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
8491
-      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
8492
-      "dev": true,
8493
-      "requires": {
8494
-        "safe-buffer": "5.1.1"
8495
-      }
8496
-    },
8497
     "stringstream": {
8483
     "stringstream": {
8498
       "version": "0.0.5",
8484
       "version": "0.0.5",
8499
       "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
8485
       "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
8865
     "ua-parser-js": {
8851
     "ua-parser-js": {
8866
       "version": "0.7.17",
8852
       "version": "0.7.17",
8867
       "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz",
8853
       "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz",
8868
-      "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==",
8869
-      "dev": true
8854
+      "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g=="
8870
     },
8855
     },
8871
     "uglify-js": {
8856
     "uglify-js": {
8872
       "version": "2.8.29",
8857
       "version": "2.8.29",
9085
     "whatwg-fetch": {
9070
     "whatwg-fetch": {
9086
       "version": "2.0.3",
9071
       "version": "2.0.3",
9087
       "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz",
9072
       "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz",
9088
-      "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=",
9089
-      "dev": true
9073
+      "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ="
9090
     },
9074
     },
9091
     "whatwg-url": {
9075
     "whatwg-url": {
9092
       "version": "4.8.0",
9076
       "version": "4.8.0",

+ 4
- 4
package.json View File

45
     "react-native": "*"
45
     "react-native": "*"
46
   },
46
   },
47
   "dependencies": {
47
   "dependencies": {
48
-    "lodash": "4.x.x"
48
+    "lodash": "4.x.x",
49
+    "prop-types": "15.x.x"
49
   },
50
   },
50
   "devDependencies": {
51
   "devDependencies": {
51
     "xo": "0.18.x",
52
     "xo": "0.18.x",
52
     "eslint-config-xo": "0.18.x",
53
     "eslint-config-xo": "0.18.x",
53
-    "eslint-config-xo-react": "0.14.x",
54
+    "eslint-config-xo-react": "0.13.x",
54
     "eslint-plugin-react": "7.x.x",
55
     "eslint-plugin-react": "7.x.x",
55
     "detox": "6.x.x",
56
     "detox": "6.x.x",
56
     "jest": "21.x.x",
57
     "jest": "21.x.x",
57
-    "mocha": "4.x.x",
58
+    "mocha": "3.x.x",
58
     "react": "16.0.0-alpha.6",
59
     "react": "16.0.0-alpha.6",
59
     "react-native": "0.44.0",
60
     "react-native": "0.44.0",
60
     "react-test-renderer": "16.0.0-alpha.6",
61
     "react-test-renderer": "16.0.0-alpha.6",
166
         }
167
         }
167
       ],
168
       ],
168
       "react/jsx-tag-spacing": 0,
169
       "react/jsx-tag-spacing": 0,
169
-      "react/jsx-curly-brace-presence": 0,
170
       "react/jsx-sort-props": 0,
170
       "react/jsx-sort-props": 0,
171
       "react/jsx-boolean-value": 0,
171
       "react/jsx-boolean-value": 0,
172
       "react/prop-types": 0,
172
       "react/prop-types": 0,

BIN
playground/img/1024.jpeg View File


BIN
playground/img/2048.jpeg View File


BIN
playground/img/400.jpeg View File


BIN
playground/img/4096.jpeg View File


BIN
playground/img/Icon-87.png View File


BIN
playground/img/fff.png View File


+ 9
- 3
playground/ios/playground.xcodeproj/project.pbxproj View File

309
 			isa = PBXGroup;
309
 			isa = PBXGroup;
310
 			children = (
310
 			children = (
311
 				7B8F2FEB1E840F6700110AEC /* libRCTAnimation.a */,
311
 				7B8F2FEB1E840F6700110AEC /* libRCTAnimation.a */,
312
-				7B8F2FED1E840F6700110AEC /* libRCTAnimation-tvOS.a */,
312
+				7B8F2FED1E840F6700110AEC /* libRCTAnimation.a */,
313
 			);
313
 			);
314
 			name = Products;
314
 			name = Products;
315
 			sourceTree = "<group>";
315
 			sourceTree = "<group>";
612
 			remoteRef = 7B8F2FEA1E840F6700110AEC /* PBXContainerItemProxy */;
612
 			remoteRef = 7B8F2FEA1E840F6700110AEC /* PBXContainerItemProxy */;
613
 			sourceTree = BUILT_PRODUCTS_DIR;
613
 			sourceTree = BUILT_PRODUCTS_DIR;
614
 		};
614
 		};
615
-		7B8F2FED1E840F6700110AEC /* libRCTAnimation-tvOS.a */ = {
615
+		7B8F2FED1E840F6700110AEC /* libRCTAnimation.a */ = {
616
 			isa = PBXReferenceProxy;
616
 			isa = PBXReferenceProxy;
617
 			fileType = archive.ar;
617
 			fileType = archive.ar;
618
-			path = "libRCTAnimation-tvOS.a";
618
+			path = libRCTAnimation.a;
619
 			remoteRef = 7B8F2FEC1E840F6700110AEC /* PBXContainerItemProxy */;
619
 			remoteRef = 7B8F2FEC1E840F6700110AEC /* PBXContainerItemProxy */;
620
 			sourceTree = BUILT_PRODUCTS_DIR;
620
 			sourceTree = BUILT_PRODUCTS_DIR;
621
 		};
621
 		};
783
 			isa = XCBuildConfiguration;
783
 			isa = XCBuildConfiguration;
784
 			buildSettings = {
784
 			buildSettings = {
785
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
785
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
786
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
787
+				CODE_SIGN_STYLE = Manual;
786
 				DEAD_CODE_STRIPPING = NO;
788
 				DEAD_CODE_STRIPPING = NO;
787
 				DEVELOPMENT_TEAM = "";
789
 				DEVELOPMENT_TEAM = "";
788
 				INFOPLIST_FILE = playground/Info.plist;
790
 				INFOPLIST_FILE = playground/Info.plist;
793
 				);
795
 				);
794
 				PRODUCT_BUNDLE_IDENTIFIER = com.reactnativenavigation.playground;
796
 				PRODUCT_BUNDLE_IDENTIFIER = com.reactnativenavigation.playground;
795
 				PRODUCT_NAME = playground;
797
 				PRODUCT_NAME = playground;
798
+				PROVISIONING_PROFILE_SPECIFIER = "";
796
 			};
799
 			};
797
 			name = Debug;
800
 			name = Debug;
798
 		};
801
 		};
800
 			isa = XCBuildConfiguration;
803
 			isa = XCBuildConfiguration;
801
 			buildSettings = {
804
 			buildSettings = {
802
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
805
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
806
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
807
+				CODE_SIGN_STYLE = Manual;
803
 				DEVELOPMENT_TEAM = "";
808
 				DEVELOPMENT_TEAM = "";
804
 				INFOPLIST_FILE = playground/Info.plist;
809
 				INFOPLIST_FILE = playground/Info.plist;
805
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
810
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
809
 				);
814
 				);
810
 				PRODUCT_BUNDLE_IDENTIFIER = com.reactnativenavigation.playground;
815
 				PRODUCT_BUNDLE_IDENTIFIER = com.reactnativenavigation.playground;
811
 				PRODUCT_NAME = playground;
816
 				PRODUCT_NAME = playground;
817
+				PROVISIONING_PROFILE_SPECIFIER = "";
812
 			};
818
 			};
813
 			name = Release;
819
 			name = Release;
814
 		};
820
 		};

+ 2
- 0
playground/ios/playground.xcodeproj/xcshareddata/xcschemes/playground.xcscheme View File

68
       buildConfiguration = "Debug"
68
       buildConfiguration = "Debug"
69
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
69
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
70
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
70
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
71
+      language = ""
71
       shouldUseLaunchSchemeArgsEnv = "NO">
72
       shouldUseLaunchSchemeArgsEnv = "NO">
72
       <Testables>
73
       <Testables>
73
          <TestableReference
74
          <TestableReference
104
       buildConfiguration = "Debug"
105
       buildConfiguration = "Debug"
105
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
106
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
106
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
107
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
108
+      language = ""
107
       launchStyle = "0"
109
       launchStyle = "0"
108
       useCustomWorkingDirectory = "NO"
110
       useCustomWorkingDirectory = "NO"
109
       ignoresPersistentStateOnLaunch = "NO"
111
       ignoresPersistentStateOnLaunch = "NO"

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

3
 
3
 
4
 function start() {
4
 function start() {
5
   registerContainers();
5
   registerContainers();
6
-
7
   Navigation.events().onAppLaunched(() => {
6
   Navigation.events().onAppLaunched(() => {
8
     Navigation.setRoot({
7
     Navigation.setRoot({
9
       container: {
8
       container: {

+ 94
- 0
playground/src/containers/CustomTransitionDestination.js View File

1
+const React = require('react');
2
+const { Component } = require('react');
3
+const { View, TouchableOpacity, Image, Text } = require('react-native');
4
+const Navigation = require('react-native-navigation');
5
+
6
+class CustomTransitionDestination extends Component {
7
+  constructor(props) {
8
+    super(props);
9
+    this.pop = this.pop.bind(this);
10
+    this.push = this.push.bind(this);
11
+  }
12
+
13
+  static get navigationOptions() {
14
+    return {
15
+      backButtonTransition: 'custom',
16
+      topBar: {
17
+        title: 'ye babyyyyyy',
18
+        textFontFamily: 'HelveticaNeue-Italic',
19
+        largeTitle: true
20
+      }
21
+    };
22
+  }
23
+  push() {
24
+    Navigation.push(this.props.containerId, {
25
+      name: 'navigation.playground.OptionsScreen'
26
+    });
27
+  }
28
+  pop() {
29
+    Navigation.pop(this.props.containerId, { customTransition: {
30
+      animations: [{ type: 'sharedElement', fromId: 'title2', toId: 'title1', startDelay: 0, springVelocity: 0.2, duration: 0.5 },
31
+            { type: 'sharedElement', toId: 'image1', fromId: 'customDestinationImage', startDelay: 0, springVelocity: 0.2, duration: 0.5 },
32
+            { type: 'sharedElement', toId: 'image2', fromId: 'customDestinationImage2', startDelay: 0, duration: 0.8 },
33
+            { fromId: 'image4', startY: 50, startX: 50, startAlpha: 0, startDelay: 0, duration: 0.8, springVelocity: 0.5 },
34
+            { fromId: 'customDestinationParagraph', endY: 50, endX: 50, endAlpha: 0, startAlpha: 1, startDelay: 0, duration: 0.8 }
35
+      ],
36
+      duration: 0.8
37
+    } });
38
+  }
39
+  render() {
40
+    return (
41
+      <View style={styles.root}>
42
+        <View>
43
+          <Navigation.Element resizeMode={'contain'} elementId={'customDestinationImage'}>
44
+            <Image resizeMode={'contain'} style={{ width: 300, height: 300 }} source={require('../../img/400.jpeg')} />
45
+          </Navigation.Element>
46
+          <Navigation.Element elementId={'customDestinationImage2'}>
47
+            <Image style={{ width: 100, height: 100 }} source={require('../../img/2048.jpeg')} />
48
+          </Navigation.Element>
49
+        </View>
50
+
51
+        <TouchableOpacity testID={'shared_image2'} onPress={this.pop}>
52
+          <Navigation.Element elementId={'title2'}>
53
+            <Text style={styles.h1}>{`Custom Transition Screen`}</Text>
54
+          </Navigation.Element>
55
+        </TouchableOpacity>
56
+        <Navigation.Element elementId={'customDestinationParagraph'}>
57
+          <Text style={styles.p}>{`Lorem ipsum dolor sit amet, consectetur adipiscing elit,
58
+           sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
59
+           Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
60
+           nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit 
61
+           in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
62
+          cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum`}
63
+          </Text>
64
+
65
+        </Navigation.Element>
66
+      </View>
67
+    );
68
+  }
69
+}
70
+module.exports = CustomTransitionDestination;
71
+
72
+const styles = {
73
+  root: {
74
+    flexGrow: 1,
75
+    justifyContent: 'center',
76
+    alignItems: 'center',
77
+    backgroundColor: '#f5fcff'
78
+  },
79
+  h1: {
80
+    fontSize: 24,
81
+    textAlign: 'left',
82
+    margin: 10
83
+  },
84
+  p: {
85
+    fontSize: 14,
86
+    margin: 10,
87
+    textAlign: 'left'
88
+  },
89
+  footer: {
90
+    fontSize: 10,
91
+    color: '#888',
92
+    marginTop: 10
93
+  }
94
+};

+ 94
- 0
playground/src/containers/CustomTransitionOrigin.js View File

1
+const React = require('react');
2
+const { Component } = require('react');
3
+const { View, Text, Image, TouchableOpacity } = require('react-native');
4
+const Navigation = require('react-native-navigation');
5
+
6
+class CustomTransitionOrigin extends Component {
7
+  constructor(props) {
8
+    super(props);
9
+    this.onClickNavigationIcon = this.onClickNavigationIcon.bind(this);
10
+  }
11
+  static get navigationOptions() {
12
+    return {
13
+      topBar: {
14
+        textFontFamily: 'HelveticaNeue-Italic',
15
+        textFontSize: 16,
16
+        largeTitle: false
17
+      }
18
+    };
19
+  }
20
+  render() {
21
+    return (
22
+      <View style={styles.root}>
23
+        <Navigation.Element elementId="title1">
24
+          <Text style={styles.h1}>Custom Transition Screen</Text>
25
+        </Navigation.Element>
26
+        <View style={{ flex: 1, justifyContent: 'flex-start' }}>
27
+          <TouchableOpacity testID="shared_image1" activeOpacity={0.5} onPress={this.onClickNavigationIcon}>
28
+            <Navigation.Element resizeMode="cover" elementId="image1">
29
+              <Image resizeMode="cover" style={styles.gyroImage} source={require('../../img/400.jpeg')} />
30
+            </Navigation.Element>
31
+          </TouchableOpacity>
32
+          <TouchableOpacity activeOpacity={0.5} onPress={this.onClickNavigationIcon}>
33
+            <Navigation.Element elementId="image2">
34
+              <Image style={styles.gyroImage} source={require('../../img/2048.jpeg')} />
35
+            </Navigation.Element>
36
+          </TouchableOpacity>
37
+          <TouchableOpacity activeOpacity={0.5} onPress={this.onClickNavigationIcon}>
38
+            <Navigation.Element elementId="image3">
39
+              <Image style={styles.gyroImage} source={require('../../img/Icon-87.png')} />
40
+            </Navigation.Element>
41
+          </TouchableOpacity>
42
+          <TouchableOpacity activeOpacity={0.5} onPress={this.onClickNavigationIcon}>
43
+            <Navigation.Element elementId="image4">
44
+              <Image style={styles.gyroImage} source={require('../../img/Icon-87.png')} />
45
+            </Navigation.Element>
46
+          </TouchableOpacity>
47
+        </View>
48
+
49
+      </View>
50
+    );
51
+  }
52
+  onClickNavigationIcon() {
53
+    Navigation.push(this.props.containerId, {
54
+      name: 'navigation.playground.CustomTransitionDestination',
55
+      customTransition: {
56
+        animations: [
57
+              { type: 'sharedElement', fromId: 'title1', toId: 'title2', startDelay: 0, springVelocity: 0.2, duration: 0.5 },
58
+              { type: 'sharedElement', fromId: 'image1', toId: 'customDestinationImage', startDelay: 0, springVelocity: 0.9, springDamping: 0.9, duration: 0.8, interactivePop: true },
59
+              { type: 'sharedElement', fromId: 'image2', toId: 'customDestinationImage2', startDelay: 0, duration: 0.8 },
60
+              { fromId: 'image4', endY: 50, endX: 50, endAlpha: 0, startDelay: 0, duration: 0.8, springVelocity: 0.5 },
61
+              { fromId: 'customDestinationParagraph', startY: 50, startAlpha: 0, endAlpha: 1, startDelay: 0, duration: 0.8 }
62
+
63
+        ],
64
+        duration: 0.8
65
+      }
66
+    });
67
+  }
68
+}
69
+module.exports = CustomTransitionOrigin;
70
+
71
+const styles = {
72
+  root: {
73
+    alignItems: 'center',
74
+    flexGrow: 1,
75
+    backgroundColor: '#f5fcff'
76
+  },
77
+  h1: {
78
+
79
+    fontSize: 24,
80
+    textAlign: 'center',
81
+    marginTop: 100
82
+  },
83
+  footer: {
84
+    fontSize: 10,
85
+    color: '#888',
86
+    marginTop: 10
87
+  },
88
+  gyroImage: {
89
+    marginTop: 10,
90
+    width: 100,
91
+    height: 100
92
+  }
93
+};
94
+

+ 29
- 1
playground/src/containers/OptionsScreen.js View File

10
 const BUTTON_LEFT = 'buttonLeft';
10
 const BUTTON_LEFT = 'buttonLeft';
11
 
11
 
12
 class OptionsScreen extends Component {
12
 class OptionsScreen extends Component {
13
-
14
   static get navigationOptions() {
13
   static get navigationOptions() {
15
     return {
14
     return {
16
       topBar: {
15
       topBar: {
17
         title: 'Static Title',
16
         title: 'Static Title',
18
         textColor: 'black',
17
         textColor: 'black',
18
+        largeTitle: false,
19
+        hidden: false,
19
         textFontSize: 16,
20
         textFontSize: 16,
20
         textFontFamily: 'HelveticaNeue-Italic'
21
         textFontFamily: 'HelveticaNeue-Italic'
21
       },
22
       },
40
     this.onClickShowTopBar = this.onClickShowTopBar.bind(this);
41
     this.onClickShowTopBar = this.onClickShowTopBar.bind(this);
41
     this.onClickHideTopBar = this.onClickHideTopBar.bind(this);
42
     this.onClickHideTopBar = this.onClickHideTopBar.bind(this);
42
     this.onClickScrollViewScreen = this.onClickScrollViewScreen.bind(this);
43
     this.onClickScrollViewScreen = this.onClickScrollViewScreen.bind(this);
44
+    this.onClickTopBarTransparent = this.onClickTopBarTransparent.bind(this);
45
+    this.onClickTopBarOpaque = this.onClickTopBarOpaque.bind(this);
46
+    this.onClickCustomTranstition = this.onClickCustomTranstition.bind(this);
43
   }
47
   }
44
 
48
 
45
   render() {
49
   render() {
49
         <Button title="Dynamic Options" onPress={this.onClickDynamicOptions} />
53
         <Button title="Dynamic Options" onPress={this.onClickDynamicOptions} />
50
         <Button title="Show Top Bar" onPress={this.onClickShowTopBar} />
54
         <Button title="Show Top Bar" onPress={this.onClickShowTopBar} />
51
         <Button title="Hide Top Bar" onPress={this.onClickHideTopBar} />
55
         <Button title="Hide Top Bar" onPress={this.onClickHideTopBar} />
56
+        <Button title="Top Bar Transparent" onPress={this.onClickTopBarTransparent} />
57
+        <Button title="Top Bar Opaque" onPress={this.onClickTopBarOpaque} />
52
         <Button title="scrollView Screen" onPress={this.onClickScrollViewScreen} />
58
         <Button title="scrollView Screen" onPress={this.onClickScrollViewScreen} />
59
+        <Button title="Custom Transition" onPress={this.onClickCustomTranstition} />
53
         <Button title="Show custom alert" onPress={this.onClickAlert} />
60
         <Button title="Show custom alert" onPress={this.onClickAlert} />
54
         <Button title="Show snackbar" onPress={this.onClickSnackbar} />
61
         <Button title="Show snackbar" onPress={this.onClickSnackbar} />
55
         <Text style={styles.footer}>{`this.props.containerId = ${this.props.containerId}`}</Text>
62
         <Text style={styles.footer}>{`this.props.containerId = ${this.props.containerId}`}</Text>
91
       topBar: {
98
       topBar: {
92
         title: 'Dynamic Title',
99
         title: 'Dynamic Title',
93
         textColor: '#00FFFF',
100
         textColor: '#00FFFF',
101
+        largeTitle: false,
94
         buttonColor: 'red',
102
         buttonColor: 'red',
95
         textFontSize: 20,
103
         textFontSize: 20,
96
         textFontFamily: 'HelveticaNeue-CondensedBold'
104
         textFontFamily: 'HelveticaNeue-CondensedBold'
104
     });
112
     });
105
   }
113
   }
106
 
114
 
115
+  onClickCustomTranstition() {
116
+    Navigation.push(this.props.containerId, {
117
+      name: 'navigation.playground.CustomTransitionOrigin'
118
+    });
119
+  }
120
+
121
+  onClickTopBarTransparent() {
122
+    Navigation.setOptions(this.props.containerId, {
123
+      topBar: {
124
+        transparent: true
125
+      }
126
+    });
127
+  }
128
+  onClickTopBarOpaque() {
129
+    Navigation.setOptions(this.props.containerId, {
130
+      topBar: {
131
+        transparent: false
132
+      }
133
+    });
134
+  }
107
   onClickShowTopBar() {
135
   onClickShowTopBar() {
108
     Navigation.setOptions(this.props.containerId, {
136
     Navigation.setOptions(this.props.containerId, {
109
       topBar: {
137
       topBar: {

+ 8
- 7
playground/src/containers/ScrollViewScreen.js View File

24
 
24
 
25
   render() {
25
   render() {
26
     return (
26
     return (
27
-      <ScrollView testID="scrollView" contentContainerStyle={styles.contentContainer}>
28
-        <View>
29
-          <Button title="Toggle Top Bar Hide On Scroll" onPress={this.onClickToggleTopBarHideOnScroll} />
30
-        </View>
31
-      </ScrollView>
27
+      <View>
28
+        <ScrollView testID="scrollView" contentContainerStyle={styles.contentContainer}>
29
+          <View>
30
+            <Button title="Toggle Top Bar Hide On Scroll" onPress={this.onClickToggleTopBarHideOnScroll} />
31
+          </View>
32
+        </ScrollView>
33
+      </View>
32
     );
34
     );
33
   }
35
   }
34
 
36
 
45
 
47
 
46
 const styles = StyleSheet.create({
48
 const styles = StyleSheet.create({
47
   contentContainer: {
49
   contentContainer: {
48
-    paddingVertical: 20,
49
     alignItems: 'center',
50
     alignItems: 'center',
50
-    height: 1000
51
+    height: 1200
51
   }
52
   }
52
 });
53
 });
53
 
54
 

+ 7
- 1
playground/src/containers/WelcomeScreen.js View File

1
 const React = require('react');
1
 const React = require('react');
2
 const { Component } = require('react');
2
 const { Component } = require('react');
3
 const { View, Text, Button } = require('react-native');
3
 const { View, Text, Button } = require('react-native');
4
-
5
 const Navigation = require('react-native-navigation');
4
 const Navigation = require('react-native-navigation');
6
 
5
 
7
 class WelcomeScreen extends Component {
6
 class WelcomeScreen extends Component {
7
+  static get navigationOptions() {
8
+    return {
9
+      topBar: {
10
+        largeTitle: false
11
+      }
12
+    };
13
+  }
8
   constructor(props) {
14
   constructor(props) {
9
     super(props);
15
     super(props);
10
     this.onClickPush = this.onClickPush.bind(this);
16
     this.onClickPush = this.onClickPush.bind(this);

+ 4
- 0
playground/src/containers/index.js View File

8
 const OrientationSelectScreen = require('./OrientationSelectScreen');
8
 const OrientationSelectScreen = require('./OrientationSelectScreen');
9
 const OrientationDetectScreen = require('./OrientationDetectScreen');
9
 const OrientationDetectScreen = require('./OrientationDetectScreen');
10
 const ScrollViewScreen = require('./ScrollViewScreen');
10
 const ScrollViewScreen = require('./ScrollViewScreen');
11
+const CustomTransitionOrigin = require('./CustomTransitionOrigin');
12
+const CustomTransitionDestination = require('./CustomTransitionDestination');
11
 const CustomDialog = require('./CustomDialog');
13
 const CustomDialog = require('./CustomDialog');
12
 const BandHandlerScreen = require('./BackHandlerScreen');
14
 const BandHandlerScreen = require('./BackHandlerScreen');
13
 
15
 
14
 function registerContainers() {
16
 function registerContainers() {
17
+  Navigation.registerContainer(`navigation.playground.CustomTransitionDestination`, () => CustomTransitionDestination);
18
+  Navigation.registerContainer(`navigation.playground.CustomTransitionOrigin`, () => CustomTransitionOrigin);
15
   Navigation.registerContainer(`navigation.playground.ScrollViewScreen`, () => ScrollViewScreen);
19
   Navigation.registerContainer(`navigation.playground.ScrollViewScreen`, () => ScrollViewScreen);
16
   Navigation.registerContainer(`navigation.playground.WelcomeScreen`, () => WelcomeScreen);
20
   Navigation.registerContainer(`navigation.playground.WelcomeScreen`, () => WelcomeScreen);
17
   Navigation.registerContainer(`navigation.playground.ModalScreen`, () => ModalScreen);
21
   Navigation.registerContainer(`navigation.playground.ModalScreen`, () => ModalScreen);