Parcourir la 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 il y a 7 ans
Parent
révision
49bd92d4b5
66 fichiers modifiés avec 1804 ajouts et 131 suppressions
  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 Voir le fichier

@@ -0,0 +1,20 @@
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 Voir le fichier

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

+ 8
- 0
e2e/ScreenStyle.test.js Voir le fichier

@@ -45,6 +45,14 @@ describe('screen style', () => {
45 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 56
   it('set Tab Bar badge on a current Tab', async () => {
49 57
     await elementByLabel('Switch to tab based app').tap();
50 58
     await elementByLabel('Set Tab Badge').tap();

+ 12
- 0
lib/ios/RNNAnimatedView.h Voir le fichier

@@ -0,0 +1,12 @@
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 Voir le fichier

@@ -0,0 +1,65 @@
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 Voir le fichier

@@ -0,0 +1,8 @@
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 Voir le fichier

@@ -0,0 +1,157 @@
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 Voir le fichier

@@ -3,7 +3,7 @@
3 3
 @implementation RNNBridgeModule {
4 4
 	RNNCommandsHandler* _commandsHandler;
5 5
 }
6
-
6
+@synthesize bridge = _bridge;
7 7
 RCT_EXPORT_MODULE();
8 8
 
9 9
 - (dispatch_queue_t)methodQueue {
@@ -30,8 +30,8 @@ RCT_EXPORT_METHOD(push:(NSString*)containerId layout:(NSDictionary*)layout) {
30 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 37
 RCT_EXPORT_METHOD(popTo:(NSString*)containerId) {

+ 2
- 2
lib/ios/RNNCommandsHandler.h Voir le fichier

@@ -6,7 +6,7 @@
6 6
 
7 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 11
 -(void) setRoot:(NSDictionary*)layout;
12 12
 
@@ -14,7 +14,7 @@
14 14
 
15 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 19
 -(void) popTo:(NSString*)containerId;
20 20
 

+ 26
- 8
lib/ios/RNNCommandsHandler.m Voir le fichier

@@ -1,6 +1,4 @@
1
-
2 1
 #import "RNNCommandsHandler.h"
3
-
4 2
 #import "RNNModalManager.h"
5 3
 #import "RNNNavigationStackManager.h"
6 4
 #import "RNNNavigationOptions.h"
@@ -9,12 +7,14 @@
9 7
 @implementation RNNCommandsHandler {
10 8
 	RNNControllerFactory *_controllerFactory;
11 9
 	RNNStore *_store;
10
+	RCTBridge* _bridge;
12 11
 	RNNNavigationStackManager* _navigationStackManager;
13 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 16
 	self = [super init];
17
+	_bridge = bridge;
18 18
 	_store = store;
19 19
 	_controllerFactory = controllerFactory;
20 20
 	_navigationStackManager = [[RNNNavigationStackManager alloc] initWithStore:_store];
@@ -47,17 +47,35 @@
47 47
 	}
48 48
 }
49 49
 
50
--(void) push:(NSString*)containerId layout:(NSDictionary*)layout {
50
+-(void)push:(NSString*)containerId layout:(NSDictionary*)layout {
51 51
 	[self assertReady];
52
-	
52
+	NSDictionary* customAnimation = layout[@"data"][@"customTransition"];
53 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 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 81
 -(void) popTo:(NSString*)containerId {

+ 6
- 0
lib/ios/RNNElement.h Voir le fichier

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

+ 30
- 0
lib/ios/RNNElement.m Voir le fichier

@@ -0,0 +1,30 @@
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 Voir le fichier

@@ -0,0 +1,14 @@
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 Voir le fichier

@@ -0,0 +1,56 @@
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 Voir le fichier

@@ -0,0 +1,12 @@
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 Voir le fichier

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

+ 15
- 0
lib/ios/RNNInteractivePopAnimator.h Voir le fichier

@@ -0,0 +1,15 @@
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 Voir le fichier

@@ -0,0 +1,175 @@
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 Voir le fichier

@@ -4,8 +4,9 @@
4 4
 
5 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 10
 -(void)showModal:(UIViewController*)viewController;
10 11
 -(void)dismissModal:(NSString*)containerId;
11 12
 -(void)dismissAllModals;

+ 19
- 2
lib/ios/RNNModalManager.m Voir le fichier

@@ -11,10 +11,27 @@
11 11
 	_store = store;
12 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 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 37
 -(void)dismissModal:(NSString *)containerId {

+ 0
- 1
lib/ios/RNNNavigationController.h Voir le fichier

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

+ 4
- 0
lib/ios/RNNNavigationOptions.h Voir le fichier

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

+ 59
- 7
lib/ios/RNNNavigationOptions.m Voir le fichier

@@ -6,9 +6,12 @@
6 6
 
7 7
 const NSInteger BLUR_STATUS_TAG = 78264801;
8 8
 const NSInteger BLUR_TOPBAR_TAG = 78264802;
9
+const NSInteger TOP_BAR_TRANSPARENT_TAG = 78264803;
9 10
 
10 11
 @implementation RNNNavigationOptions
11 12
 
13
+
14
+
12 15
 -(instancetype)init {
13 16
 	return [self initWithDict:@{}];
14 17
 }
@@ -17,6 +20,7 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
17 20
 	self = [super init];
18 21
 	self.statusBarHidden = [navigationOptions objectForKey:@"statusBarHidden"];
19 22
 	self.screenBackgroundColor = [navigationOptions objectForKey:@"screenBackgroundColor"];
23
+	self.backButtonTransition = [navigationOptions objectForKey:@"backButtonTransition"];
20 24
 	self.orientation = [navigationOptions objectForKey:@"orientation"];
21 25
 	self.leftButtons = [navigationOptions objectForKey:@"leftButtons"];
22 26
 	self.rightButtons = [navigationOptions objectForKey:@"rightButtons"];
@@ -51,6 +55,21 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
51 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 73
 		if (self.topBar.textFontFamily || self.topBar.textFontSize || self.topBar.textColor) {
55 74
 			NSMutableDictionary* navigationBarTitleTextAttributes = [NSMutableDictionary new];
56 75
 			if (self.topBar.textColor) {
@@ -106,17 +125,37 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
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 155
 		if (self.topBar.translucent) {
110 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 159
 		if (self.topBar.noBorder) {
121 160
 			if ([self.topBar.noBorder boolValue]) {
122 161
 				viewController.navigationController.navigationBar
@@ -194,5 +233,18 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
194 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 250
 @end

+ 6
- 2
lib/ios/RNNNavigationStackManager.h Voir le fichier

@@ -4,10 +4,14 @@
4 4
 
5 5
 @interface RNNNavigationStackManager : NSObject
6 6
 
7
+@property (nonatomic, strong) UIViewController* fromVC;
8
+@property (nonatomic, strong) RNNRootViewController* toVC;
9
+@property (nonatomic) int loadCount;
7 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 15
 -(void)popTo:(NSString*)containerId;
12 16
 -(void)popToRoot:(NSString*)containerId;
13 17
 

+ 52
- 4
lib/ios/RNNNavigationStackManager.m Voir le fichier

@@ -1,6 +1,10 @@
1 1
 #import "RNNNavigationStackManager.h"
2 2
 #import "RNNRootViewController.h"
3
+#import "React/RCTUIManager.h"
4
+#import "RNNAnimator.h"
3 5
 
6
+
7
+dispatch_queue_t RCTGetUIManagerQueue(void);
4 8
 @implementation RNNNavigationStackManager {
5 9
 	RNNStore *_store;
6 10
 }
@@ -11,16 +15,60 @@
11 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 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 60
 	UIViewController* vc = [_store findContainerForId:containerId];
21 61
 	UINavigationController* nvc = [vc navigationController];
22 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 72
 	} else {
25 73
 		NSMutableArray * vcs = nvc.viewControllers.mutableCopy;
26 74
 		[vcs removeObject:vc];

+ 3
- 3
lib/ios/RNNRootViewController.h Voir le fichier

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

+ 35
- 3
lib/ios/RNNRootViewController.m Voir le fichier

@@ -1,6 +1,7 @@
1 1
 
2 2
 #import "RNNRootViewController.h"
3 3
 #import <React/RCTConvert.h>
4
+#import "RNNAnimator.h"
4 5
 #import "RNNNavigationButtons.h"
5 6
 
6 7
 @interface RNNRootViewController()
@@ -28,18 +29,23 @@
28 29
 											 selector:@selector(onJsReload)
29 30
 												 name:RCTJavaScriptWillStartLoadingNotification
30 31
 											   object:nil];
31
-	
32
+	self.animator = [[RNNAnimator alloc] init];
33
+	self.navigationController.modalPresentationStyle = UIModalPresentationCustom;
34
+	self.navigationController.delegate = self;
32 35
 	self.navigationButtons = [[RNNNavigationButtons alloc] initWithViewController:self];
33
-	
34 36
 	return self;
35 37
 }
36
-
38
+	
37 39
 -(void)viewWillAppear:(BOOL)animated{
38 40
 	[super viewWillAppear:animated];
39 41
 	[self.navigationOptions applyOn:self];
40 42
 	[self applyNavigationButtons];
41 43
 }
42 44
 
45
+- (void)viewDidLoad {
46
+	[super viewDidLoad];
47
+}
48
+
43 49
 - (BOOL)prefersStatusBarHidden {
44 50
 	if ([self.navigationOptions.statusBarHidden boolValue]) {
45 51
 		return YES;
@@ -71,6 +77,32 @@
71 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 106
 -(void) applyNavigationButtons{
75 107
 	[self.navigationButtons applyLeftButtons:self.navigationOptions.leftButtons rightButtons:self.navigationOptions.rightButtons];
76 108
 }

+ 1
- 0
lib/ios/RNNTopBarOptions.h Voir le fichier

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

+ 1
- 0
lib/ios/RNNTopBarOptions.m Voir le fichier

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

+ 33
- 0
lib/ios/RNNTransitionStateHolder.h Voir le fichier

@@ -0,0 +1,33 @@
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 Voir le fichier

@@ -0,0 +1,32 @@
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 Voir le fichier

@@ -0,0 +1,8 @@
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 Voir le fichier

@@ -0,0 +1,25 @@
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 Voir le fichier

@@ -0,0 +1,27 @@
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 Voir le fichier

@@ -0,0 +1,49 @@
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 Voir le fichier

@@ -70,7 +70,7 @@
70 70
 	
71 71
 	id<RNNRootViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
72 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 74
 	RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
75 75
 	
76 76
 	return @[bridgeModule,eventEmitter];

+ 122
- 1
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj Voir le fichier

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

+ 3
- 1
lib/ios/ReactNativeNavigation.xcodeproj/xcshareddata/xcschemes/ReactNativeNavigation.xcscheme Voir le fichier

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

+ 15
- 11
lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m Voir le fichier

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

+ 1
- 2
lib/ios/ReactNativeNavigationTests/RNNNavigationStackManagerTest.m Voir le fichier

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

+ 43
- 11
lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m Voir le fichier

@@ -172,16 +172,6 @@
172 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 175
 -(void)testTabBadge {
186 176
 	NSString* tabBadgeInput = @"5";
187 177
 	self.options.tabBar.tabBadge = tabBadgeInput;
@@ -196,6 +186,29 @@
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 213
 -(void)testTopBarTextFontSize_withoutTextFontFamily_withoutTextColor {
201 214
 	NSNumber* topBarTextFontSizeInput = @(15);
@@ -464,7 +477,26 @@
464 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 500
 -(void)testTopBarBlur_false {
469 501
 	NSNumber* topBarBlurInput = @(0);
470 502
 	self.options.topBar.blur = topBarBlurInput;

+ 26
- 0
lib/ios/ReactNativeNavigationTests/RNNTransitionStateHolderTest.m Voir le fichier

@@ -0,0 +1,26 @@
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 Voir le fichier

@@ -0,0 +1,24 @@
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 Voir le fichier

@@ -0,0 +1,280 @@
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 Voir le fichier

@@ -8,6 +8,7 @@ const LayoutTreeParser = require('./commands/LayoutTreeParser');
8 8
 const LayoutTreeCrawler = require('./commands/LayoutTreeCrawler');
9 9
 const PrivateEventsListener = require('./events/PrivateEventsListener');
10 10
 const PublicEventsRegistry = require('./events/PublicEventsRegistry');
11
+const Element = require('./adapters/Element');
11 12
 
12 13
 class Navigation {
13 14
   constructor() {
@@ -22,8 +23,8 @@ class Navigation {
22 23
     this.publicEventsRegistry = new PublicEventsRegistry(this.nativeEventsReceiver);
23 24
     this.privateEventsListener = new PrivateEventsListener(this.nativeEventsReceiver, this.store);
24 25
     this.privateEventsListener.listenAndHandlePrivateEvents();
26
+    this.Element = Element;
25 27
   }
26
-
27 28
   registerContainer(containerName, getContainerFunc) {
28 29
     this.containerRegistry.registerContainer(containerName, getContainerFunc);
29 30
   }
@@ -56,8 +57,8 @@ class Navigation {
56 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 64
   popTo(containerId) {

+ 20
- 0
lib/src/adapters/Element.js Voir le fichier

@@ -0,0 +1,20 @@
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 Voir le fichier

@@ -21,8 +21,8 @@ class NativeCommandsSender {
21 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 28
   popTo(containerId) {

+ 2
- 2
lib/src/commands/Commands.js Voir le fichier

@@ -49,8 +49,8 @@ class Commands {
49 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 56
   popTo(containerId) {

+ 13
- 1
lib/src/commands/Commands.test.js Voir le fichier

@@ -193,7 +193,19 @@ describe('Commands', () => {
193 193
     it('pops a container, passing containerId', () => {
194 194
       uut.pop('theContainerId');
195 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 211
     it('pop returns a promise that resolves to containerId', async () => {

+ 26
- 42
package-lock.json Voir le fichier

@@ -303,8 +303,7 @@
303 303
     "asap": {
304 304
       "version": "2.0.6",
305 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 308
     "asn1": {
310 309
       "version": "0.2.3",
@@ -1851,8 +1850,7 @@
1851 1850
     "core-js": {
1852 1851
       "version": "1.2.7",
1853 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 1855
     "core-util-is": {
1858 1856
       "version": "1.0.2",
@@ -2244,7 +2242,6 @@
2244 2242
       "version": "0.1.12",
2245 2243
       "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
2246 2244
       "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
2247
-      "dev": true,
2248 2245
       "requires": {
2249 2246
         "iconv-lite": "0.4.19"
2250 2247
       }
@@ -3058,7 +3055,6 @@
3058 3055
       "version": "0.8.16",
3059 3056
       "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz",
3060 3057
       "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=",
3061
-      "dev": true,
3062 3058
       "requires": {
3063 3059
         "core-js": "1.2.7",
3064 3060
         "isomorphic-fetch": "2.2.1",
@@ -4069,22 +4065,22 @@
4069 4065
             }
4070 4066
           }
4071 4067
         },
4072
-        "string-width": {
4073
-          "version": "1.0.2",
4068
+        "string_decoder": {
4069
+          "version": "1.0.1",
4074 4070
           "bundled": true,
4075 4071
           "dev": true,
4076 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 4078
           "bundled": true,
4085 4079
           "dev": true,
4086 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 4086
         "stringstream": {
@@ -4640,8 +4636,7 @@
4640 4636
     "iconv-lite": {
4641 4637
       "version": "0.4.19",
4642 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 4641
     "ignore": {
4647 4642
       "version": "3.3.7",
@@ -5056,8 +5051,7 @@
5056 5051
     "is-stream": {
5057 5052
       "version": "1.1.0",
5058 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 5056
     "is-symbol": {
5063 5057
       "version": "1.0.1",
@@ -5108,7 +5102,6 @@
5108 5102
       "version": "2.2.1",
5109 5103
       "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
5110 5104
       "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
5111
-      "dev": true,
5112 5105
       "requires": {
5113 5106
         "node-fetch": "1.7.3",
5114 5107
         "whatwg-fetch": "2.0.3"
@@ -5566,8 +5559,7 @@
5566 5559
     "js-tokens": {
5567 5560
       "version": "3.0.2",
5568 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 5564
     "js-types": {
5573 5565
       "version": "1.0.0",
@@ -5998,7 +5990,6 @@
5998 5990
       "version": "1.3.1",
5999 5991
       "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
6000 5992
       "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
6001
-      "dev": true,
6002 5993
       "requires": {
6003 5994
         "js-tokens": "3.0.2"
6004 5995
       }
@@ -6391,7 +6382,6 @@
6391 6382
       "version": "1.7.3",
6392 6383
       "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
6393 6384
       "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
6394
-      "dev": true,
6395 6385
       "requires": {
6396 6386
         "encoding": "0.1.12",
6397 6387
         "is-stream": "1.1.0"
@@ -6490,8 +6480,7 @@
6490 6480
     "object-assign": {
6491 6481
       "version": "4.1.1",
6492 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 6485
     "object-keys": {
6497 6486
       "version": "1.0.11",
@@ -6943,7 +6932,6 @@
6943 6932
       "version": "7.3.1",
6944 6933
       "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
6945 6934
       "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
6946
-      "dev": true,
6947 6935
       "requires": {
6948 6936
         "asap": "2.0.6"
6949 6937
       }
@@ -6958,7 +6946,6 @@
6958 6946
       "version": "15.6.0",
6959 6947
       "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz",
6960 6948
       "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=",
6961
-      "dev": true,
6962 6949
       "requires": {
6963 6950
         "fbjs": "0.8.16",
6964 6951
         "loose-envify": "1.3.1",
@@ -8196,8 +8183,7 @@
8196 8183
     "setimmediate": {
8197 8184
       "version": "1.0.5",
8198 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 8188
     "shebang-command": {
8203 8189
       "version": "1.2.0",
@@ -8447,6 +8433,15 @@
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 8445
     "string-length": {
8451 8446
       "version": "2.0.0",
8452 8447
       "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz",
@@ -8485,15 +8480,6 @@
8485 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 8483
     "stringstream": {
8498 8484
       "version": "0.0.5",
8499 8485
       "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
@@ -8865,8 +8851,7 @@
8865 8851
     "ua-parser-js": {
8866 8852
       "version": "0.7.17",
8867 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 8856
     "uglify-js": {
8872 8857
       "version": "2.8.29",
@@ -9085,8 +9070,7 @@
9085 9070
     "whatwg-fetch": {
9086 9071
       "version": "2.0.3",
9087 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 9075
     "whatwg-url": {
9092 9076
       "version": "4.8.0",

+ 4
- 4
package.json Voir le fichier

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

BIN
playground/img/1024.jpeg Voir le fichier


BIN
playground/img/2048.jpeg Voir le fichier


BIN
playground/img/400.jpeg Voir le fichier


BIN
playground/img/4096.jpeg Voir le fichier


BIN
playground/img/Icon-87.png Voir le fichier


BIN
playground/img/fff.png Voir le fichier


+ 9
- 3
playground/ios/playground.xcodeproj/project.pbxproj Voir le fichier

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

+ 2
- 0
playground/ios/playground.xcodeproj/xcshareddata/xcschemes/playground.xcscheme Voir le fichier

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

+ 0
- 1
playground/src/app.js Voir le fichier

@@ -3,7 +3,6 @@ const { registerContainers } = require('./containers');
3 3
 
4 4
 function start() {
5 5
   registerContainers();
6
-
7 6
   Navigation.events().onAppLaunched(() => {
8 7
     Navigation.setRoot({
9 8
       container: {

+ 94
- 0
playground/src/containers/CustomTransitionDestination.js Voir le fichier

@@ -0,0 +1,94 @@
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 Voir le fichier

@@ -0,0 +1,94 @@
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 Voir le fichier

@@ -10,12 +10,13 @@ const BUTTON_TWO = 'buttonTwo';
10 10
 const BUTTON_LEFT = 'buttonLeft';
11 11
 
12 12
 class OptionsScreen extends Component {
13
-
14 13
   static get navigationOptions() {
15 14
     return {
16 15
       topBar: {
17 16
         title: 'Static Title',
18 17
         textColor: 'black',
18
+        largeTitle: false,
19
+        hidden: false,
19 20
         textFontSize: 16,
20 21
         textFontFamily: 'HelveticaNeue-Italic'
21 22
       },
@@ -40,6 +41,9 @@ class OptionsScreen extends Component {
40 41
     this.onClickShowTopBar = this.onClickShowTopBar.bind(this);
41 42
     this.onClickHideTopBar = this.onClickHideTopBar.bind(this);
42 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 49
   render() {
@@ -49,7 +53,10 @@ class OptionsScreen extends Component {
49 53
         <Button title="Dynamic Options" onPress={this.onClickDynamicOptions} />
50 54
         <Button title="Show Top Bar" onPress={this.onClickShowTopBar} />
51 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 58
         <Button title="scrollView Screen" onPress={this.onClickScrollViewScreen} />
59
+        <Button title="Custom Transition" onPress={this.onClickCustomTranstition} />
53 60
         <Button title="Show custom alert" onPress={this.onClickAlert} />
54 61
         <Button title="Show snackbar" onPress={this.onClickSnackbar} />
55 62
         <Text style={styles.footer}>{`this.props.containerId = ${this.props.containerId}`}</Text>
@@ -91,6 +98,7 @@ class OptionsScreen extends Component {
91 98
       topBar: {
92 99
         title: 'Dynamic Title',
93 100
         textColor: '#00FFFF',
101
+        largeTitle: false,
94 102
         buttonColor: 'red',
95 103
         textFontSize: 20,
96 104
         textFontFamily: 'HelveticaNeue-CondensedBold'
@@ -104,6 +112,26 @@ class OptionsScreen extends Component {
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 135
   onClickShowTopBar() {
108 136
     Navigation.setOptions(this.props.containerId, {
109 137
       topBar: {

+ 8
- 7
playground/src/containers/ScrollViewScreen.js Voir le fichier

@@ -24,11 +24,13 @@ class ScrollViewScreen extends Component {
24 24
 
25 25
   render() {
26 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,9 +47,8 @@ module.exports = ScrollViewScreen;
45 47
 
46 48
 const styles = StyleSheet.create({
47 49
   contentContainer: {
48
-    paddingVertical: 20,
49 50
     alignItems: 'center',
50
-    height: 1000
51
+    height: 1200
51 52
   }
52 53
 });
53 54
 

+ 7
- 1
playground/src/containers/WelcomeScreen.js Voir le fichier

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

+ 4
- 0
playground/src/containers/index.js Voir le fichier

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