Skip to content

Commit

Permalink
Fix topBar options merging with default (#5918)
Browse files Browse the repository at this point in the history
  • Loading branch information
yogevbd authored Feb 10, 2020
1 parent 0011bcb commit af34fb3
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 130 deletions.
226 changes: 113 additions & 113 deletions lib/ios/RNNStackPresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
#import "InteractivePopGestureDelegate.h"

@interface RNNStackPresenter() {
RNNReactComponentRegistry* _componentRegistry;
UIView* _customTopBarBackground;
RNNReactView* _topBarBackgroundReactView;
RNNReactComponentRegistry* _componentRegistry;
UIView* _customTopBarBackground;
RNNReactView* _topBarBackgroundReactView;
TopBarPresenter* _topBarPresenter;
InteractivePopGestureDelegate *_interactivePopGestureDelegate;
}
Expand All @@ -20,10 +20,10 @@ @interface RNNStackPresenter() {
@implementation RNNStackPresenter

- (instancetype)initWithComponentRegistry:(RNNReactComponentRegistry *)componentRegistry defaultOptions:(RNNNavigationOptions *)defaultOptions {
self = [super initWithDefaultOptions:defaultOptions];
_componentRegistry = componentRegistry;
self = [super initWithDefaultOptions:defaultOptions];
_componentRegistry = componentRegistry;
_interactivePopGestureDelegate = [InteractivePopGestureDelegate new];
return self;
return self;
}

- (void)bindViewController:(UINavigationController *)boundViewController {
Expand All @@ -46,149 +46,149 @@ - (RNNStackController *)stackController {
}

- (void)applyOptions:(RNNNavigationOptions *)options {
[super applyOptions:options];
RNNStackController* stack = self.stackController;
RNNNavigationOptions * withDefault = [options withDefault:[self defaultOptions]];
[super applyOptions:options];
RNNStackController* stack = self.stackController;
RNNNavigationOptions * withDefault = [options withDefault:[self defaultOptions]];
[_interactivePopGestureDelegate setEnabled:[withDefault.popGesture getWithDefaultValue:YES]];
stack.interactivePopGestureRecognizer.delegate = _interactivePopGestureDelegate;
stack.interactivePopGestureRecognizer.delegate = _interactivePopGestureDelegate;

[stack setBarStyle:[RCTConvert UIBarStyle:[withDefault.topBar.barStyle getWithDefaultValue:@"default"]]];
[stack setRootBackgroundImage:[withDefault.rootBackgroundImage getWithDefaultValue:nil]];
[stack setNavigationBarTestId:[withDefault.topBar.testID getWithDefaultValue:nil]];
[stack setNavigationBarVisible:[withDefault.topBar.visible getWithDefaultValue:YES] animated:[withDefault.topBar.animate getWithDefaultValue:YES]];
[stack hideBarsOnScroll:[withDefault.topBar.hideOnScroll getWithDefaultValue:NO]];
[stack setRootBackgroundImage:[withDefault.rootBackgroundImage getWithDefaultValue:nil]];
[stack setNavigationBarTestId:[withDefault.topBar.testID getWithDefaultValue:nil]];
[stack setNavigationBarVisible:[withDefault.topBar.visible getWithDefaultValue:YES] animated:[withDefault.topBar.animate getWithDefaultValue:YES]];
[stack hideBarsOnScroll:[withDefault.topBar.hideOnScroll getWithDefaultValue:NO]];

[_topBarPresenter applyOptions:withDefault.topBar];

[stack setNavigationBarBlur:[withDefault.topBar.background.blur getWithDefaultValue:NO]];
[stack setNavigationBarLargeTitleVisible:[withDefault.topBar.largeTitle.visible getWithDefaultValue:NO]];
[stack setNavigationBarClipsToBounds:[withDefault.topBar.background.clipToBounds getWithDefaultValue:NO]];
[stack setBackButtonColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil]];
[stack setNavigationBarClipsToBounds:[withDefault.topBar.background.clipToBounds getWithDefaultValue:NO]];
[stack setBackButtonColor:[withDefault.topBar.backButton.color getWithDefaultValue:nil]];
}

- (void)applyOptionsOnViewDidLayoutSubviews:(RNNNavigationOptions *)options {
RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
if (withDefault.topBar.background.component.name.hasValue) {
[self presentBackgroundComponent];
}
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]];
RNNStackController* navigationController = self.stackController;
[navigationController setNavigationBarLargeTitleVisible:[withDefault.topBar.largeTitle.visible getWithDefaultValue:NO]];
RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
RNNStackController* navigationController = self.stackController;
[navigationController setNavigationBarLargeTitleVisible:[withDefault.topBar.largeTitle.visible getWithDefaultValue:NO]];
[_topBarPresenter applyOptionsBeforePopping:options.topBar];
}

- (void)mergeOptions:(RNNNavigationOptions *)options resolvedOptions:(RNNNavigationOptions *)resolvedOptions {
[super mergeOptions:options resolvedOptions:resolvedOptions];
RNNStackController* stack = self.stackController;

if (options.popGesture.hasValue) {
[_interactivePopGestureDelegate setEnabled:options.popGesture.get];
}
if (options.rootBackgroundImage.hasValue) {
[stack setRootBackgroundImage:options.rootBackgroundImage.get];
}
if (options.topBar.testID.hasValue) {
[stack setNavigationBarTestId:options.topBar.testID.get];
}
if (options.topBar.visible.hasValue) {
[stack setNavigationBarVisible:options.topBar.visible.get animated:[options.topBar.animate getWithDefaultValue:YES]];
}
if (options.topBar.hideOnScroll.hasValue) {
[stack hideBarsOnScroll:[options.topBar.hideOnScroll get]];
}
if (options.topBar.barStyle.hasValue) {
[stack setBarStyle:[RCTConvert UIBarStyle:options.topBar.barStyle.get]];
}
if (options.topBar.background.clipToBounds.hasValue) {
[stack setNavigationBarClipsToBounds:[options.topBar.background.clipToBounds get]];
}
if (options.topBar.background.blur.hasValue) {
[stack setNavigationBarBlur:[options.topBar.background.blur get]];
}
if (options.topBar.largeTitle.visible.hasValue) {
[stack setNavigationBarLargeTitleVisible:options.topBar.largeTitle.visible.get];
}
if (options.topBar.backButton.color.hasValue) {
[stack setBackButtonColor:options.topBar.backButton.color.get];
}

if (options.topBar.background.component.name.hasValue) {
[self setCustomNavigationComponentBackground:options perform:nil];
}
RNNStackController* stack = self.stackController;

if (options.popGesture.hasValue) {
[_interactivePopGestureDelegate setEnabled:options.popGesture.get];
}
if (options.rootBackgroundImage.hasValue) {
[stack setRootBackgroundImage:options.rootBackgroundImage.get];
}
if (options.topBar.testID.hasValue) {
[stack setNavigationBarTestId:options.topBar.testID.get];
}
if (options.topBar.visible.hasValue) {
[stack setNavigationBarVisible:options.topBar.visible.get animated:[options.topBar.animate getWithDefaultValue:YES]];
}
if (options.topBar.hideOnScroll.hasValue) {
[stack hideBarsOnScroll:[options.topBar.hideOnScroll get]];
}
if (options.topBar.barStyle.hasValue) {
[stack setBarStyle:[RCTConvert UIBarStyle:options.topBar.barStyle.get]];
}
if (options.topBar.background.clipToBounds.hasValue) {
[stack setNavigationBarClipsToBounds:[options.topBar.background.clipToBounds get]];
}
if (options.topBar.background.blur.hasValue) {
[stack setNavigationBarBlur:[options.topBar.background.blur get]];
}
if (options.topBar.largeTitle.visible.hasValue) {
[stack setNavigationBarLargeTitleVisible:options.topBar.largeTitle.visible.get];
}
if (options.topBar.backButton.color.hasValue) {
[stack setBackButtonColor:options.topBar.backButton.color.get];
}

if (options.topBar.background.component.name.hasValue) {
[self setCustomNavigationComponentBackground:options perform:nil];
}

RNNNavigationOptions * withDefault = (RNNNavigationOptions *) [[options mergeInOptions:resolvedOptions] withDefault:[self defaultOptions]];
[_topBarPresenter mergeOptions:options.topBar defaultOptions:withDefault.topBar];
[_topBarPresenter mergeOptions:options.topBar withDefault:withDefault.topBar];
}

- (void)renderComponents:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(dispatch_get_main_queue(), ^{
[self setCustomNavigationComponentBackground:options perform:^{
dispatch_group_leave(group);
}];
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_main_queue(), ^{
if (readyBlock) {
readyBlock();
}
});
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(dispatch_get_main_queue(), ^{
[self setCustomNavigationComponentBackground:options perform:^{
dispatch_group_leave(group);
}];
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_main_queue(), ^{
if (readyBlock) {
readyBlock();
}
});
});
}

- (void)setCustomNavigationComponentBackground:(RNNNavigationOptions *)options perform:(RNNReactViewReadyCompletionBlock)readyBlock {
RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
RNNStackController* stack = self.stackController;
if (![withDefault.topBar.background.component.waitForRender getWithDefaultValue:NO] && readyBlock) {
readyBlock();
readyBlock = nil;
}

if (withDefault.topBar.background.component.name.hasValue) {
NSString* currentChildComponentId = [stack getCurrentChild].layoutInfo.componentId;
_topBarBackgroundReactView = [_componentRegistry createComponentIfNotExists:withDefault.topBar.background.component parentComponentId:currentChildComponentId componentType:RNNComponentTypeTopBarBackground reactViewReadyBlock:readyBlock];
} else {
RNNStackController* stack = self.stackController;
if (![withDefault.topBar.background.component.waitForRender getWithDefaultValue:NO] && readyBlock) {
readyBlock();
readyBlock = nil;
}

if (withDefault.topBar.background.component.name.hasValue) {
NSString* currentChildComponentId = [stack getCurrentChild].layoutInfo.componentId;
_topBarBackgroundReactView = [_componentRegistry createComponentIfNotExists:withDefault.topBar.background.component parentComponentId:currentChildComponentId componentType:RNNComponentTypeTopBarBackground reactViewReadyBlock:readyBlock];
} else {
[_topBarBackgroundReactView componentDidDisappear];
[_customTopBarBackground removeFromSuperview];
_customTopBarBackground = nil;
if (readyBlock) {
readyBlock();
}
}
[_customTopBarBackground removeFromSuperview];
_customTopBarBackground = nil;
if (readyBlock) {
readyBlock();
}
}
}

- (void)presentBackgroundComponent {
RNNStackController* stack = self.stackController;
if (_customTopBarBackground) {
[_customTopBarBackground removeFromSuperview];
}
_customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:stack.navigationBar.bounds subView:_topBarBackgroundReactView alignment:@"fill"];
[stack.navigationBar insertSubview:_customTopBarBackground atIndex:1];
RNNStackController* stack = self.stackController;
if (_customTopBarBackground) {
[_customTopBarBackground removeFromSuperview];
}
_customTopBarBackground = [[RNNCustomTitleView alloc] initWithFrame:stack.navigationBar.bounds subView:_topBarBackgroundReactView alignment:@"fill"];
[stack.navigationBar insertSubview:_customTopBarBackground atIndex:1];
[_topBarBackgroundReactView componentDidAppear];
}

- (void)dealloc {
[_componentRegistry removeComponent:self.boundComponentId];
[_componentRegistry removeComponent:self.boundComponentId];
}

@end
3 changes: 1 addition & 2 deletions lib/ios/RNNTitleOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
@property (nonatomic, strong) Color* color;
@property (nonatomic, strong) Text* fontFamily;
@property (nonatomic, strong) Text* fontWeight;

@property (nonatomic, strong) RNNComponentOptions* component;
@property (nonatomic, strong) Text* componentAlignment;

@property (nonatomic, strong) NSDictionary* fontAttributes;
- (BOOL)hasValue;

@end
26 changes: 15 additions & 11 deletions lib/ios/RNNTitleOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
@implementation RNNTitleOptions

- (instancetype)initWithDict:(NSDictionary *)dict {
self = [super init];

self.text = [TextParser parse:dict key:@"text"];
self.fontFamily = [TextParser parse:dict key:@"fontFamily"];
self.fontSize = [NumberParser parse:dict key:@"fontSize"];
self.fontWeight = [TextParser parse:dict key:@"fontWeight"];
self.color = [ColorParser parse:dict key:@"color"];

self.component = [[RNNComponentOptions alloc] initWithDict:dict[@"component"]];

return self;
self = [super init];

self.text = [TextParser parse:dict key:@"text"];
self.fontFamily = [TextParser parse:dict key:@"fontFamily"];
self.fontSize = [NumberParser parse:dict key:@"fontSize"];
self.fontWeight = [TextParser parse:dict key:@"fontWeight"];
self.color = [ColorParser parse:dict key:@"color"];

self.component = [[RNNComponentOptions alloc] initWithDict:dict[@"component"]];

return self;
}

- (BOOL)hasValue {
return self.text.hasValue || self.fontFamily.hasValue || self.fontSize.hasValue || self.fontWeight.hasValue || self.color.hasValue || self.component.hasValue || self.componentAlignment.hasValue;
}

@end
2 changes: 1 addition & 1 deletion lib/ios/TopBarPresenter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

- (void)applyOptionsBeforePopping:(RNNTopBarOptions *)options;

- (void)mergeOptions:(RNNTopBarOptions *)options defaultOptions:(RNNTopBarOptions *)defaultOptions;
- (void)mergeOptions:(RNNTopBarOptions *)options withDefault:(RNNTopBarOptions *)defaultOptions;

- (instancetype)initWithNavigationController:(UINavigationController *)boundNavigationController;

Expand Down
8 changes: 5 additions & 3 deletions lib/ios/TopBarPresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ - (void)applyOptionsBeforePopping:(RNNTopBarOptions *)options {
[self setLargeTitleAttributes:options.largeTitle];
}

- (void)mergeOptions:(RNNTopBarOptions *)options defaultOptions:(RNNTopBarOptions *)defaultOptions {
- (void)mergeOptions:(RNNTopBarOptions *)options withDefault:(RNNTopBarOptions *)withDefault {
if (options.background.color.hasValue) {
[self setBackgroundColor:options.background.color.get];
}
Expand All @@ -43,10 +43,12 @@ - (void)mergeOptions:(RNNTopBarOptions *)options defaultOptions:(RNNTopBarOption
[self setLargeTitleAttributes:largeTitleOptions];
}

[self setTitleAttributes:options.title];
if (options.title.hasValue) {
[self setTitleAttributes:withDefault.title];
}

if (options.backButton.hasValue) {
[self setBackButtonIcon:[defaultOptions.backButton.icon getWithDefaultValue:nil] withColor:[defaultOptions.backButton.color getWithDefaultValue:nil] title:[defaultOptions.backButton.title getWithDefaultValue:nil] showTitle:[defaultOptions.backButton.showTitle getWithDefaultValue:YES]];
[self setBackButtonIcon:[withDefault.backButton.icon getWithDefaultValue:nil] withColor:[withDefault.backButton.color getWithDefaultValue:nil] title:[withDefault.backButton.title getWithDefaultValue:nil] showTitle:[withDefault.backButton.showTitle getWithDefaultValue:YES]];
}
}

Expand Down
36 changes: 36 additions & 0 deletions playground/ios/NavigationTests/TopBarAppearancePresenterTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import <ReactNativeNavigation/TopBarAppearancePresenter.h>
#import "UIViewController+RNNOptions.h"
#import <ReactNativeNavigation/RNNStackController.h>

@interface TopBarAppearancePresenterTest : XCTestCase

@end

@implementation TopBarAppearancePresenterTest {
TopBarAppearancePresenter* _uut;
RNNStackController* _stack;
}

- (void)setUp {
[super setUp];
_stack = [[RNNStackController alloc] initWithLayoutInfo:nil creator:nil options:[[RNNNavigationOptions alloc] initEmptyOptions] defaultOptions:[[RNNNavigationOptions alloc] initEmptyOptions] presenter:_uut eventEmitter:nil childViewControllers:@[]];
_uut = [[TopBarAppearancePresenter alloc] initWithNavigationController:_stack];
}

- (void)testMergeOptions_shouldMergeWithDefault {
RNNNavigationOptions* mergeOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
RNNNavigationOptions* defaultOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
defaultOptions.topBar.title.color = [Color withColor:UIColor.redColor];

mergeOptions.topBar.title.fontSize = [Number withValue:@(21)];
RNNNavigationOptions* withDefault = [mergeOptions withDefault:defaultOptions];
[_uut mergeOptions:mergeOptions.topBar withDefault:withDefault.topBar];
XCTAssertEqual(_stack.navigationBar.standardAppearance.titleTextAttributes[NSForegroundColorAttributeName], UIColor.redColor);
UIFont* font = _stack.navigationBar.standardAppearance.titleTextAttributes[NSFontAttributeName];
XCTAssertEqual(font.pointSize, 21);
}


@end
Loading

0 comments on commit af34fb3

Please sign in to comment.