소스 검색

V2 animations (#2878)

* passProps to buttons

* push and pop custom transitions

* refactored defaultOptions

* custom animations support for show and dismiss modal
yogevbd 6 년 전
부모
커밋
8543d80fa2
No account linked to committer's email address
36개의 변경된 파일351개의 추가작업 그리고 82개의 파일을 삭제
  1. 0
    4
      lib/ios/RNNAnimationOptions.m
  2. 2
    6
      lib/ios/RNNAnimator.m
  3. 3
    8
      lib/ios/RNNCommandsHandler.m
  4. 1
    1
      lib/ios/RNNControllerFactory.h
  5. 3
    2
      lib/ios/RNNControllerFactory.m
  6. 11
    0
      lib/ios/RNNModalAnimation.h
  7. 42
    0
      lib/ios/RNNModalAnimation.m
  8. 13
    1
      lib/ios/RNNModalManager.m
  9. 13
    0
      lib/ios/RNNNavigationController.m
  10. 2
    1
      lib/ios/RNNNavigationOptions.h
  11. 2
    14
      lib/ios/RNNNavigationOptions.m
  12. 1
    1
      lib/ios/RNNNavigationStackManager.h
  13. 6
    7
      lib/ios/RNNNavigationStackManager.m
  14. 7
    2
      lib/ios/RNNOptions.m
  15. 9
    0
      lib/ios/RNNPushAnimation.h
  16. 34
    0
      lib/ios/RNNPushAnimation.m
  17. 14
    5
      lib/ios/RNNRootViewController.m
  18. 2
    2
      lib/ios/RNNRootViewProtocol.h
  19. 10
    0
      lib/ios/RNNScreenTransition.h
  20. 14
    0
      lib/ios/RNNScreenTransition.m
  21. 4
    0
      lib/ios/RNNSideMenuChildVC.m
  22. 4
    0
      lib/ios/RNNSideMenuController.m
  23. 4
    0
      lib/ios/RNNTabBarController.m
  24. 4
    0
      lib/ios/RNNTopTabsViewController.m
  25. 2
    0
      lib/ios/RNNTransition.h
  26. 8
    0
      lib/ios/RNNTransition.m
  27. 7
    2
      lib/ios/RNNTransitionStateHolder.h
  28. 19
    1
      lib/ios/RNNTransitionStateHolder.m
  29. 12
    0
      lib/ios/RNNTransitionsOptions.h
  30. 20
    0
      lib/ios/RNNTransitionsOptions.m
  31. 34
    2
      lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj
  32. 4
    4
      lib/src/commands/Commands.ts
  33. 2
    2
      lib/src/commands/LayoutTreeCrawler.ts
  34. 26
    15
      lib/src/commands/OptionsProcessor.test.ts
  35. 11
    2
      lib/src/commands/OptionsProcessor.ts
  36. 1
    0
      lib/src/components/Store.mock.ts

+ 0
- 4
lib/ios/RNNAnimationOptions.m 파일 보기

@@ -7,10 +7,6 @@
7 7
 @implementation RNNAnimationOptions
8 8
 
9 9
 - (instancetype)initWithDict:(NSDictionary *)dict {
10
-	if (!dict[@"animations"]) {
11
-		return nil;
12
-	}
13
-	
14 10
 	return [super initWithDict:dict];
15 11
 }
16 12
 

+ 2
- 6
lib/ios/RNNAnimator.m 파일 보기

@@ -12,7 +12,7 @@
12 12
 
13 13
 -(instancetype)initWithTransitionOptions:(RNNAnimationOptions *)transitionOptions {
14 14
 	self = [super init];
15
-	if (transitionOptions) {
15
+	if (transitionOptions.animations) {
16 16
 		[self setupTransition:transitionOptions];
17 17
 	} else {
18 18
 		return nil;
@@ -47,11 +47,7 @@
47 47
 
48 48
 -(void)animateTransitions:(NSArray*)transitions {
49 49
 	for (RNNTransition* transition in transitions ) {
50
-		[UIView animateWithDuration:transition.options.duration delay:transition.options.startDelay usingSpringWithDamping:transition.options.springDamping initialSpringVelocity:transition.options.springVelocity options:UIViewAnimationOptionCurveEaseOut  animations:^{
51
-			[transition setAnimatedViewFinalProperties];
52
-		} completion:^(BOOL finished) {
53
-
54
-		}];
50
+		[transition animate];
55 51
 	}
56 52
 }
57 53
 

+ 3
- 8
lib/ios/RNNCommandsHandler.m 파일 보기

@@ -56,8 +56,7 @@
56 56
 
57 57
 -(void) setDefaultOptions:(NSDictionary*)optionsDict completion:(RNNTransitionCompletionBlock)completion {
58 58
 	[self assertReady];
59
-	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:optionsDict];
60
-	[_controllerFactory setDefaultOptions:options];
59
+	[_controllerFactory setDefaultOptionsDict:optionsDict];
61 60
 }
62 61
 
63 62
 -(void) push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion {
@@ -79,12 +78,8 @@
79 78
 	NSDictionary* animationData = options[@"customTransition"];
80 79
 	RNNAnimationOptions* transitionOptions = [[RNNAnimationOptions alloc] initWithDict:animationData];
81 80
 	
82
-	if (transitionOptions){
83
-		if (transitionOptions.animations) {
84
-			[_navigationStackManager pop:componentId withTransitionOptions:transitionOptions];
85
-		} else {
86
-			[[NSException exceptionWithName:NSInvalidArgumentException reason:@"unsupported transitionAnimation" userInfo:nil] raise];
87
-		}
81
+	if (transitionOptions.animations){
82
+		[_navigationStackManager pop:componentId withTransitionOptions:transitionOptions];
88 83
 	} else {
89 84
 		[_navigationStackManager pop:componentId withTransitionOptions:nil];
90 85
 	}

+ 1
- 1
lib/ios/RNNControllerFactory.h 파일 보기

@@ -17,7 +17,7 @@
17 17
 
18 18
 - (UIViewController<RNNRootViewProtocol> *)createOverlay:(NSDictionary*)layout;
19 19
 
20
-@property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
20
+@property (nonatomic, strong) NSDictionary* defaultOptionsDict;
21 21
 @property (nonatomic, strong) RNNEventEmitter *eventEmitter;
22 22
 
23 23
 @end

+ 3
- 2
lib/ios/RNNControllerFactory.m 파일 보기

@@ -90,8 +90,9 @@
90 90
 
91 91
 - (UIViewController<RNNRootViewProtocol> *)createComponent:(RNNLayoutNode*)node nativeComponent:(BOOL)nativeComponent {
92 92
 	NSString* name = node.data[@"name"];
93
-	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];
94
-	options.defaultOptions = _defaultOptions;
93
+	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:_defaultOptionsDict];
94
+	[options mergeWith:node.data[@"options"]];
95
+
95 96
 	NSString* componentId = node.nodeId;
96 97
 	RNNRootViewController* component = [[RNNRootViewController alloc] initWithName:name withOptions:options withComponentId:componentId rootViewCreator:_creator eventEmitter:_eventEmitter isExternalComponent:nativeComponent];
97 98
 	if (!component.isCustomViewController) {

+ 11
- 0
lib/ios/RNNModalAnimation.h 파일 보기

@@ -0,0 +1,11 @@
1
+#import <Foundation/Foundation.h>
2
+#import "RNNScreenTransition.h"
3
+
4
+@interface RNNModalAnimation : NSObject <UIViewControllerAnimatedTransitioning>
5
+
6
+@property (nonatomic, strong) RNNScreenTransition* screenTransition;
7
+@property (nonatomic) BOOL isDismiss;
8
+
9
+- (instancetype)initWithScreenTransition:(RNNScreenTransition *)screenTransition isDismiss:(BOOL)isDismiss;
10
+
11
+@end

+ 42
- 0
lib/ios/RNNModalAnimation.m 파일 보기

@@ -0,0 +1,42 @@
1
+#import "RNNModalAnimation.h"
2
+
3
+@implementation RNNModalAnimation
4
+
5
+- (instancetype)initWithScreenTransition:(RNNScreenTransition *)screenTransition isDismiss:(BOOL)isDismiss {
6
+	self = [super init];
7
+	self.screenTransition = screenTransition;
8
+	self.isDismiss = isDismiss;
9
+	
10
+	return self;
11
+}
12
+
13
+- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
14
+	return self.screenTransition.content.duration;
15
+}
16
+
17
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
18
+	UIViewController* toViewController = [transitionContext viewControllerForKey:self.isDismiss ? UITransitionContextFromViewControllerKey : UITransitionContextToViewControllerKey];
19
+	UIViewController* fromViewController = [transitionContext viewControllerForKey:self.isDismiss ? UITransitionContextToViewControllerKey : UITransitionContextFromViewControllerKey];
20
+	
21
+	if (self.isDismiss) {
22
+		[[transitionContext containerView] addSubview:fromViewController.view];
23
+		[[transitionContext containerView] addSubview:toViewController.view];
24
+	} else {
25
+		[[transitionContext containerView] addSubview:toViewController.view];
26
+	}
27
+	
28
+	[_screenTransition.content setupInitialTransitionForView:toViewController.view];
29
+	[_screenTransition.topBar setupInitialTransitionForView:toViewController.navigationController.navigationBar];
30
+	
31
+	
32
+	[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
33
+		[_screenTransition.content completeTransitionForView:toViewController.view];
34
+		[_screenTransition.topBar completeTransitionForView:toViewController.navigationController.navigationBar];
35
+	} completion:^(BOOL finished) {
36
+		[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
37
+	}];
38
+}
39
+
40
+
41
+@end
42
+

+ 13
- 1
lib/ios/RNNModalManager.m 파일 보기

@@ -21,7 +21,10 @@
21 21
 
22 22
 -(void)showModalAfterLoad:(NSDictionary*)notif {
23 23
 	[[NSNotificationCenter defaultCenter] removeObserver:self name:@"RCTContentDidAppearNotification" object:nil];
24
-	UIViewController *topVC = [self topPresentedVC];
24
+	RNNRootViewController *topVC = (RNNRootViewController*)[self topPresentedVC];
25
+	if (topVC.options.animations.showModal) {
26
+		self.toVC.transitioningDelegate = topVC;
27
+	}
25 28
 	[topVC presentViewController:self.toVC animated:self.toVC.isAnimated completion:^{
26 29
 		if (_completionBlock) {
27 30
 			_completionBlock();
@@ -61,6 +64,10 @@
61 64
 	
62 65
 	UIViewController* topPresentedVC = [self topPresentedVC];
63 66
 	
67
+	if (modalToDismiss.options.animations.showModal) {
68
+		modalToDismiss.transitioningDelegate = modalToDismiss;
69
+	}
70
+	
64 71
 	if (modalToDismiss == topPresentedVC || [[topPresentedVC childViewControllers] containsObject:modalToDismiss]) {
65 72
 		[modalToDismiss dismissViewControllerAnimated:modalToDismiss.isAnimated completion:^{
66 73
 			[[_store pendingModalIdsToDismiss] removeObject:componentId];
@@ -77,5 +84,10 @@
77 84
 	return root;
78 85
 }
79 86
 
87
+-(UIViewController*)topPresentedVCLeaf {
88
+	id root = [self topPresentedVC];
89
+	return [root topViewController] ? [root topViewController] : root;
90
+}
91
+
80 92
 
81 93
 @end

+ 13
- 0
lib/ios/RNNNavigationController.m 파일 보기

@@ -1,5 +1,6 @@
1 1
 
2 2
 #import "RNNNavigationController.h"
3
+#import "RNNModalAnimation.h"
3 4
 
4 5
 @implementation RNNNavigationController
5 6
 
@@ -24,4 +25,16 @@
24 25
 	return ((UIViewController<RNNRootViewProtocol>*)self.topViewController).componentId;
25 26
 }
26 27
 
28
+- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
29
+	return [[RNNModalAnimation alloc] initWithScreenTransition:self.options.animations.showModal isDismiss:NO];
30
+}
31
+
32
+- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
33
+	return [[RNNModalAnimation alloc] initWithScreenTransition:self.options.animations.dismissModal isDismiss:YES];
34
+}
35
+
36
+- (RNNNavigationOptions *)options {
37
+	return ((UIViewController<RNNRootViewProtocol>*)self.topViewController).options;
38
+}
39
+
27 40
 @end

+ 2
- 1
lib/ios/RNNNavigationOptions.h 파일 보기

@@ -7,6 +7,7 @@
7 7
 #import "RNNTopTabsOptions.h"
8 8
 #import "RNNOverlayOptions.h"
9 9
 #import "RNNAnimationOptions.h"
10
+#import "RNNTransitionsOptions.h"
10 11
 
11 12
 extern const NSInteger BLUR_STATUS_TAG;
12 13
 extern const NSInteger BLUR_TOPBAR_TAG;
@@ -22,8 +23,8 @@ extern const NSInteger TOP_BAR_TRANSPARENT_TAG;
22 23
 @property (nonatomic, strong) RNNSideMenuOptions* sideMenu;
23 24
 @property (nonatomic, strong) RNNOverlayOptions* overlay;
24 25
 @property (nonatomic, strong) RNNAnimationOptions* customTransition;
26
+@property (nonatomic, strong) RNNTransitionsOptions* animations;
25 27
 
26
-@property (nonatomic, strong) RNNNavigationOptions* defaultOptions;
27 28
 
28 29
 @property (nonatomic, strong) NSNumber* animated;
29 30
 @property (nonatomic, strong) NSNumber* statusBarHidden;

+ 2
- 14
lib/ios/RNNNavigationOptions.m 파일 보기

@@ -33,6 +33,7 @@ const NSInteger TOP_BAR_TRANSPARENT_TAG = 78264803;
33 33
 	self.overlay = [[RNNOverlayOptions alloc] initWithDict:[options objectForKey:@"overlay"]];
34 34
 	self.animated = [options objectForKey:@"animated"];
35 35
 	self.customTransition = [[RNNAnimationOptions alloc] initWithDict:[options objectForKey:@"customTransition"]];
36
+	self.animations = [[RNNTransitionsOptions alloc] initWithDict:[options objectForKey:@"animations"]];
36 37
 	
37 38
 	return self;
38 39
 }
@@ -50,21 +51,8 @@ const NSInteger TOP_BAR_TRANSPARENT_TAG = 78264803;
50 51
 	}
51 52
 }
52 53
 
53
--(void)mergeIfEmptyWith:(NSDictionary *)otherOptions {
54
-	for (id key in otherOptions) {
55
-		if ([self hasProperty:key]) {
56
-			if ([[self valueForKey:key] isKindOfClass:[RNNOptions class]]) {
57
-				RNNOptions* options = [self valueForKey:key];
58
-				[options mergeIfEmptyWith:[otherOptions objectForKey:key]];
59
-			} else if (![self valueForKey:key]) {
60
-				[self setValue:[otherOptions objectForKey:key] forKey:key];
61
-			}
62
-		}
63
-	}
64
-}
65
-
66 54
 -(void)applyOn:(UIViewController*)viewController {
67
-	[_defaultOptions applyOn:viewController];
55
+//	[_defaultOptions applyOn:viewController];
68 56
 	
69 57
 	[self.topBar applyOn:viewController];
70 58
 	[self.bottomTabs applyOn:viewController];

+ 1
- 1
lib/ios/RNNNavigationStackManager.h 파일 보기

@@ -5,7 +5,7 @@
5 5
 @interface RNNNavigationStackManager : NSObject
6 6
 
7 7
 @property (nonatomic, strong) UIViewController* fromVC;
8
-@property (nonatomic, strong) UIViewController<RNNRootViewProtocol>* toVC;
8
+@property (nonatomic, strong) RNNRootViewController* toVC;
9 9
 @property (nonatomic) int loadCount;
10 10
 -(instancetype)initWithStore:(RNNStore*)store;
11 11
 

+ 6
- 7
lib/ios/RNNNavigationStackManager.m 파일 보기

@@ -26,10 +26,11 @@ dispatch_queue_t RCTGetUIManagerQueue(void);
26 26
 }
27 27
 
28 28
 -(void)preparePush:(UIViewController<RNNRootViewProtocol> *)newTop onTopVC:(UIViewController*)vc completion:(RNNTransitionCompletionBlock)completion {
29
-	self.toVC = newTop;
29
+	self.toVC = (RNNRootViewController*)newTop;
30 30
 	self.fromVC = vc;
31 31
 	
32
-	if (self.toVC.isCustomTransitioned) {
32
+	
33
+	if (self.toVC.options.animations.push) {
33 34
 		vc.navigationController.delegate = newTop;
34 35
 	} else {
35 36
 		vc.navigationController.delegate = nil;
@@ -65,13 +66,11 @@ dispatch_queue_t RCTGetUIManagerQueue(void);
65 66
 }
66 67
 
67 68
 -(void)pop:(NSString *)componentId withTransitionOptions:(RNNAnimationOptions *)transitionOptions {
68
-	UIViewController<RNNRootViewProtocol>* vc = (UIViewController<RNNRootViewProtocol>*)[_store findComponentForId:componentId];
69
+	RNNRootViewController* vc = (RNNRootViewController*)[_store findComponentForId:componentId];
69 70
 	UINavigationController* nvc = [vc navigationController];
70 71
 	if ([nvc topViewController] == vc) {
71
-		if (transitionOptions) {
72
-			RNNRootViewController* RNNVC = (RNNRootViewController*)vc;
73
-			nvc.delegate = RNNVC;
74
-			RNNVC.animator = [[RNNAnimator alloc] initWithTransitionOptions:transitionOptions];
72
+		if (vc.options.animations.pop) {
73
+			nvc.delegate = vc;
75 74
 			[nvc popViewControllerAnimated:vc.isAnimated];
76 75
 		} else {
77 76
 			nvc.delegate = nil;

+ 7
- 2
lib/ios/RNNOptions.m 파일 보기

@@ -24,8 +24,13 @@
24 24
 
25 25
 -(void)mergeIfEmptyWith:(NSDictionary *)otherOptions {
26 26
 	for (id key in otherOptions) {
27
-		if ([self hasProperty:key] && ![self valueForKey:key]) {
28
-			[self setValue:[otherOptions objectForKey:key] forKey:key];
27
+		if ([self hasProperty:key]) {
28
+			if ([[self valueForKey:key] isKindOfClass:[RNNOptions class]]) {
29
+				RNNOptions* options = [self valueForKey:key];
30
+				[options mergeIfEmptyWith:[otherOptions objectForKey:key]];
31
+			} else if (![self valueForKey:key]) {
32
+				[self setValue:[otherOptions objectForKey:key] forKey:key];
33
+			}
29 34
 		}
30 35
 	}
31 36
 }

+ 9
- 0
lib/ios/RNNPushAnimation.h 파일 보기

@@ -0,0 +1,9 @@
1
+#import <Foundation/Foundation.h>
2
+#import <UIKit/UIKit.h>
3
+#import "RNNModalAnimation.h"
4
+
5
+@interface RNNPushAnimation : RNNModalAnimation <UIViewControllerAnimatedTransitioning>
6
+
7
+- (instancetype)initWithScreenTransition:(RNNScreenTransition *)screenTransition;
8
+
9
+@end

+ 34
- 0
lib/ios/RNNPushAnimation.m 파일 보기

@@ -0,0 +1,34 @@
1
+#import "RNNPushAnimation.h"
2
+
3
+@implementation RNNPushAnimation
4
+
5
+- (instancetype)initWithScreenTransition:(RNNScreenTransition *)screenTransition {
6
+	self = [super init];
7
+	self.screenTransition = screenTransition;
8
+	
9
+	return self;
10
+}
11
+
12
+- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
13
+	return 0.5;
14
+}
15
+
16
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
17
+	UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
18
+	
19
+	[[transitionContext containerView] addSubview:toViewController.view];
20
+	
21
+	[self.screenTransition.content setupInitialTransitionForView:toViewController.view];
22
+	[self.screenTransition.topBar setupInitialTransitionForView:toViewController.navigationController.navigationBar];
23
+	
24
+	
25
+	[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
26
+		[self.screenTransition.content completeTransitionForView:toViewController.view];
27
+		[self.screenTransition.topBar completeTransitionForView:toViewController.navigationController.navigationBar];
28
+	} completion:^(BOOL finished) {
29
+		[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
30
+	}];
31
+}
32
+
33
+
34
+@end

+ 14
- 5
lib/ios/RNNRootViewController.m 파일 보기

@@ -3,6 +3,7 @@
3 3
 #import <React/RCTConvert.h>
4 4
 #import "RNNAnimator.h"
5 5
 #import "RNNCustomTitleView.h"
6
+#import "RNNPushAnimation.h"
6 7
 
7 8
 @interface RNNRootViewController()
8 9
 @property (nonatomic, strong) NSString* componentName;
@@ -37,7 +38,6 @@
37 38
 											 selector:@selector(onJsReload)
38 39
 												 name:RCTJavaScriptWillStartLoadingNotification
39 40
 											   object:nil];
40
-	self.navigationController.modalPresentationStyle = UIModalPresentationCustom;
41 41
 	self.navigationController.delegate = self;
42 42
 
43 43
 	return self;
@@ -91,7 +91,7 @@
91 91
 }
92 92
 
93 93
 -(BOOL)isCustomTransitioned {
94
-	return self.options.customTransition != nil;
94
+	return self.options.customTransition.animations != nil;
95 95
 }
96 96
 
97 97
 - (BOOL)isAnimated {
@@ -135,16 +135,25 @@
135 135
 											   fromViewController:(UIViewController*)fromVC
136 136
 												 toViewController:(UIViewController*)toVC {
137 137
 {
138
-	if (operation == UINavigationControllerOperationPush) {
139
-		return self.animator;
140
-	} else if (operation == UINavigationControllerOperationPop) {
138
+	if (self.animator) {
141 139
 		return self.animator;
140
+	} else if (operation == UINavigationControllerOperationPush && self.options.animations.push) {
141
+		return [[RNNPushAnimation alloc] initWithScreenTransition:self.options.animations.push];
142
+	} else if (operation == UINavigationControllerOperationPop && self.options.animations.pop) {
143
+		return [[RNNPushAnimation alloc] initWithScreenTransition:self.options.animations.pop];
142 144
 	} else {
143 145
 		return nil;
144 146
 	}
145 147
 }
146 148
 	return nil;
149
+}
150
+
151
+- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
152
+	return [[RNNModalAnimation alloc] initWithScreenTransition:self.options.animations.showModal isDismiss:NO];
153
+}
147 154
 
155
+- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
156
+	return [[RNNModalAnimation alloc] initWithScreenTransition:self.options.animations.dismissModal isDismiss:YES];
148 157
 }
149 158
 
150 159
 -(void)applyTabBarItem {

+ 2
- 2
lib/ios/RNNRootViewProtocol.h 파일 보기

@@ -1,6 +1,6 @@
1 1
 #import "RNNNavigationOptions.h"
2 2
 
3
-@protocol RNNRootViewProtocol <NSObject, UINavigationControllerDelegate>
3
+@protocol RNNRootViewProtocol <NSObject, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate>
4 4
 
5 5
 @optional
6 6
 - (void)mergeOptions:(NSDictionary*)options;
@@ -9,7 +9,7 @@
9 9
 @required
10 10
 - (BOOL)isCustomTransitioned;
11 11
 - (BOOL)isAnimated;
12
-
12
+- (RNNNavigationOptions*)options;
13 13
 - (NSString *)componentId;
14 14
 
15 15
 @end

+ 10
- 0
lib/ios/RNNScreenTransition.h 파일 보기

@@ -0,0 +1,10 @@
1
+#import "RNNOptions.h"
2
+#import "RNNTransitionStateHolder.h"
3
+
4
+@interface RNNScreenTransition : RNNOptions
5
+
6
+@property (nonatomic, strong) RNNTransitionStateHolder* topBar;
7
+@property (nonatomic, strong) RNNTransitionStateHolder* content;
8
+@property (nonatomic, strong) RNNTransitionStateHolder* bottomTabs;
9
+
10
+@end

+ 14
- 0
lib/ios/RNNScreenTransition.m 파일 보기

@@ -0,0 +1,14 @@
1
+#import "RNNScreenTransition.h"
2
+
3
+@implementation RNNScreenTransition
4
+
5
+- (instancetype)initWithDict:(NSDictionary *)dict {
6
+	self = [super init];
7
+	self.topBar = [[RNNTransitionStateHolder alloc] initWithTransition:dict[@"topBar"]];
8
+	self.content = [[RNNTransitionStateHolder alloc] initWithTransition:dict[@"content"]];
9
+	self.bottomTabs = [[RNNTransitionStateHolder alloc] initWithTransition:dict[@"bottomTabs"]];
10
+	
11
+	return self;
12
+}
13
+
14
+@end

+ 4
- 0
lib/ios/RNNSideMenuChildVC.m 파일 보기

@@ -41,6 +41,10 @@
41 41
 	return YES;
42 42
 }
43 43
 
44
+- (RNNOptions *)options {
45
+	return nil;
46
+}
47
+
44 48
 - (NSString *)componentId {
45 49
 	return _child.componentId;
46 50
 }

+ 4
- 0
lib/ios/RNNSideMenuController.m 파일 보기

@@ -80,6 +80,10 @@
80 80
 	return YES;
81 81
 }
82 82
 
83
+- (RNNOptions *)options {
84
+	return nil;
85
+}
86
+
83 87
 - (NSString *)componentId {
84 88
 	return _center.componentId;
85 89
 }

+ 4
- 0
lib/ios/RNNTabBarController.m 파일 보기

@@ -41,6 +41,10 @@
41 41
 	return YES;
42 42
 }
43 43
 
44
+- (RNNOptions *)options {
45
+	return nil;
46
+}
47
+
44 48
 - (void)mergeOptions:(NSDictionary *)options {
45 49
 	[((UIViewController<RNNRootViewProtocol>*)self.selectedViewController) mergeOptions:options];
46 50
 }

+ 4
- 0
lib/ios/RNNTopTabsViewController.m 파일 보기

@@ -80,6 +80,10 @@
80 80
 	return YES;
81 81
 }
82 82
 
83
+- (RNNOptions *)options {
84
+	return nil;
85
+}
86
+
83 87
 - (NSString *)componentId {
84 88
 	return _currentViewController.componentId;
85 89
 }

+ 2
- 0
lib/ios/RNNTransition.h 파일 보기

@@ -9,6 +9,8 @@
9 9
 
10 10
 - (instancetype)initFromVC:(UIViewController*)fromVC toVC:(UIViewController*)toVC transitionOptions:(RNNTransitionStateHolder*)transitionOptions isBackButton:(BOOL)isBackButton;
11 11
 
12
+- (void)animate;
13
+
12 14
 - (void)setAnimatedViewFinalProperties;
13 15
 
14 16
 - (void)transitionCompleted;

+ 8
- 0
lib/ios/RNNTransition.m 파일 보기

@@ -43,6 +43,14 @@
43 43
 	return self;
44 44
 }
45 45
 
46
+- (void)animate {
47
+	[UIView animateWithDuration:self.options.duration delay:self.options.startDelay usingSpringWithDamping:self.options.springDamping initialSpringVelocity:self.options.springVelocity options:UIViewAnimationOptionCurveEaseOut  animations:^{
48
+		[self setAnimatedViewFinalProperties];
49
+	} completion:^(BOOL finished) {
50
+		
51
+	}];
52
+}
53
+
46 54
 - (void)setAnimatedViewFinalProperties {
47 55
 	CGFloat alpha = _isBackButton ? self.options.startAlpha : self.options.endAlpha;
48 56
 	self.animatedView.alpha = alpha;

+ 7
- 2
lib/ios/RNNTransitionStateHolder.h 파일 보기

@@ -1,6 +1,8 @@
1 1
 #import <Foundation/Foundation.h>
2
+#import <UIKit/UIKit.h>
3
+#import "RNNOptions.h"
2 4
 
3
-@interface RNNTransitionStateHolder : NSObject
5
+@interface RNNTransitionStateHolder : RNNOptions
4 6
 
5 7
 @property (nonatomic) double startAlpha;
6 8
 @property (nonatomic) double endAlpha;
@@ -9,7 +11,6 @@
9 11
 @property (nonatomic) double springVelocity;
10 12
 @property (nonatomic) double springDamping;
11 13
 @property (nonatomic) double startDelay;
12
-@property (nonatomic, strong) NSString* fromElementType;
13 14
 @property (nonatomic, strong) NSString* fromId;
14 15
 @property (nonatomic, strong) NSString* toId;
15 16
 @property (nonatomic) BOOL isSharedElementTransition;
@@ -20,4 +21,8 @@
20 21
 
21 22
 - (instancetype)initWithTransition:(NSDictionary*)transition;
22 23
 
24
+- (void)setupInitialTransitionForView:(UIView *)view;
25
+
26
+- (void)completeTransitionForView:(UIView*)view;
27
+
23 28
 @end

+ 19
- 1
lib/ios/RNNTransitionStateHolder.m 파일 보기

@@ -1,10 +1,16 @@
1 1
 #import "RNNTransitionStateHolder.h"
2 2
 #import "RNNUtils.h"
3 3
 
4
+@interface RNNTransitionStateHolder() {
5
+	CGRect _initialFrame;
6
+}
7
+
8
+@end
4 9
 @implementation RNNTransitionStateHolder
5 10
 
6 11
 -(instancetype)initWithTransition:(NSDictionary *)transition {
7 12
 	self = [super init];
13
+	
8 14
 	self.springDamping = [RNNUtils getDoubleOrKey:transition withKey:@"springDamping" withDefault:0.85];
9 15
 	self.springVelocity = [RNNUtils getDoubleOrKey:transition withKey:@"springVelocity" withDefault:0.8];
10 16
 	self.startDelay = [RNNUtils getDoubleOrKey:transition withKey:@"startDelay" withDefault:0];
@@ -18,9 +24,21 @@
18 24
 	self.endY = [RNNUtils getDoubleOrKey:transition[@"y"] withKey:@"to" withDefault:0];
19 25
 	self.fromId = [transition objectForKey:@"fromId"];
20 26
 	self.toId = [transition objectForKey:@"toId"];
21
-	self.fromElementType = nil;
22 27
 	self.isSharedElementTransition = [[transition objectForKey:@"type"] isEqualToString:@"sharedElement"];
28
+	
23 29
 	return self;
24 30
 }
25 31
 
32
+- (void)setupInitialTransitionForView:(UIView*)view {
33
+	_initialFrame = view.frame;
34
+	view.alpha = self.startAlpha;
35
+	view.frame = CGRectMake(_initialFrame.origin.x + self.startX, _initialFrame.origin.y + self.startY, view.frame.size.width, view.frame.size.height);
36
+}
37
+
38
+- (void)completeTransitionForView:(UIView*)view {
39
+	view.alpha = self.endAlpha;
40
+	view.frame = CGRectMake(_initialFrame.origin.x + self.endX, _initialFrame.origin.y + self.endY, view.frame.size.width, view.frame.size.height);
41
+	[view layoutSubviews];
42
+}
43
+
26 44
 @end

+ 12
- 0
lib/ios/RNNTransitionsOptions.h 파일 보기

@@ -0,0 +1,12 @@
1
+#import "RNNOptions.h"
2
+#import "RNNTransitionStateHolder.h"
3
+#import "RNNScreenTransition.h"
4
+
5
+@interface RNNTransitionsOptions : RNNOptions
6
+
7
+@property (nonatomic, strong) RNNScreenTransition* push;
8
+@property (nonatomic, strong) RNNScreenTransition* pop;
9
+@property (nonatomic, strong) RNNScreenTransition* showModal;
10
+@property (nonatomic, strong) RNNScreenTransition* dismissModal;
11
+
12
+@end

+ 20
- 0
lib/ios/RNNTransitionsOptions.m 파일 보기

@@ -0,0 +1,20 @@
1
+#import "RNNTransitionsOptions.h"
2
+
3
+@implementation RNNTransitionsOptions
4
+
5
+- (instancetype)initWithDict:(NSDictionary *)dict {
6
+	self = [super init];
7
+
8
+	[self mergeWith:dict];
9
+	
10
+	return self;
11
+}
12
+
13
+- (void)mergeWith:(NSDictionary *)otherOptions {
14
+	self.push = otherOptions[@"push"] ? [[RNNScreenTransition alloc] initWithDict:otherOptions[@"push"]] : _push;
15
+	self.pop = otherOptions[@"pop"] ? [[RNNScreenTransition alloc] initWithDict:otherOptions[@"pop"]] : _pop;
16
+	self.showModal = otherOptions[@"showModal"] ? [[RNNScreenTransition alloc] initWithDict:otherOptions[@"showModal"]] : _showModal;
17
+	self.dismissModal = otherOptions[@"dismissModal"] ? [[RNNScreenTransition alloc] initWithDict:otherOptions[@"dismissModal"]] : _dismissModal;
18
+}
19
+
20
+@end

+ 34
- 2
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj 파일 보기

@@ -67,6 +67,12 @@
67 67
 		5032774F2015E86D00ECD75D /* RNNNavigationEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 5032774D2015E86D00ECD75D /* RNNNavigationEvent.m */; };
68 68
 		503277602016302900ECD75D /* RNNComponentLifecycleEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 5032775E2016302900ECD75D /* RNNComponentLifecycleEvent.h */; };
69 69
 		503277612016302900ECD75D /* RNNComponentLifecycleEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 5032775F2016302900ECD75D /* RNNComponentLifecycleEvent.m */; };
70
+		50415CBA20553B8E00BB682E /* RNNScreenTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 50415CB820553B8E00BB682E /* RNNScreenTransition.h */; };
71
+		50415CBB20553B8E00BB682E /* RNNScreenTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 50415CB920553B8E00BB682E /* RNNScreenTransition.m */; };
72
+		50451D052042DAEB00695F00 /* RNNPushAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 50451D032042DAEB00695F00 /* RNNPushAnimation.h */; };
73
+		50451D062042DAEB00695F00 /* RNNPushAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 50451D042042DAEB00695F00 /* RNNPushAnimation.m */; };
74
+		50451D092042E20600695F00 /* RNNTransitionsOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50451D072042E20600695F00 /* RNNTransitionsOptions.h */; };
75
+		50451D0A2042E20600695F00 /* RNNTransitionsOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50451D082042E20600695F00 /* RNNTransitionsOptions.m */; };
70 76
 		50451D0D2042F70900695F00 /* RNNTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 50451D0B2042F70900695F00 /* RNNTransition.h */; };
71 77
 		50451D0E2042F70900695F00 /* RNNTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 50451D0C2042F70900695F00 /* RNNTransition.m */; };
72 78
 		504AFE641FFE53070076E904 /* RNNOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 504AFE621FFE53070076E904 /* RNNOptions.h */; };
@@ -75,6 +81,8 @@
75 81
 		504AFE751FFFF0540076E904 /* RNNTopTabsOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */; };
76 82
 		504AFE761FFFF1E00076E904 /* RNNNavigationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = E83BAD691F27362500A9F3DD /* RNNNavigationOptions.h */; };
77 83
 		504AFE771FFFF1E20076E904 /* RNNTopBarOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = A7626BFE1FC2FB6700492FB8 /* RNNTopBarOptions.h */; };
84
+		50762D08205E96C200E3D18A /* RNNModalAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 50762D06205E96C200E3D18A /* RNNModalAnimation.h */; };
85
+		50762D09205E96C200E3D18A /* RNNModalAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 50762D07205E96C200E3D18A /* RNNModalAnimation.m */; };
78 86
 		507E7D57201DDD3000444E6C /* RNNAnimationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 507E7D55201DDD3000444E6C /* RNNAnimationOptions.h */; };
79 87
 		507E7D58201DDD3000444E6C /* RNNAnimationOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 507E7D56201DDD3000444E6C /* RNNAnimationOptions.m */; };
80 88
 		507F43C51FF4F17C00D9425B /* RNNTopTabsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 507F43C31FF4F17C00D9425B /* RNNTopTabsViewController.h */; };
@@ -248,12 +256,20 @@
248 256
 		5032774D2015E86D00ECD75D /* RNNNavigationEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNNavigationEvent.m; sourceTree = "<group>"; };
249 257
 		5032775E2016302900ECD75D /* RNNComponentLifecycleEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNComponentLifecycleEvent.h; sourceTree = "<group>"; };
250 258
 		5032775F2016302900ECD75D /* RNNComponentLifecycleEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNComponentLifecycleEvent.m; sourceTree = "<group>"; };
259
+		50415CB820553B8E00BB682E /* RNNScreenTransition.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNScreenTransition.h; sourceTree = "<group>"; };
260
+		50415CB920553B8E00BB682E /* RNNScreenTransition.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNScreenTransition.m; sourceTree = "<group>"; };
261
+		50451D032042DAEB00695F00 /* RNNPushAnimation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNPushAnimation.h; sourceTree = "<group>"; };
262
+		50451D042042DAEB00695F00 /* RNNPushAnimation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNPushAnimation.m; sourceTree = "<group>"; };
263
+		50451D072042E20600695F00 /* RNNTransitionsOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTransitionsOptions.h; sourceTree = "<group>"; };
264
+		50451D082042E20600695F00 /* RNNTransitionsOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTransitionsOptions.m; sourceTree = "<group>"; };
251 265
 		50451D0B2042F70900695F00 /* RNNTransition.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTransition.h; sourceTree = "<group>"; };
252 266
 		50451D0C2042F70900695F00 /* RNNTransition.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTransition.m; sourceTree = "<group>"; };
253 267
 		504AFE621FFE53070076E904 /* RNNOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNOptions.h; sourceTree = "<group>"; };
254 268
 		504AFE631FFE53070076E904 /* RNNOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNOptions.m; sourceTree = "<group>"; };
255 269
 		504AFE721FFFF0540076E904 /* RNNTopTabsOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTopTabsOptions.h; sourceTree = "<group>"; };
256 270
 		504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTopTabsOptions.m; sourceTree = "<group>"; };
271
+		50762D06205E96C200E3D18A /* RNNModalAnimation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNModalAnimation.h; sourceTree = "<group>"; };
272
+		50762D07205E96C200E3D18A /* RNNModalAnimation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNModalAnimation.m; sourceTree = "<group>"; };
257 273
 		507E7D55201DDD3000444E6C /* RNNAnimationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNAnimationOptions.h; sourceTree = "<group>"; };
258 274
 		507E7D56201DDD3000444E6C /* RNNAnimationOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNAnimationOptions.m; sourceTree = "<group>"; };
259 275
 		507F43C31FF4F17C00D9425B /* RNNTopTabsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTopTabsViewController.h; sourceTree = "<group>"; };
@@ -483,6 +499,12 @@
483 499
 				50A00C36200F84D6000F01A6 /* RNNOverlayOptions.m */,
484 500
 				507E7D55201DDD3000444E6C /* RNNAnimationOptions.h */,
485 501
 				507E7D56201DDD3000444E6C /* RNNAnimationOptions.m */,
502
+				E8E5182C1F83A48B000467AC /* RNNTransitionStateHolder.h */,
503
+				E8E5182D1F83A48B000467AC /* RNNTransitionStateHolder.m */,
504
+				50451D072042E20600695F00 /* RNNTransitionsOptions.h */,
505
+				50451D082042E20600695F00 /* RNNTransitionsOptions.m */,
506
+				50415CB820553B8E00BB682E /* RNNScreenTransition.h */,
507
+				50415CB920553B8E00BB682E /* RNNScreenTransition.m */,
486 508
 			);
487 509
 			name = Options;
488 510
 			sourceTree = "<group>";
@@ -652,14 +674,16 @@
652 674
 				E8A5CD511F464F0400E89D0D /* RNNAnimator.m */,
653 675
 				E8AEDB481F5C0BAF000F5A6A /* RNNInteractivePopAnimator.h */,
654 676
 				E8AEDB491F5C0BAF000F5A6A /* RNNInteractivePopAnimator.m */,
655
-				E8E5182C1F83A48B000467AC /* RNNTransitionStateHolder.h */,
656
-				E8E5182D1F83A48B000467AC /* RNNTransitionStateHolder.m */,
657 677
 				50451D0B2042F70900695F00 /* RNNTransition.h */,
658 678
 				50451D0C2042F70900695F00 /* RNNTransition.m */,
659 679
 				E8E518341F83B94A000467AC /* RNNViewLocation.h */,
660 680
 				E8E518351F83B94A000467AC /* RNNViewLocation.m */,
661 681
 				E8DA243E1F97459B00CD552B /* RNNElementFinder.h */,
662 682
 				E8DA243F1F97459B00CD552B /* RNNElementFinder.m */,
683
+				50451D032042DAEB00695F00 /* RNNPushAnimation.h */,
684
+				50451D042042DAEB00695F00 /* RNNPushAnimation.m */,
685
+				50762D06205E96C200E3D18A /* RNNModalAnimation.h */,
686
+				50762D07205E96C200E3D18A /* RNNModalAnimation.m */,
663 687
 			);
664 688
 			name = Animations;
665 689
 			sourceTree = "<group>";
@@ -707,9 +731,11 @@
707 731
 				50CB3B691FDE911400AA153B /* RNNSideMenuOptions.h in Headers */,
708 732
 				263905BD1E4C6F440023D7D3 /* RCCDrawerProtocol.h in Headers */,
709 733
 				5016E8EF20209690009D4F7C /* RNNCustomTitleView.h in Headers */,
734
+				50415CBA20553B8E00BB682E /* RNNScreenTransition.h in Headers */,
710 735
 				263905C21E4C6F440023D7D3 /* SidebarAnimation.h in Headers */,
711 736
 				E8E518361F83B94A000467AC /* RNNViewLocation.h in Headers */,
712 737
 				263905B51E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.h in Headers */,
738
+				50451D052042DAEB00695F00 /* RNNPushAnimation.h in Headers */,
713 739
 				507F43C51FF4F17C00D9425B /* RNNTopTabsViewController.h in Headers */,
714 740
 				263905C61E4C6F440023D7D3 /* SidebarFeedlyAnimation.h in Headers */,
715 741
 				7B1126A31E2D2B6C00F9B03B /* RNNSplashScreen.h in Headers */,
@@ -734,11 +760,13 @@
734 760
 				E8E518321F83B3E0000467AC /* RNNUtils.h in Headers */,
735 761
 				507F44201FFA8A8800D9425B /* RNNRootViewProtocol.h in Headers */,
736 762
 				263905CA1E4C6F440023D7D3 /* SidebarLuvocracyAnimation.h in Headers */,
763
+				50762D08205E96C200E3D18A /* RNNModalAnimation.h in Headers */,
737 764
 				390AD477200F499D00A8250D /* RNNSwizzles.h in Headers */,
738 765
 				263905B11E4C6F440023D7D3 /* MMDrawerController.h in Headers */,
739 766
 				504AFE641FFE53070076E904 /* RNNOptions.h in Headers */,
740 767
 				263905B91E4C6F440023D7D3 /* RCCDrawerController.h in Headers */,
741 768
 				263905B31E4C6F440023D7D3 /* MMDrawerVisualState.h in Headers */,
769
+				50451D092042E20600695F00 /* RNNTransitionsOptions.h in Headers */,
742 770
 				E8A5CD621F49114F00E89D0D /* RNNElement.h in Headers */,
743 771
 				504AFE741FFFF0540076E904 /* RNNTopTabsOptions.h in Headers */,
744 772
 				E8E5182E1F83A48B000467AC /* RNNTransitionStateHolder.h in Headers */,
@@ -867,6 +895,7 @@
867 895
 				263905C51E4C6F440023D7D3 /* SidebarFacebookAnimation.m in Sources */,
868 896
 				50451D0E2042F70900695F00 /* RNNTransition.m in Sources */,
869 897
 				7BEF0D191E437684003E96B0 /* RNNRootViewController.m in Sources */,
898
+				50415CBB20553B8E00BB682E /* RNNScreenTransition.m in Sources */,
870 899
 				263905C31E4C6F440023D7D3 /* SidebarAnimation.m in Sources */,
871 900
 				E8A5CD531F464F0400E89D0D /* RNNAnimator.m in Sources */,
872 901
 				50CB3B6A1FDE911400AA153B /* RNNSideMenuOptions.m in Sources */,
@@ -908,8 +937,10 @@
908 937
 				263905CF1E4C6F440023D7D3 /* TheSidebarController.m in Sources */,
909 938
 				E8A430121F9CB87B00B61A20 /* RNNAnimatedView.m in Sources */,
910 939
 				507F43F51FF4FCFE00D9425B /* HMSegmentedControl.m in Sources */,
940
+				50451D0A2042E20600695F00 /* RNNTransitionsOptions.m in Sources */,
911 941
 				507F43C61FF4F17C00D9425B /* RNNTopTabsViewController.m in Sources */,
912 942
 				50A00C38200F84D6000F01A6 /* RNNOverlayOptions.m in Sources */,
943
+				50762D09205E96C200E3D18A /* RNNModalAnimation.m in Sources */,
913 944
 				50EB93421FE14A3E00BD8EEE /* RNNBottomTabOptions.m in Sources */,
914 945
 				E8367B811F7A8A4700675C05 /* VICMAImageView.m in Sources */,
915 946
 				A7626C011FC5796200492FB8 /* RNNBottomTabsOptions.m in Sources */,
@@ -923,6 +954,7 @@
923 954
 				E8E5182F1F83A48B000467AC /* RNNTransitionStateHolder.m in Sources */,
924 955
 				263905B61E4C6F440023D7D3 /* MMExampleDrawerVisualStateManager.m in Sources */,
925 956
 				E8E518331F83B3E0000467AC /* RNNUtils.m in Sources */,
957
+				50451D062042DAEB00695F00 /* RNNPushAnimation.m in Sources */,
926 958
 				50F5DFC61F407AA0001A00BC /* RNNNavigationController.m in Sources */,
927 959
 				21B85E5D1F44480200B314B5 /* RNNNavigationButtons.m in Sources */,
928 960
 				E8E518371F83B94A000467AC /* RNNViewLocation.m in Sources */,

+ 4
- 4
lib/src/commands/Commands.ts 파일 보기

@@ -21,13 +21,13 @@ export class Commands {
21 21
 
22 22
   setDefaultOptions(options) {
23 23
     const input = _.cloneDeep(options);
24
-    OptionsProcessor.processOptions(input);
24
+    OptionsProcessor.processOptions(input, this.layoutTreeCrawler.store);
25 25
     this.nativeCommandsSender.setDefaultOptions(input);
26 26
   }
27 27
 
28 28
   setOptions(componentId, options) {
29 29
     const input = _.cloneDeep(options);
30
-    OptionsProcessor.processOptions(input);
30
+    OptionsProcessor.processOptions(input, this.layoutTreeCrawler.store);
31 31
     this.nativeCommandsSender.setOptions(componentId, input);
32 32
   }
33 33
 
@@ -48,7 +48,7 @@ export class Commands {
48 48
 
49 49
   push(onComponentId, componentData) {
50 50
     const input = _.cloneDeep(componentData);
51
-    OptionsProcessor.processOptions(input);
51
+    OptionsProcessor.processOptions(input, this.layoutTreeCrawler.store);
52 52
     const layout = this.layoutTreeParser.parse(input);
53 53
     this.layoutTreeCrawler.crawl(layout);
54 54
     return this.nativeCommandsSender.push(onComponentId, layout);
@@ -68,7 +68,7 @@ export class Commands {
68 68
 
69 69
   showOverlay(componentData) {
70 70
     const input = _.cloneDeep(componentData);
71
-    OptionsProcessor.processOptions(input);
71
+    OptionsProcessor.processOptions(input, this.layoutTreeCrawler.store);
72 72
 
73 73
     const layout = this.layoutTreeParser.parse(input);
74 74
     this.layoutTreeCrawler.crawl(layout);

+ 2
- 2
lib/src/commands/LayoutTreeCrawler.ts 파일 보기

@@ -17,7 +17,7 @@ export interface LayoutNode {
17 17
 export class LayoutTreeCrawler {
18 18
   constructor(
19 19
     private readonly uniqueIdProvider: any,
20
-    private readonly store: any) {
20
+    public readonly store: any) {
21 21
     this.crawl = this.crawl.bind(this);
22 22
   }
23 23
 
@@ -29,7 +29,7 @@ export class LayoutTreeCrawler {
29 29
     if (node.type === LayoutType.Component) {
30 30
       this._handleComponent(node);
31 31
     }
32
-    OptionsProcessor.processOptions(node.data.options);
32
+    OptionsProcessor.processOptions(node.data.options, this.store);
33 33
     _.forEach(node.children, this.crawl);
34 34
   }
35 35
 

+ 26
- 15
lib/src/commands/OptionsProcessor.test.ts 파일 보기

@@ -1,56 +1,58 @@
1 1
 import { OptionsProcessor } from './OptionsProcessor';
2
+import { Store } from '../components/Store.mock';
2 3
 
3 4
 describe('navigation options', () => {
4 5
   let options;
5
-
6
+  let store;
6 7
   beforeEach(() => {
7 8
     options = {};
9
+    store = new Store();
8 10
   });
9 11
 
10 12
   it('processes colors into numeric AARRGGBB', () => {
11 13
     options.someKeyColor = 'red';
12 14
     options.color = 'blue';
13
-    OptionsProcessor.processOptions(options);
15
+    OptionsProcessor.processOptions(options, store);
14 16
     expect(options.someKeyColor).toEqual(0xffff0000);
15 17
     expect(options.color).toEqual(0xff0000ff);
16 18
 
17 19
     options.someKeyColor = 'yellow';
18
-    OptionsProcessor.processOptions(options);
20
+    OptionsProcessor.processOptions(options, store);
19 21
     expect(options.someKeyColor).toEqual(0xffffff00);
20 22
   });
21 23
 
22 24
   it('processes numeric colors', () => {
23 25
     options.someKeyColor = '#123456';
24
-    OptionsProcessor.processOptions(options);
26
+    OptionsProcessor.processOptions(options, store);
25 27
     expect(options.someKeyColor).toEqual(0xff123456);
26 28
 
27 29
     options.someKeyColor = 0x123456ff; // wut
28
-    OptionsProcessor.processOptions(options);
30
+    OptionsProcessor.processOptions(options, store);
29 31
     expect(options.someKeyColor).toEqual(0xff123456);
30 32
   });
31 33
 
32 34
   it('process colors with rgb functions', () => {
33 35
     options.someKeyColor = 'rgb(255, 0, 255)';
34
-    OptionsProcessor.processOptions(options);
36
+    OptionsProcessor.processOptions(options, store);
35 37
     expect(options.someKeyColor).toEqual(0xffff00ff);
36 38
   });
37 39
 
38 40
   it('process colors with special words', () => {
39 41
     options.someKeyColor = 'fuchsia';
40
-    OptionsProcessor.processOptions(options);
42
+    OptionsProcessor.processOptions(options, store);
41 43
     expect(options.someKeyColor).toEqual(0xffff00ff);
42 44
   });
43 45
 
44 46
   it('process colors with hsla functions', () => {
45 47
     options.someKeyColor = 'hsla(360, 100%, 100%, 1.0)';
46
-    OptionsProcessor.processOptions(options);
48
+    OptionsProcessor.processOptions(options, store);
47 49
 
48 50
     expect(options.someKeyColor).toEqual(0xffffffff);
49 51
   });
50 52
 
51 53
   it('unknown colors return undefined', () => {
52 54
     options.someKeyColor = 'wut';
53
-    OptionsProcessor.processOptions(options);
55
+    OptionsProcessor.processOptions(options, store);
54 56
     expect(options.someKeyColor).toEqual(undefined);
55 57
   });
56 58
 
@@ -58,7 +60,7 @@ describe('navigation options', () => {
58 60
     options.otherKeyColor = 'red';
59 61
     options.yetAnotherColor = 'blue';
60 62
     options.andAnotherColor = 'rgb(0, 255, 0)';
61
-    OptionsProcessor.processOptions(options);
63
+    OptionsProcessor.processOptions(options, store);
62 64
     expect(options.otherKeyColor).toEqual(0xffff0000);
63 65
     expect(options.yetAnotherColor).toEqual(0xff0000ff);
64 66
     expect(options.andAnotherColor).toEqual(0xff00ff00);
@@ -66,14 +68,14 @@ describe('navigation options', () => {
66 68
 
67 69
   it('keys ending with Color case sensitive', () => {
68 70
     options.otherKey_color = 'red'; // eslint-disable-line camelcase
69
-    OptionsProcessor.processOptions(options);
71
+    OptionsProcessor.processOptions(options, store);
70 72
     expect(options.otherKey_color).toEqual('red');
71 73
   });
72 74
 
73 75
   it('any nested recursive keys ending with Color', () => {
74 76
     options.topBar = { textColor: 'red' };
75 77
     options.topBar.innerMostObj = { anotherColor: 'yellow' };
76
-    OptionsProcessor.processOptions(options);
78
+    OptionsProcessor.processOptions(options, store);
77 79
     expect(options.topBar.textColor).toEqual(0xffff0000);
78 80
     expect(options.topBar.innerMostObj.anotherColor).toEqual(0xffffff00);
79 81
   });
@@ -86,7 +88,7 @@ describe('navigation options', () => {
86 88
       myIcon: 'require("https://wix.github.io/react-native-navigation/_images/logo.png");',
87 89
       myOtherValue: 'value'
88 90
     };
89
-    OptionsProcessor.processOptions(options);
91
+    OptionsProcessor.processOptions(options, store);
90 92
 
91 93
     // As we can't import external images and we don't want to add an image here
92 94
     // I assign the icons to strings (what the require would generally look like)
@@ -98,19 +100,28 @@ describe('navigation options', () => {
98 100
     expect(options.topBar.myOtherValue).toEqual('value');
99 101
   });
100 102
 
103
+  it('register props for button options', () => {
104
+    const passProps = { prop: 'prop' };
105
+    options.rightButtons = [{ passProps, id: '1' }];
106
+
107
+    OptionsProcessor.processOptions({ o: options }, store);
108
+
109
+    expect(store.setPropsForComponentId).toBeCalledWith('1', passProps);
110
+  });
111
+
101 112
   it('processes Options object', () => {
102 113
     options.someKeyColor = 'rgb(255, 0, 255)';
103 114
     options.topBar = { textColor: 'red' };
104 115
     options.topBar.innerMostObj = { anotherColor: 'yellow' };
105 116
 
106
-    OptionsProcessor.processOptions({ o: options });
117
+    OptionsProcessor.processOptions({ o: options }, store);
107 118
 
108 119
     expect(options.topBar.textColor).toEqual(0xffff0000);
109 120
   });
110 121
 
111 122
   it('undefined value return undefined ', () => {
112 123
     options.someImage = undefined;
113
-    OptionsProcessor.processOptions(options);
124
+    OptionsProcessor.processOptions(options, store);
114 125
 
115 126
     expect(options.someImage).toEqual(undefined);
116 127
   });

+ 11
- 2
lib/src/commands/OptionsProcessor.ts 파일 보기

@@ -3,7 +3,7 @@ import { processColor } from 'react-native';
3 3
 import * as resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
4 4
 
5 5
 export class OptionsProcessor {
6
-  static processOptions(options) {
6
+  static processOptions(options, store) {
7 7
     _.forEach(options, (value, key) => {
8 8
       if (!value) { return; }
9 9
 
@@ -14,7 +14,16 @@ export class OptionsProcessor {
14 14
         options[key] = resolveAssetSource(options[key]);
15 15
       }
16 16
       if (_.isObject(value) || _.isArray(value)) {
17
-        OptionsProcessor.processOptions(value);
17
+        OptionsProcessor.processOptions(value, store);
18
+        OptionsProcessor.processArrayOptions(key, value, store);
19
+      }
20
+    });
21
+  }
22
+
23
+  static processArrayOptions(key, array, store) {
24
+    _.forEach(array, (value) => {
25
+      if (_.endsWith(key, 'Buttons') && value.passProps) {
26
+        store.setPropsForComponentId(value.id, value.passProps);
18 27
       }
19 28
     });
20 29
   }

+ 1
- 0
lib/src/components/Store.mock.ts 파일 보기

@@ -0,0 +1 @@
1
+export const { Store } = jest.genMockFromModule('./Store');