#import "RNNCommandsHandler.h" #import "RNNModalManager.h" #import "RNNNavigationStackManager.h" #import "RNNOverlayManager.h" #import "RNNNavigationOptions.h" #import "RNNRootViewController.h" #import "React/RCTUIManager.h" @implementation RNNCommandsHandler { RNNControllerFactory *_controllerFactory; RNNStore *_store; RNNNavigationStackManager* _navigationStackManager; RNNModalManager* _modalManager; RNNOverlayManager* _overlayManager; } -(instancetype) initWithStore:(RNNStore*)store controllerFactory:(RNNControllerFactory*)controllerFactory { self = [super init]; _store = store; _controllerFactory = controllerFactory; _navigationStackManager = [[RNNNavigationStackManager alloc] initWithStore:_store]; _modalManager = [[RNNModalManager alloc] initWithStore:_store]; _overlayManager = [[RNNOverlayManager alloc] init]; return self; } #pragma mark - public -(void) setRoot:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; [_modalManager dismissAllModals]; UIViewController *vc = [_controllerFactory createLayoutAndSaveToStore:layout]; UIApplication.sharedApplication.delegate.window.rootViewController = vc; [UIApplication.sharedApplication.delegate.window makeKeyAndVisible]; completion(); } -(void) setOptions:(NSString*)componentId options:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; UIViewController* vc = [_store findComponentForId:componentId]; if([vc isKindOfClass:[RNNRootViewController class]]) { RNNRootViewController* rootVc = (RNNRootViewController*)vc; [rootVc.options mergeWith:options]; [CATransaction begin]; [CATransaction setCompletionBlock:completion]; [rootVc.options applyOn:vc]; [CATransaction commit]; } } -(void) setDefaultOptions:(NSDictionary*)optionsDict completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:optionsDict]; [_controllerFactory setDefaultOptions:options]; } -(void) push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; UIViewController *newVc = [_controllerFactory createLayoutAndSaveToStore:layout]; [_navigationStackManager push:newVc onTop:componentId completion:^{ [_controllerFactory.eventEmitter sendNavigationEvent:[RNNNavigationEvent create:kPush fromComponent:componentId toComponent:newVc.componentId]]; completion(); }]; } -(void)pop:(NSString*)componentId options:(NSDictionary*)options completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; [CATransaction begin]; [CATransaction setCompletionBlock:^{ [_controllerFactory.eventEmitter sendNavigationEvent:[RNNNavigationEvent create:kPop fromComponent:nil toComponent:componentId]]; completion(); }]; NSDictionary* animationData = options[@"customTransition"]; RNNTransitionOptions* transitionOptions = [[RNNTransitionOptions alloc] initWithDict:animationData]; if (transitionOptions){ if (transitionOptions.animations) { [_navigationStackManager pop:componentId withTransitionOptions:transitionOptions]; } else { [[NSException exceptionWithName:NSInvalidArgumentException reason:@"unsupported transitionAnimation" userInfo:nil] raise]; } } else { [_navigationStackManager pop:componentId withTransitionOptions:nil]; } [CATransaction commit]; } -(void) popTo:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; [CATransaction begin]; [CATransaction setCompletionBlock:^{ [_controllerFactory.eventEmitter sendNavigationEvent:[RNNNavigationEvent create:kPopTo fromComponent:nil toComponent:componentId]]; completion(); }]; [_navigationStackManager popTo:componentId]; [CATransaction commit]; } -(void) popToRoot:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; [CATransaction begin]; [CATransaction setCompletionBlock:^{ [_controllerFactory.eventEmitter sendNavigationEvent:[RNNNavigationEvent create:kPopToRoot fromComponent:componentId toComponent:nil]]; completion(); }]; [_navigationStackManager popToRoot:componentId]; [CATransaction commit]; } -(void) showModal:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; UIViewController *newVc = [_controllerFactory createLayoutAndSaveToStore:layout]; [_modalManager showModal:newVc completion:^{ [_controllerFactory.eventEmitter sendNavigationEvent:[RNNNavigationEvent create:kShowModal fromComponent:nil toComponent:newVc.componentId]]; completion(); }]; } -(void) dismissModal:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; [CATransaction begin]; [CATransaction setCompletionBlock:^{ [_controllerFactory.eventEmitter sendNavigationEvent:[RNNNavigationEvent create:kDismissModal fromComponent:componentId toComponent:nil]]; completion(); }]; [_modalManager dismissModal:componentId]; [CATransaction commit]; } -(void) dismissAllModalsWithCompletion:(RNNTransitionCompletionBlock)completion { [self assertReady]; [CATransaction begin]; [CATransaction setCompletionBlock:^{ [_controllerFactory.eventEmitter sendNavigationEvent:[RNNNavigationEvent create:kDismissAllModals fromComponent:nil toComponent:nil]]; completion(); }]; [_modalManager dismissAllModals]; [CATransaction commit]; } -(void)showOverlay:(NSDictionary *)layout completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; UIViewController* overlayVC = [_controllerFactory createOverlay:layout]; [_overlayManager showOverlay:overlayVC completion:^{ [_controllerFactory.eventEmitter sendNavigationEvent:[RNNNavigationEvent create:kShowOverlay fromComponent:nil toComponent:overlayVC.componentId]]; completion(); }]; } - (void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; [_overlayManager dismissOverlay:componentId completion:^{ [_controllerFactory.eventEmitter sendNavigationEvent:[RNNNavigationEvent create:kDismissOverlay fromComponent:componentId toComponent:nil]]; completion(); }]; } #pragma mark - private -(void) assertReady { if (!_store.isReadyToReceiveCommands) { [[NSException exceptionWithName:@"BridgeNotLoadedError" reason:@"Bridge not yet loaded! Send commands after Navigation.events().onAppLaunched() has been called." userInfo:nil] raise]; } } @end