Skip to content

Commit

Permalink
SetRoot wait for render (#4688)
Browse files Browse the repository at this point in the history
* Layout changes

* WIP

* Revert "Layout changes"

This reverts commit 4da8cfb.

* Clean topBar.component and topBar.background.component when not needed

* Move custom components login from viewController to presenters

* Change waitForRender and enabled property from primitive bool to Bool object

* Fix ios unit tests

* Add unit tests

* Remove RNNReactView observer when view ready

* Load react components from component manager

* Remove createCustomReactView duplication

* Handle render children in each Layout

* Wait for navigation presenter components render, refactor RNNTitleViewHelper

* Fix unit tests

* Add waitForRender for custom react components

* Fixes e2e
  • Loading branch information
yogevbd authored Feb 6, 2019
1 parent bb9b557 commit 5abea28
Show file tree
Hide file tree
Showing 52 changed files with 621 additions and 305 deletions.
12 changes: 12 additions & 0 deletions lib/ios/RNNBasePresenter.m
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
#import "RNNBasePresenter.h"
#import "UIViewController+RNNOptions.h"
#import "RNNTabBarItemCreator.h"
#import "RNNReactComponentManager.h"

@interface RNNBasePresenter ()
@property (nonatomic, strong) RNNReactComponentManager* componentManager;
@end


@implementation RNNBasePresenter

- (instancetype)initWithComponentManager:(RNNReactComponentManager *)componentManager {
self = [super init];
self.componentManager = componentManager;
return self;
}

- (void)bindViewController:(UIViewController *)bindedViewController {
_bindedViewController = bindedViewController;
}
Expand Down
6 changes: 5 additions & 1 deletion lib/ios/RNNBridgeManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
#import "RNNBridgeModule.h"
#import "RNNRootViewCreator.h"
#import "RNNReactRootViewCreator.h"
#import "RNNReactComponentManager.h"

@interface RNNBridgeManager() <RCTBridgeDelegate>

@property (nonatomic, strong, readwrite) RCTBridge *bridge;
@property (nonatomic, strong, readwrite) RNNStore *store;
@property (nonatomic, strong, readwrite) RNNReactComponentManager *componentManager;

@end

Expand Down Expand Up @@ -77,7 +79,8 @@ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
RNNEventEmitter *eventEmitter = [[RNNEventEmitter alloc] init];

id<RNNRootViewCreator> rootViewCreator = [[RNNReactRootViewCreator alloc] initWithBridge:bridge];
RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator eventEmitter:eventEmitter andBridge:bridge];
_componentManager = [[RNNReactComponentManager alloc] initWithCreator:rootViewCreator];
RNNControllerFactory *controllerFactory = [[RNNControllerFactory alloc] initWithRootViewCreator:rootViewCreator eventEmitter:eventEmitter store:_store componentManager:_componentManager andBridge:bridge];

_commandsHandler = [[RNNCommandsHandler alloc] initWithStore:_store controllerFactory:controllerFactory eventEmitter:eventEmitter stackManager:[RNNNavigationStackManager new] modalManager:[RNNModalManager new] overlayManager:[RNNOverlayManager new] mainWindow:_mainWindow];
RNNBridgeModule *bridgeModule = [[RNNBridgeModule alloc] initWithCommandsHandler:_commandsHandler];
Expand All @@ -89,6 +92,7 @@ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {

- (void)onJavaScriptWillLoad {
[_store clean];
[_componentManager clean];
}

- (void)onJavaScriptLoaded {
Expand Down
54 changes: 30 additions & 24 deletions lib/ios/RNNCommandsHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,13 @@ - (void)setRoot:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)c
[_modalManager dismissAllModalsAnimated:NO];
[_store removeAllComponentsFromWindow:_mainWindow];

UIViewController *vc = [_controllerFactory createLayout:layout[@"root"] saveToStore:_store];
UIViewController<RNNLayoutProtocol> *vc = [_controllerFactory createLayout:layout[@"root"]];

_mainWindow.rootViewController = vc;

[_eventEmitter sendOnNavigationCommandCompletion:setRoot params:@{@"layout": layout}];
completion();
[vc renderTreeAndWait:[vc.resolveOptions.animations.setRoot.waitForRender getWithDefaultValue:NO] perform:^{
_mainWindow.rootViewController = vc;
[_eventEmitter sendOnNavigationCommandCompletion:setRoot params:@{@"layout": layout}];
completion() ;
}];
}

- (void)mergeOptions:(NSString*)componentId options:(NSDictionary*)mergeOptions completion:(RNNTransitionCompletionBlock)completion {
Expand Down Expand Up @@ -96,7 +97,7 @@ - (void)setDefaultOptions:(NSDictionary*)optionsDict completion:(RNNTransitionCo
- (void)push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
[self assertReady];

UIViewController<RNNLayoutProtocol> *newVc = [_controllerFactory createLayout:layout saveToStore:_store];
UIViewController<RNNLayoutProtocol> *newVc = [_controllerFactory createLayout:layout];
UIViewController *fromVC = [_store findComponentForId:componentId];

if ([[newVc.resolveOptions.preview.reactTag getWithDefaultValue:@(0)] floatValue] > 0) {
Expand Down Expand Up @@ -141,8 +142,8 @@ - (void)push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNN
}
} else {
id animationDelegate = (newVc.resolveOptions.animations.push.hasCustomAnimation || newVc.getCurrentLeaf.isCustomTransitioned) ? newVc : nil;
[newVc.getCurrentLeaf waitForReactViewRender:(newVc.resolveOptions.animations.push.waitForRender || animationDelegate) perform:^{
[_stackManager push:newVc onTop:fromVC animated:newVc.resolveOptions.animations.push.enable animationDelegate:animationDelegate completion:^{
[newVc renderTreeAndWait:([newVc.resolveOptions.animations.push.waitForRender getWithDefaultValue:NO] || animationDelegate) perform:^{
[_stackManager push:newVc onTop:fromVC animated:[newVc.resolveOptions.animations.push.enable getWithDefaultValue:YES] animationDelegate:animationDelegate completion:^{
[_eventEmitter sendOnNavigationCommandCompletion:push params:@{@"componentId": componentId}];
completion();
} rejection:rejection];
Expand All @@ -153,11 +154,14 @@ - (void)push:(NSString*)componentId layout:(NSDictionary*)layout completion:(RNN
- (void)setStackRoot:(NSString*)componentId children:(NSArray*)children completion:(RNNTransitionCompletionBlock)completion rejection:(RCTPromiseRejectBlock)rejection {
[self assertReady];

NSArray<RNNLayoutProtocol> *childViewControllers = [_controllerFactory createChildrenLayout:children saveToStore:_store];
NSArray<RNNLayoutProtocol> *childViewControllers = [_controllerFactory createChildrenLayout:children];
for (UIViewController<RNNLayoutProtocol>* viewController in childViewControllers) {
[viewController renderTreeAndWait:NO perform:nil];
}
RNNNavigationOptions* options = [childViewControllers.lastObject getCurrentChild].resolveOptions;
UIViewController *fromVC = [_store findComponentForId:componentId];
__weak typeof(RNNEventEmitter*) weakEventEmitter = _eventEmitter;
[_stackManager setStackChildren:childViewControllers fromViewController:fromVC animated:options.animations.setStackRoot.enable completion:^{
[_stackManager setStackChildren:childViewControllers fromViewController:fromVC animated:[options.animations.setStackRoot.enable getWithDefaultValue:YES] completion:^{
[weakEventEmitter sendOnNavigationCommandCompletion:setStackRoot params:@{@"componentId": componentId}];
completion();
} rejection:rejection];
Expand All @@ -181,10 +185,10 @@ - (void)pop:(NSString*)componentId mergeOptions:(NSDictionary*)mergeOptions comp
} else {
NSMutableArray * vcs = nvc.viewControllers.mutableCopy;
[vcs removeObject:vc];
[nvc setViewControllers:vcs animated:vc.resolveOptions.animations.pop.enable];
[nvc setViewControllers:vcs animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES]];
}

[_stackManager pop:vc animated:vc.resolveOptions.animations.pop.enable completion:^{
[_stackManager pop:vc animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES] completion:^{
[_store removeComponent:componentId];
[_eventEmitter sendOnNavigationCommandCompletion:pop params:@{@"componentId": componentId}];
completion();
Expand All @@ -197,7 +201,7 @@ - (void)popTo:(NSString*)componentId mergeOptions:(NSDictionary *)mergeOptions c
RNNNavigationOptions *options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
[vc overrideOptions:options];

[_stackManager popTo:vc animated:vc.resolveOptions.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
[_stackManager popTo:vc animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES] completion:^(NSArray *poppedViewControllers) {
[_eventEmitter sendOnNavigationCommandCompletion:popTo params:@{@"componentId": componentId}];
[self removePopedViewControllers:poppedViewControllers];
completion();
Expand All @@ -216,7 +220,7 @@ - (void)popToRoot:(NSString*)componentId mergeOptions:(NSDictionary *)mergeOptio
completion();
}];

[_stackManager popToRoot:vc animated:vc.resolveOptions.animations.pop.enable completion:^(NSArray *poppedViewControllers) {
[_stackManager popToRoot:vc animated:[vc.resolveOptions.animations.pop.enable getWithDefaultValue:YES] completion:^(NSArray *poppedViewControllers) {
[self removePopedViewControllers:poppedViewControllers];
} rejection:^(NSString *code, NSString *message, NSError *error) {

Expand All @@ -228,10 +232,10 @@ - (void)popToRoot:(NSString*)componentId mergeOptions:(NSDictionary *)mergeOptio
- (void)showModal:(NSDictionary*)layout completion:(RNNTransitionWithComponentIdCompletionBlock)completion {
[self assertReady];

UIViewController<RNNParentProtocol> *newVc = [_controllerFactory createLayout:layout saveToStore:_store];
UIViewController<RNNParentProtocol> *newVc = [_controllerFactory createLayout:layout];

[newVc.getCurrentLeaf waitForReactViewRender:newVc.getCurrentLeaf.resolveOptions.animations.showModal.waitForRender perform:^{
[_modalManager showModal:newVc animated:newVc.getCurrentChild.resolveOptions.animations.showModal.enable hasCustomAnimation:newVc.getCurrentChild.resolveOptions.animations.showModal.hasCustomAnimation completion:^(NSString *componentId) {
[newVc renderTreeAndWait:[newVc.getCurrentLeaf.resolveOptions.animations.showModal.waitForRender getWithDefaultValue:NO] perform:^{
[_modalManager showModal:newVc animated:[newVc.getCurrentChild.resolveOptions.animations.showModal.enable getWithDefaultValue:YES] hasCustomAnimation:newVc.getCurrentChild.resolveOptions.animations.showModal.hasCustomAnimation completion:^(NSString *componentId) {
[_eventEmitter sendOnNavigationCommandCompletion:showModal params:@{@"layout": layout}];
completion(componentId);
}];
Expand Down Expand Up @@ -272,20 +276,22 @@ - (void)dismissAllModals:(NSDictionary *)mergeOptions completion:(RNNTransitionC
completion();
}];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
[_modalManager dismissAllModalsAnimated:options.animations.dismissModal.enable];
[_modalManager dismissAllModalsAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES]];

[CATransaction commit];
}

- (void)showOverlay:(NSDictionary *)layout completion:(RNNTransitionCompletionBlock)completion {
[self assertReady];

UIViewController<RNNParentProtocol>* overlayVC = [_controllerFactory createLayout:layout saveToStore:_store];
UIWindow* overlayWindow = [[RNNOverlayWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
overlayWindow.rootViewController = overlayVC;
[_overlayManager showOverlayWindow:overlayWindow];
[_eventEmitter sendOnNavigationCommandCompletion:showOverlay params:@{@"layout": layout}];
completion();
UIViewController<RNNParentProtocol>* overlayVC = [_controllerFactory createLayout:layout];
[overlayVC renderTreeAndWait:[overlayVC.options.animations.showOverlay.waitForRender getWithDefaultValue:NO] perform:^{
UIWindow* overlayWindow = [[RNNOverlayWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
overlayWindow.rootViewController = overlayVC;
[_overlayManager showOverlayWindow:overlayWindow];
[_eventEmitter sendOnNavigationCommandCompletion:showOverlay params:@{@"layout": layout}];
completion();
}];
}

- (void)dismissOverlay:(NSString*)componentId completion:(RNNTransitionCompletionBlock)completion rejection:(RNNTransitionRejectionBlock)reject {
Expand Down
1 change: 1 addition & 0 deletions lib/ios/RNNComponentOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
@property (nonatomic, strong) Text* name;
@property (nonatomic, strong) Text* componentId;
@property (nonatomic, strong) Text* alignment;
@property (nonatomic, strong) Bool* waitForRender;

@end
1 change: 1 addition & 0 deletions lib/ios/RNNComponentOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ - (instancetype)initWithDict:(NSDictionary *)dict {
self.name = [TextParser parse:dict key:@"name"];
self.componentId = [TextParser parse:dict key:@"componentId"];
self.alignment = [TextParser parse:dict key:@"alignment"];
self.waitForRender = [BoolParser parse:dict key:@"waitForRender"];

return self;
}
Expand Down
7 changes: 5 additions & 2 deletions lib/ios/RNNControllerFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@
#import "RNNStore.h"
#import "RNNEventEmitter.h"
#import "RNNParentProtocol.h"
#import "RNNReactComponentManager.h"

@interface RNNControllerFactory : NSObject

-(instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
eventEmitter:(RNNEventEmitter*)eventEmitter
store:(RNNStore *)store
componentManager:(RNNReactComponentManager *)componentManager
andBridge:(RCTBridge*)bridge;

- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout saveToStore:(RNNStore *)store;
- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout;

- (NSArray<RNNLayoutProtocol> *)createChildrenLayout:(NSArray*)children saveToStore:(RNNStore *)store;
- (NSArray<RNNLayoutProtocol> *)createChildrenLayout:(NSArray*)children;

@property (nonatomic, strong) RNNEventEmitter *eventEmitter;

Expand Down
27 changes: 10 additions & 17 deletions lib/ios/RNNControllerFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,39 @@ @implementation RNNControllerFactory {
id<RNNRootViewCreator> _creator;
RNNStore *_store;
RCTBridge *_bridge;
RNNReactComponentManager* _componentManager;
}

# pragma mark public


- (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
eventEmitter:(RNNEventEmitter*)eventEmitter
store:(RNNStore *)store
componentManager:(RNNReactComponentManager *)componentManager
andBridge:(RCTBridge *)bridge {

self = [super init];

_creator = creator;
_eventEmitter = eventEmitter;
_bridge = bridge;
_store = store;
_componentManager = componentManager;

return self;
}

- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout saveToStore:(RNNStore *)store {
_store = store;
- (UIViewController<RNNParentProtocol> *)createLayout:(NSDictionary*)layout {
UIViewController<RNNParentProtocol>* layoutViewController = [self fromTree:layout];
_store = nil;
return layoutViewController;
}

- (NSArray<RNNLayoutProtocol> *)createChildrenLayout:(NSArray*)children saveToStore:(RNNStore *)store {
_store = store;
- (NSArray<RNNLayoutProtocol> *)createChildrenLayout:(NSArray*)children {
NSMutableArray<RNNLayoutProtocol>* childViewControllers = [NSMutableArray<RNNLayoutProtocol> new];
for (NSDictionary* layout in children) {
[childViewControllers addObject:[self fromTree:layout]];
}
_store = nil;
return childViewControllers;
}

Expand Down Expand Up @@ -114,17 +115,10 @@ - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator
- (UIViewController<RNNParentProtocol> *)createComponent:(RNNLayoutNode*)node {
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;

RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] init];

RNNViewControllerPresenter* presenter = [[RNNViewControllerPresenter alloc] initWithComponentManager:_componentManager];

RNNRootViewController* component = [[RNNRootViewController alloc] initWithLayoutInfo:layoutInfo rootViewCreator:_creator eventEmitter:_eventEmitter presenter:presenter options:options defaultOptions:_defaultOptions];

if (!component.isExternalViewController) {
CGSize availableSize = UIApplication.sharedApplication.delegate.window.bounds.size;
[_bridge.uiManager setAvailableSize:availableSize forRootView:component.view];
}

return (UIViewController<RNNParentProtocol> *)component;
}

Expand All @@ -143,14 +137,13 @@ - (instancetype)initWithRootViewCreator:(id <RNNRootViewCreator>)creator


- (UIViewController<RNNParentProtocol> *)createStack:(RNNLayoutNode*)node {
RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] init];

RNNNavigationControllerPresenter* presenter = [[RNNNavigationControllerPresenter alloc] initWithComponentManager:_componentManager];
RNNLayoutInfo* layoutInfo = [[RNNLayoutInfo alloc] initWithNode:node];
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:node.data[@"options"]];;

NSArray *childViewControllers = [self extractChildrenViewControllersFromNode:node];

RNNNavigationController* stack = [[RNNNavigationController alloc] initWithLayoutInfo:layoutInfo childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter];
RNNNavigationController* stack = [[RNNNavigationController alloc] initWithLayoutInfo:layoutInfo creator:_creator childViewControllers:childViewControllers options:options defaultOptions:_defaultOptions presenter:presenter];

return stack;
}
Expand Down
6 changes: 5 additions & 1 deletion lib/ios/RNNLayoutProtocol.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#import "RNNLayoutInfo.h"
#import "RNNViewControllerPresenter.h"
#import "RNNLeafProtocol.h"
#import "RNNBasePresenter.h"

typedef void (^RNNReactViewReadyCompletionBlock)(void);

@protocol RNNLayoutProtocol <NSObject, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate, UISplitViewControllerDelegate>

Expand All @@ -11,6 +13,8 @@
@property (nonatomic, strong) RNNNavigationOptions* options;
@property (nonatomic, strong) RNNNavigationOptions* defaultOptions;

- (void)renderTreeAndWait:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock;

- (UIViewController<RNNLayoutProtocol> *)getCurrentChild;

- (UIViewController<RNNLeafProtocol, RNNLayoutProtocol> *)getCurrentLeaf;
Expand Down
7 changes: 0 additions & 7 deletions lib/ios/RNNLeafProtocol.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
#import "RNNRootViewCreator.h"

typedef void (^RNNReactViewReadyCompletionBlock)(void);

@protocol RNNLeafProtocol <NSObject>

- (void)waitForReactViewRender:(BOOL)wait perform:(RNNReactViewReadyCompletionBlock)readyBlock;

- (void)bindViewController:(UIViewController *)viewController;

- (BOOL)isCustomTransitioned;

- (id<RNNRootViewCreator>)creator;

@end
4 changes: 2 additions & 2 deletions lib/ios/RNNModalManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ -(void)removePendingNextModalIfOnTop:(RNNTransitionCompletionBlock)completion {
}

if (modalToDismiss == topPresentedVC || [[topPresentedVC childViewControllers] containsObject:modalToDismiss]) {
[modalToDismiss dismissViewControllerAnimated:options.animations.dismissModal.enable completion:^{
[modalToDismiss dismissViewControllerAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES] completion:^{
[_pendingModalIdsToDismiss removeObject:modalToDismiss];
if (modalToDismiss.view) {
[self dismissedModal:modalToDismiss];
Expand All @@ -88,7 +88,7 @@ -(void)removePendingNextModalIfOnTop:(RNNTransitionCompletionBlock)completion {
} else {
[modalToDismiss.view removeFromSuperview];
modalToDismiss.view = nil;
modalToDismiss.getCurrentChild.resolveOptions.animations.dismissModal.enable = NO;
modalToDismiss.getCurrentChild.resolveOptions.animations.dismissModal.enable = [[Bool alloc] initWithBOOL:NO];
[self dismissedModal:modalToDismiss];

if (completion) {
Expand Down
3 changes: 2 additions & 1 deletion lib/ios/RNNNavigationButtons.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
#import <UIKit/UIKit.h>
#import "RNNButtonOptions.h"
#import "RNNRootViewCreator.h"
#import "RNNReactComponentManager.h"

@interface RNNNavigationButtons : NSObject

-(instancetype)initWithViewController:(UIViewController*)viewController rootViewCreator:(id<RNNRootViewCreator>)creator;
-(instancetype)initWithViewController:(UIViewController*)viewController componentManager:(RNNReactComponentManager *)componentManager;

-(void)applyLeftButtons:(NSArray*)leftButtons rightButtons:(NSArray*)rightButtons defaultLeftButtonStyle:(RNNButtonOptions *)defaultLeftButtonStyle defaultRightButtonStyle:(RNNButtonOptions *)defaultRightButtonStyle;

Expand Down
Loading

0 comments on commit 5abea28

Please sign in to comment.