diff --git a/e2e/Options.test.js b/e2e/Options.test.js index 3b3a5cdb19b..f5326f3949d 100644 --- a/e2e/Options.test.js +++ b/e2e/Options.test.js @@ -56,9 +56,9 @@ describe('Options', () => { await elementById(TestIDs.HIDE_TOPBAR_DEFAULT_OPTIONS).tap(); await expect(elementById(TestIDs.TOP_BAR)).toBeVisible(); await elementById(TestIDs.PUSH_BTN).tap(); - await expect(elementById(TestIDs.TOP_BAR)).toBeNotVisible(); + await expect(elementById(TestIDs.PUSHED_SCREEN_HEADER)).toBeNotVisible(); await elementById(TestIDs.PUSH_BTN).tap(); - await expect(elementById(TestIDs.TOP_BAR)).toBeNotVisible(); + await expect(elementById(TestIDs.PUSHED_SCREEN_HEADER)).toBeNotVisible(); }); it('default options should not override static options', async () => { diff --git a/lib/ios/RNNBasePresenter.h b/lib/ios/RNNBasePresenter.h index c30445cee60..6c25696009f 100644 --- a/lib/ios/RNNBasePresenter.h +++ b/lib/ios/RNNBasePresenter.h @@ -8,10 +8,14 @@ typedef void (^RNNReactViewReadyCompletionBlock)(void); @property(nonatomic, strong) NSString *boundComponentId; +@property(nonatomic, strong) RNNNavigationOptions * defaultOptions; + - (instancetype)initWithDefaultOptions:(RNNNavigationOptions *)defaultOptions; - (void)bindViewController:(UIViewController *)boundViewController; +- (void)setDefaultOptions:(RNNNavigationOptions *)defaultOptions; + - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions; - (void)applyOptionsOnViewDidLayoutSubviews:(RNNNavigationOptions *)options; diff --git a/lib/ios/RNNBasePresenter.m b/lib/ios/RNNBasePresenter.m index 0d18b186bd8..413a81da0f2 100644 --- a/lib/ios/RNNBasePresenter.m +++ b/lib/ios/RNNBasePresenter.m @@ -8,7 +8,6 @@ @interface RNNBasePresenter () @property(nonatomic, strong) RNNDotIndicatorPresenter* dotIndicatorPresenter; -@property(nonatomic, strong) RNNNavigationOptions* defaultOptions; @end @implementation RNNBasePresenter @@ -24,6 +23,10 @@ - (void)bindViewController:(UIViewController *)boundViewCont _boundViewController = boundViewController; } +- (void)setDefaultOptions:(RNNNavigationOptions *)defaultOptions { + _defaultOptions = defaultOptions; +} + - (void)applyOptionsOnInit:(RNNNavigationOptions *)initialOptions { } diff --git a/lib/ios/RNNCommandsHandler.m b/lib/ios/RNNCommandsHandler.m index 1fae64e2e10..88415aad049 100644 --- a/lib/ios/RNNCommandsHandler.m +++ b/lib/ios/RNNCommandsHandler.m @@ -1,15 +1,12 @@ #import "RNNCommandsHandler.h" -#import "RNNNavigationOptions.h" #import "RNNRootViewController.h" -#import "RNNSplitViewController.h" -#import "RNNElementFinder.h" -#import "React/RCTUIManager.h" #import "RNNErrorHandler.h" #import "RNNDefaultOptionsHelper.h" #import "UIViewController+RNNOptions.h" #import "React/RCTI18nUtil.h" #import "UIViewController+LayoutProtocol.h" #import "RNNLayoutManager.h" +#import "UIViewController+Utils.h" static NSString* const setRoot = @"setRoot"; static NSString* const setStackRoot = @"setStackRoot"; @@ -86,7 +83,7 @@ - (void)setRoot:(NSDictionary*)layout commandId:(NSString*)commandId completion: - (void)mergeOptions:(NSString*)componentId options:(NSDictionary*)mergeOptions completion:(RNNTransitionCompletionBlock)completion { [self assertReady]; - UIViewController* vc = (UIViewController*)[RNNLayoutManager findComponentForId:componentId]; + UIViewController* vc = [RNNLayoutManager findComponentForId:componentId]; RNNNavigationOptions* newOptions = [[RNNNavigationOptions alloc] initWithDict:mergeOptions]; if ([vc conformsToProtocol:@protocol(RNNLayoutProtocol)] || [vc isKindOfClass:[RNNRootViewController class]]) { [CATransaction begin]; @@ -106,7 +103,7 @@ - (void)setDefaultOptions:(NSDictionary*)optionsDict completion:(RNNTransitionCo UIViewController *rootViewController = UIApplication.sharedApplication.delegate.window.rootViewController; [RNNDefaultOptionsHelper recrusivelySetDefaultOptions:defaultOptions onRootViewController:rootViewController]; - + completion(); } diff --git a/lib/ios/RNNNavigationController.m b/lib/ios/RNNNavigationController.m index 6170900945a..29f2c074acf 100644 --- a/lib/ios/RNNNavigationController.m +++ b/lib/ios/RNNNavigationController.m @@ -1,11 +1,15 @@ #import "RNNNavigationController.h" #import "RNNRootViewController.h" -#import "InteractivePopGestureDelegate.h" const NSInteger TOP_BAR_TRANSPARENT_TAG = 78264803; @implementation RNNNavigationController +-(void)setDefaultOptions:(RNNNavigationOptions *)defaultOptions { + [super setDefaultOptions:defaultOptions]; + [self.presenter setDefaultOptions:defaultOptions]; +} + - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; [self.presenter applyOptionsOnViewDidLayoutSubviews:self.resolveOptions]; diff --git a/lib/ios/RNNNavigationControllerPresenter.m b/lib/ios/RNNNavigationControllerPresenter.m index 828b157164b..8bc2fbf4155 100644 --- a/lib/ios/RNNNavigationControllerPresenter.m +++ b/lib/ios/RNNNavigationControllerPresenter.m @@ -1,9 +1,7 @@ #import "RNNNavigationControllerPresenter.h" #import "UINavigationController+RNNOptions.h" #import "RNNNavigationController.h" -#import #import "RNNCustomTitleView.h" -#import "UIViewController+LayoutProtocol.h" @interface RNNNavigationControllerPresenter() { RNNReactComponentRegistry* _componentRegistry; @@ -25,44 +23,43 @@ - (void)applyOptions:(RNNNavigationOptions *)options { [super applyOptions:options]; RNNNavigationController* navigationController = self.boundViewController; + RNNNavigationOptions * withDefault = [options withDefault:[self defaultOptions]]; self.interactivePopGestureDelegate = [InteractivePopGestureDelegate new]; self.interactivePopGestureDelegate.navigationController = navigationController; self.interactivePopGestureDelegate.originalDelegate = navigationController.interactivePopGestureRecognizer.delegate; navigationController.interactivePopGestureRecognizer.delegate = self.interactivePopGestureDelegate; - [navigationController rnn_setInteractivePopGestureEnabled:[options.popGesture getWithDefaultValue:YES]]; - [navigationController rnn_setRootBackgroundImage:[options.rootBackgroundImage getWithDefaultValue:nil]]; - [navigationController rnn_setNavigationBarTestID:[options.topBar.testID getWithDefaultValue:nil]]; - [navigationController rnn_setNavigationBarVisible:[options.topBar.visible getWithDefaultValue:YES] animated:[options.topBar.animate getWithDefaultValue:YES]]; - [navigationController rnn_hideBarsOnScroll:[options.topBar.hideOnScroll getWithDefaultValue:NO]]; - [navigationController rnn_setNavigationBarNoBorder:[options.topBar.noBorder getWithDefaultValue:NO]]; - [navigationController rnn_setBarStyle:[RCTConvert UIBarStyle:[options.topBar.barStyle getWithDefaultValue:@"default"]]]; - [navigationController rnn_setNavigationBarTranslucent:[options.topBar.background.translucent getWithDefaultValue:NO]]; - [navigationController rnn_setNavigationBarClipsToBounds:[options.topBar.background.clipToBounds getWithDefaultValue:NO]]; - [navigationController rnn_setNavigationBarBlur:[options.topBar.background.blur getWithDefaultValue:NO]]; - [navigationController setTopBarBackgroundColor:[options.topBar.background.color getWithDefaultValue:nil]]; - [navigationController rnn_setNavigationBarLargeTitleVisible:[options.topBar.largeTitle.visible getWithDefaultValue:NO]]; - [navigationController rnn_setNavigationBarLargeTitleFontFamily:[options.topBar.largeTitle.fontFamily getWithDefaultValue:nil] fontSize:[options.topBar.largeTitle.fontSize getWithDefaultValue:nil] color:[options.topBar.largeTitle.color getWithDefaultValue:nil]]; - [navigationController rnn_setNavigationBarFontFamily:[options.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[options.topBar.title.fontSize getWithDefaultValue:nil] color:[options.topBar.title.color getWithDefaultValue:nil]]; - [navigationController rnn_setBackButtonColor:[options.topBar.backButton.color getWithDefaultValue:nil]]; -} - -- (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options { - [super applyOptionsOnWillMoveToParentViewController:options]; + [navigationController rnn_setInteractivePopGestureEnabled:[withDefault.popGesture getWithDefaultValue:YES]]; + [navigationController rnn_setRootBackgroundImage:[withDefault.rootBackgroundImage getWithDefaultValue:nil]]; + [navigationController rnn_setNavigationBarTestID:[withDefault.topBar.testID getWithDefaultValue:nil]]; + [navigationController rnn_setNavigationBarVisible:[withDefault.topBar.visible getWithDefaultValue:YES] animated:[withDefault.topBar.animate getWithDefaultValue:YES]]; + [navigationController rnn_hideBarsOnScroll:[withDefault.topBar.hideOnScroll getWithDefaultValue:NO]]; + [navigationController rnn_setNavigationBarNoBorder:[withDefault.topBar.noBorder getWithDefaultValue:NO]]; + [navigationController rnn_setBarStyle:[RCTConvert UIBarStyle:[withDefault.topBar.barStyle getWithDefaultValue:@"default"]]]; + [navigationController rnn_setNavigationBarTranslucent:[withDefault.topBar.background.translucent getWithDefaultValue:NO]]; + [navigationController rnn_setNavigationBarClipsToBounds:[withDefault.topBar.background.clipToBounds getWithDefaultValue:NO]]; + [navigationController rnn_setNavigationBarBlur:[withDefault.topBar.background.blur getWithDefaultValue:NO]]; + [navigationController setTopBarBackgroundColor:[withDefault.topBar.background.color getWithDefaultValue:nil]]; + [navigationController rnn_setNavigationBarLargeTitleVisible:[withDefault.topBar.largeTitle.visible getWithDefaultValue:NO]]; + [navigationController rnn_setNavigationBarLargeTitleFontFamily:[withDefault.topBar.largeTitle.fontFamily getWithDefaultValue:nil] fontSize:[withDefault.topBar.largeTitle.fontSize getWithDefaultValue:nil] color:[withDefault.topBar.largeTitle.color getWithDefaultValue:nil]]; + [navigationController rnn_setNavigationBarFontFamily:[withDefault.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[withDefault.topBar.title.fontSize getWithDefaultValue:nil] color:[withDefault.topBar.title.color getWithDefaultValue:nil]]; + [navigationController rnn_setBackButtonColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil]]; } - (void)applyOptionsOnViewDidLayoutSubviews:(RNNNavigationOptions *)options { - if (options.topBar.background.component.name.hasValue) { + RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]]; + if (withDefault.topBar.background.component.name.hasValue) { [self presentBackgroundComponent]; } } - (void)applyOptionsBeforePopping:(RNNNavigationOptions *)options { + RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]]; RNNNavigationController* navigationController = self.boundViewController; - [navigationController setTopBarBackgroundColor:[options.topBar.background.color getWithDefaultValue:nil]]; - [navigationController rnn_setNavigationBarFontFamily:[options.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[options.topBar.title.fontSize getWithDefaultValue:nil] color:[options.topBar.title.color getWithDefaultValue:[UIColor blackColor]]]; - [navigationController rnn_setNavigationBarLargeTitleVisible:[options.topBar.largeTitle.visible getWithDefaultValue:NO]]; + [navigationController setTopBarBackgroundColor:[withDefault.topBar.background.color getWithDefaultValue:nil]]; + [navigationController rnn_setNavigationBarFontFamily:[withDefault.topBar.title.fontFamily getWithDefaultValue:nil] fontSize:[withDefault.topBar.title.fontSize getWithDefaultValue:nil] color:[withDefault.topBar.title.color getWithDefaultValue:[UIColor blackColor]]]; + [navigationController rnn_setNavigationBarLargeTitleVisible:[withDefault.topBar.largeTitle.visible getWithDefaultValue:NO]]; } - (void)mergeOptions:(RNNNavigationOptions *)newOptions currentOptions:(RNNNavigationOptions *)currentOptions { diff --git a/lib/ios/RNNRootViewController.m b/lib/ios/RNNRootViewController.m index bec8b899f08..ca8914a4200 100644 --- a/lib/ios/RNNRootViewController.m +++ b/lib/ios/RNNRootViewController.m @@ -27,6 +27,10 @@ - (void)bindViewController:(UIViewController *)viewController { [viewController didMoveToParentViewController:self]; } +- (void)setDefaultOptions:(RNNNavigationOptions *)defaultOptions { + [_presenter setDefaultOptions:defaultOptions]; +} + - (void)mergeOptions:(RNNNavigationOptions *)options { [_presenter mergeOptions:options currentOptions:self.options]; [self.parentViewController mergeOptions:options]; diff --git a/lib/ios/RNNSideMenuController.m b/lib/ios/RNNSideMenuController.m index 3ccbad308fc..2d35896fffe 100644 --- a/lib/ios/RNNSideMenuController.m +++ b/lib/ios/RNNSideMenuController.m @@ -34,6 +34,10 @@ - (instancetype)initWithLayoutInfo:(RNNLayoutInfo *)layoutInfo creator:(id *)bindedViewCont - (void)applyOptionsOnWillMoveToParentViewController:(RNNNavigationOptions *)options { [super applyOptionsOnWillMoveToParentViewController:options]; UIViewController* viewController = self.boundViewController; - [viewController rnn_setBackButtonIcon:[options.topBar.backButton.icon getWithDefaultValue:nil] withColor:[options.topBar.backButton.color getWithDefaultValue:nil] title:[options.topBar.backButton.showTitle getWithDefaultValue:YES] ? [options.topBar.backButton.title getWithDefaultValue:nil] : @""]; + RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]]; + [viewController rnn_setBackButtonIcon:[withDefault.topBar.backButton.icon getWithDefaultValue:nil] withColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil] title:[withDefault.topBar.backButton.showTitle getWithDefaultValue:YES] ? [withDefault.topBar.backButton.title getWithDefaultValue:nil] : @""]; } - (void)applyOptions:(RNNNavigationOptions *)options { [super applyOptions:options]; UIViewController* viewController = self.boundViewController; - [viewController rnn_setBackgroundImage:[options.backgroundImage getWithDefaultValue:nil]]; - [viewController rnn_setNavigationItemTitle:[options.topBar.title.text getWithDefaultValue:nil]]; - [viewController rnn_setTopBarPrefersLargeTitle:[options.topBar.largeTitle.visible getWithDefaultValue:NO]]; - [viewController rnn_setTabBarItemBadgeColor:[options.bottomTab.badgeColor getWithDefaultValue:nil]]; - [viewController rnn_setStatusBarBlur:[options.statusBar.blur getWithDefaultValue:NO]]; - [viewController rnn_setStatusBarStyle:[options.statusBar.style getWithDefaultValue:@"default"] animated:[options.statusBar.animate getWithDefaultValue:YES]]; - [viewController rnn_setBackButtonVisible:[options.topBar.backButton.visible getWithDefaultValue:YES]]; - [viewController rnn_setInterceptTouchOutside:[options.overlay.interceptTouchOutside getWithDefaultValue:YES]]; + RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]]; + [viewController rnn_setBackgroundImage:[withDefault.backgroundImage getWithDefaultValue:nil]]; + [viewController rnn_setNavigationItemTitle:[withDefault.topBar.title.text getWithDefaultValue:nil]]; + [viewController rnn_setTopBarPrefersLargeTitle:[withDefault.topBar.largeTitle.visible getWithDefaultValue:NO]]; + [viewController rnn_setTabBarItemBadgeColor:[withDefault.bottomTab.badgeColor getWithDefaultValue:nil]]; + [viewController rnn_setStatusBarBlur:[withDefault.statusBar.blur getWithDefaultValue:NO]]; + [viewController rnn_setStatusBarStyle:[withDefault.statusBar.style getWithDefaultValue:@"default"] animated:[withDefault.statusBar.animate getWithDefaultValue:YES]]; + [viewController rnn_setBackButtonVisible:[withDefault.topBar.backButton.visible getWithDefaultValue:YES]]; + [viewController rnn_setInterceptTouchOutside:[withDefault.overlay.interceptTouchOutside getWithDefaultValue:YES]]; - if (options.layout.backgroundColor.hasValue) { - [viewController rnn_setBackgroundColor:options.layout.backgroundColor.get]; + if (withDefault.layout.backgroundColor.hasValue) { + [viewController rnn_setBackgroundColor:withDefault.layout.backgroundColor.get]; } - if (options.topBar.searchBar.hasValue) { + if (withDefault.topBar.searchBar.hasValue) { BOOL hideNavBarOnFocusSearchBar = YES; - if (options.topBar.hideNavBarOnFocusSearchBar.hasValue) { - hideNavBarOnFocusSearchBar = options.topBar.hideNavBarOnFocusSearchBar.get; + if (withDefault.topBar.hideNavBarOnFocusSearchBar.hasValue) { + hideNavBarOnFocusSearchBar = withDefault.topBar.hideNavBarOnFocusSearchBar.get; } - [viewController rnn_setSearchBarWithPlaceholder:[options.topBar.searchBarPlaceholder getWithDefaultValue:@""] hideNavBarOnFocusSearchBar: hideNavBarOnFocusSearchBar]; + [viewController rnn_setSearchBarWithPlaceholder:[withDefault.topBar.searchBarPlaceholder getWithDefaultValue:@""] hideNavBarOnFocusSearchBar: hideNavBarOnFocusSearchBar]; } - [self setTitleViewWithSubtitle:options]; + [self setTitleViewWithSubtitle:withDefault]; } - (void)applyOptionsOnInit:(RNNNavigationOptions *)options { [super applyOptionsOnInit:options]; UIViewController* viewController = self.boundViewController; - [viewController rnn_setModalPresentationStyle:[RCTConvert UIModalPresentationStyle:[options.modalPresentationStyle getWithDefaultValue:@"fullScreen"]]]; - [viewController rnn_setModalTransitionStyle:[RCTConvert UIModalTransitionStyle:[options.modalTransitionStyle getWithDefaultValue:@"coverVertical"]]]; - [viewController rnn_setDrawBehindTopBar:[options.topBar.drawBehind getWithDefaultValue:NO]]; - [viewController rnn_setDrawBehindTabBar:[options.bottomTabs.drawBehind getWithDefaultValue:NO] || ![options.bottomTabs.visible getWithDefaultValue:YES]]; - - if ((options.topBar.leftButtons || options.topBar.rightButtons)) { - [_navigationButtons applyLeftButtons:options.topBar.leftButtons rightButtons:options.topBar.rightButtons defaultLeftButtonStyle:options.topBar.leftButtonStyle defaultRightButtonStyle:options.topBar.rightButtonStyle]; + RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]]; + [viewController rnn_setModalPresentationStyle:[RCTConvert UIModalPresentationStyle:[withDefault.modalPresentationStyle getWithDefaultValue:@"fullScreen"]]]; + [viewController rnn_setModalTransitionStyle:[RCTConvert UIModalTransitionStyle:[withDefault.modalTransitionStyle getWithDefaultValue:@"coverVertical"]]]; + [viewController rnn_setDrawBehindTopBar:[withDefault.topBar.drawBehind getWithDefaultValue:NO]]; + [viewController rnn_setDrawBehindTabBar:[withDefault.bottomTabs.drawBehind getWithDefaultValue:NO] || ![withDefault.bottomTabs.visible getWithDefaultValue:YES]]; + + if ((withDefault.topBar.leftButtons || withDefault.topBar.rightButtons)) { + [_navigationButtons applyLeftButtons:withDefault.topBar.leftButtons rightButtons:withDefault.topBar.rightButtons defaultLeftButtonStyle:withDefault.topBar.leftButtonStyle defaultRightButtonStyle:withDefault.topBar.rightButtonStyle]; } } diff --git a/lib/ios/UIViewController+RNNOptions.h b/lib/ios/UIViewController+RNNOptions.h index a2c6396ad60..5e5e026e5b4 100644 --- a/lib/ios/UIViewController+RNNOptions.h +++ b/lib/ios/UIViewController+RNNOptions.h @@ -1,9 +1,12 @@ #import @class RNNBottomTabOptions; +@class RNNNavigationOptions; @interface UIViewController (RNNOptions) +- (void)setDefaultOptions:(RNNNavigationOptions *)defaultOptions; + - (void)rnn_setBackgroundImage:(UIImage *)backgroundImage; - (void)rnn_setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle; diff --git a/lib/ios/UIViewController+RNNOptions.m b/lib/ios/UIViewController+RNNOptions.m index 37a0e59970a..5f781657542 100644 --- a/lib/ios/UIViewController+RNNOptions.m +++ b/lib/ios/UIViewController+RNNOptions.m @@ -2,12 +2,17 @@ #import #import "UIImage+tint.h" #import "RNNBottomTabOptions.h" +#import "RNNNavigationOptions.h" #define kStatusBarAnimationDuration 0.35 const NSInteger BLUR_STATUS_TAG = 78264801; @implementation UIViewController (RNNOptions) +- (void)setDefaultOptions:(RNNNavigationOptions *)defaultOptions { + +} + - (void)rnn_setBackgroundImage:(UIImage *)backgroundImage { if (backgroundImage) { UIImageView* backgroundImageView = (self.view.subviews.count > 0) ? self.view.subviews[0] : nil; diff --git a/playground/src/screens/StatusBarOptionsScreen.js b/playground/src/screens/StatusBarOptionsScreen.js index a1bbcdd7db9..4827144eb62 100644 --- a/playground/src/screens/StatusBarOptionsScreen.js +++ b/playground/src/screens/StatusBarOptionsScreen.js @@ -31,18 +31,20 @@ class StatusBarOptions extends React.Component { render() { return ( - + -