Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ class TabScreenViewManager :
view.iconResourceName = value
}

override fun setOrientation(
view: TabScreen,
value: String?,
) = Unit

companion object {
const val REACT_CLASS = "RNSBottomTabsScreen"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case "title":
mViewManager.setTitle(view, value == null ? null : (String) value);
break;
case "orientation":
mViewManager.setOrientation(view, (String) value);
break;
case "iconResourceName":
mViewManager.setIconResourceName(view, value == null ? null : (String) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public interface RNSBottomTabsScreenManagerInterface<T extends View> {
void setTabBarItemIconColor(T view, @Nullable Integer value);
void setTabBarItemBadgeBackgroundColor(T view, @Nullable Integer value);
void setTitle(T view, @Nullable String value);
void setOrientation(T view, @Nullable String value);
void setIconResourceName(T view, @Nullable String value);
void setTabBarItemBadgeTextColor(T view, @Nullable Integer value);
void setIconType(T view, @Nullable String value);
Expand Down
3 changes: 3 additions & 0 deletions apps/src/tests/TestBottomTabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const TAB_CONFIGS: TabConfiguration[] = [
tabBarItemIconColor: Colors.RedDark120,
iconResourceName: 'sym_call_missed', // Android specific
title: 'Tab2',
orientation: 'landscape',
},
component: Tab2,
},
Expand All @@ -72,6 +73,7 @@ const TAB_CONFIGS: TabConfiguration[] = [
},
iconResourceName: 'sym_action_email', // Android specific
title: 'Tab3',
orientation: 'portrait',
},
component: Tab3,
},
Expand All @@ -87,6 +89,7 @@ const TAB_CONFIGS: TabConfiguration[] = [
iconResourceName: 'sym_action_chat', // Android specific
title: 'Tab4',
badgeValue: '',
orientation: 'portrait',
},
component: Tab4,
},
Expand Down
3 changes: 2 additions & 1 deletion apps/src/tests/TestBottomTabs/tabs/Tab4.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,14 @@ export function Tab4() {
<Stack.Screen
name="Screen1"
component={Screen1}
options={{ headerTransparent: true }}
options={{ headerTransparent: true, orientation: 'landscape' }}
/>
<Stack.Screen
name="Screen2"
component={Screen2}
options={{
headerLargeTitle: true,
orientation: 'default',
}}
/>
<Stack.Screen
Expand Down
12 changes: 12 additions & 0 deletions ios/RNSEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,15 @@ typedef NS_ENUM(NSInteger, RNSTabBarMinimizeBehavior) {
RNSTabBarMinimizeBehaviorOnScrollUp,
};
#endif

typedef NS_ENUM(NSInteger, RNSOrientation) {
RNSOrientationInherit,
RNSOrientationAll,
RNSOrientationAllButUpsideDown,
RNSOrientationPortrait,
RNSOrientationPortraitUp,
RNSOrientationPortraitDown,
RNSOrientationLandscape,
RNSOrientationLandscapeLeft,
RNSOrientationLandscapeRight,
};
11 changes: 11 additions & 0 deletions ios/RNSOrientationProviding.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#import "RNSEnums.h"

NS_ASSUME_NONNULL_BEGIN

@protocol RNSOrientationProviding

- (RNSOrientation)evaluateOrientation;

@end

NS_ASSUME_NONNULL_END
13 changes: 11 additions & 2 deletions ios/RNSScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#import "RNSScreenContentWrapper.h"
#import "RNSScrollViewBehaviorOverriding.h"

#if !TARGET_OS_TV
#import "RNSOrientationProviding.h"
#endif // !TARGET_OS_TV

#if RCT_NEW_ARCH_ENABLED
#import <React/RCTViewComponentView.h>
#else
Expand Down Expand Up @@ -33,8 +37,13 @@ namespace react = facebook::react;

@class RNSScreenView;

@interface RNSScreen : UIViewController <RNSViewControllerDelegate>

@interface RNSScreen : UIViewController <
RNSViewControllerDelegate
#if !TARGET_OS_TV
,
RNSOrientationProviding
#endif // !TARGET_OS_TV
>
- (instancetype)initWithView:(UIView *)view;
- (UIViewController *)findChildVCForConfigAndTrait:(RNSWindowTrait)trait includingModals:(BOOL)includingModals;
- (BOOL)hasNestedStack;
Expand Down
21 changes: 21 additions & 0 deletions ios/RNSScreen.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#import <React/RCTUIManager.h>
#import <React/RCTUIManagerUtils.h>

#import "RNSConversions.h"
#import "RNSScreenFooter.h"
#import "RNSScreenStack.h"
#import "RNSScreenStackHeaderConfig.h"
Expand Down Expand Up @@ -1979,6 +1980,26 @@ - (void)presentViewController:(UIViewController *)viewControllerToPresent
[super presentViewController:viewControllerToPresent animated:flag completion:completion];
}

#pragma mark - RNSOrientationProviding

#if !TARGET_OS_TV

- (RNSOrientation)evaluateOrientation
{
if ([self.childViewControllers.lastObject respondsToSelector:@selector(evaluateOrientation)]) {
id<RNSOrientationProviding> child = static_cast<id<RNSOrientationProviding>>(self.childViewControllers.lastObject);
RNSOrientation childOrientation = [child evaluateOrientation];

if (childOrientation != RNSOrientationInherit) {
return childOrientation;
}
}

return rnscreens::conversion::RNSOrientationFromUIInterfaceOrientationMask([self supportedInterfaceOrientations]);
}

#endif // !TARGET_OS_TV

#ifdef RCT_NEW_ARCH_ENABLED
#pragma mark - Fabric specific

Expand Down
8 changes: 8 additions & 0 deletions ios/RNSScreenStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#import "RNSBottomTabsSpecialEffectsSupporting.h"
#import "RNSScreenContainer.h"

#if !TARGET_OS_TV
#import "RNSOrientationProviding.h"
#endif // !TARGET_OS_TV

#ifdef RNS_GAMMA_ENABLED
#import "RNSFrameCorrectionProvider.h"
#endif // RNS_GAMMA_ENABLED
Expand All @@ -17,6 +21,10 @@ NS_ASSUME_NONNULL_BEGIN
@interface RNSNavigationController : UINavigationController <
RNSViewControllerDelegate,
RNSBottomTabsSpecialEffectsSupporting
#if !TARGET_OS_TV
,
RNSOrientationProviding
#endif // !TARGET_OS_TV
#ifdef RNS_GAMMA_ENABLED
,
RNSFrameCorrectionProvider
Expand Down
14 changes: 14 additions & 0 deletions ios/RNSScreenStack.mm
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ - (UIInterfaceOrientationMask)supportedInterfaceOrientations
return [self topViewController].supportedInterfaceOrientations;
}

#if !TARGET_OS_TV

- (RNSOrientation)evaluateOrientation
{
if ([self.topViewController respondsToSelector:@selector(evaluateOrientation)]) {
id<RNSOrientationProviding> top = static_cast<id<RNSOrientationProviding>>(self.topViewController);
return [top evaluateOrientation];
}

return RNSOrientationInherit;
}

#endif // !TARGET_OS_TV

- (UIViewController *)childViewControllerForHomeIndicatorAutoHidden
{
return [self topViewController];
Expand Down
26 changes: 24 additions & 2 deletions ios/UIViewController+RNScreens.mm
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#import "RNSConversions.h"
#import "RNSEnums.h"
#import "RNSOrientationProviding.h"
#import "RNSScreenContainer.h"
#import "UIViewController+RNScreens.h"

Expand Down Expand Up @@ -27,8 +30,18 @@ - (UIStatusBarAnimation)reactNativeScreensPreferredStatusBarUpdateAnimation

- (UIInterfaceOrientationMask)reactNativeScreensSupportedInterfaceOrientations
{
UIViewController *childVC = [self findChildRNSScreensViewController];
return childVC ? childVC.supportedInterfaceOrientations : [self reactNativeScreensSupportedInterfaceOrientations];
id<RNSOrientationProviding> childOrientationProvidingVC = [self findChildRNSOrientationProvidingViewController];

if (childOrientationProvidingVC != nil) {
RNSOrientation orientation = [childOrientationProvidingVC evaluateOrientation];
if (orientation == RNSOrientationInherit) {
return [[UIApplication sharedApplication] supportedInterfaceOrientationsForWindow:self.view.window];
}

return rnscreens::conversion::UIInterfaceOrientationMaskFromRNSOrientation(orientation);
}

return [self reactNativeScreensSupportedInterfaceOrientations];
}

- (UIViewController *)reactNativeScreensChildViewControllerForHomeIndicatorAutoHidden
Expand All @@ -37,6 +50,15 @@ - (UIViewController *)reactNativeScreensChildViewControllerForHomeIndicatorAutoH
return childVC ?: [self reactNativeScreensChildViewControllerForHomeIndicatorAutoHidden];
}

- (id<RNSOrientationProviding>)findChildRNSOrientationProvidingViewController
{
UIViewController *lastViewController = [[self childViewControllers] lastObject];
if ([lastViewController respondsToSelector:@selector(evaluateOrientation)]) {
return static_cast<id<RNSOrientationProviding>>(lastViewController);
}
return nil;
}

- (UIViewController *)findChildRNSScreensViewController
{
UIViewController *lastViewController = [[self childViewControllers] lastObject];
Expand Down
2 changes: 2 additions & 0 deletions ios/bottom-tabs/RCTConvert+RNSBottomTabs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ NS_ASSUME_NONNULL_BEGIN

+ (RNSBottomTabsIconType)RNSBottomTabsIconType:(nonnull id)json;

+ (RNSOrientation)RNSOrientation:(nonnull id)json;

@end

NS_ASSUME_NONNULL_END
Expand Down
16 changes: 16 additions & 0 deletions ios/bottom-tabs/RCTConvert+RNSBottomTabs.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@ + (UIOffset)UIOffset:(id)json;
RNSTabBarMinimizeBehaviorAutomatic,
integerValue)

RCT_ENUM_CONVERTER(
RNSOrientation,
(@{
@"inherit" : @(RNSOrientationInherit),
@"all" : @(RNSOrientationAll),
@"allButUpsideDown" : @(RNSOrientationAllButUpsideDown),
@"portrait" : @(RNSOrientationPortrait),
@"portraitUp" : @(RNSOrientationPortraitUp),
@"portraitDown" : @(RNSOrientationPortraitDown),
@"landscape" : @(RNSOrientationLandscape),
@"landscapeLeft" : @(RNSOrientationLandscapeLeft),
@"landscapeRight" : @(RNSOrientationLandscapeRight),
}),
RNSOrientationInherit,
integerValue)

@end

#endif // !RCT_NEW_ARCH_ENABLED
1 change: 1 addition & 0 deletions ios/bottom-tabs/RNSBottomTabsScreenComponentView.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, nullable) UIColor *tabBarItemBadgeBackgroundColor;

@property (nonatomic, nullable) NSString *title;
@property (nonatomic, readonly) RNSOrientation orientation;

@property (nonatomic) BOOL shouldUseRepeatedTabSelectionPopToRootSpecialEffect;
@property (nonatomic) BOOL shouldUseRepeatedTabSelectionScrollToTopSpecialEffect;
Expand Down
25 changes: 25 additions & 0 deletions ios/bottom-tabs/RNSBottomTabsScreenComponentView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ @implementation RNSBottomTabsScreenComponentView {
BOOL _isOverrideScrollViewContentInsetAdjustmentBehaviorSet;
#if !RCT_NEW_ARCH_ENABLED
BOOL _tabItemNeedsAppearanceUpdate;
BOOL _tabScreenOrientationNeedsUpdate;
#endif // !RCT_NEW_ARCH_ENABLED
}

Expand All @@ -56,6 +57,7 @@ - (void)initState

#if !RCT_NEW_ARCH_ENABLED
_tabItemNeedsAppearanceUpdate = NO;
_tabScreenOrientationNeedsUpdate = NO;
#endif

// This is a temporary workaround to avoid UIScrollEdgeEffect glitch
Expand All @@ -72,6 +74,7 @@ - (void)resetProps
_badgeValue = nil;
_title = nil;
_tabBarBlurEffect = RNSBlurEffectStyleSystemDefault;
_orientation = RNSOrientationInherit;
_tabBarBackgroundColor = nil;

_tabBarItemTitleFontFamily = nil;
Expand Down Expand Up @@ -152,12 +155,19 @@ - (void)updateProps:(const facebook::react::Props::Shared &)props
const auto &newComponentProps = *std::static_pointer_cast<const react::RNSBottomTabsScreenProps>(props);

bool tabItemNeedsAppearanceUpdate{false};
bool tabScreenOrientationNeedsUpdate{false};

if (newComponentProps.title != oldComponentProps.title) {
_title = RCTNSStringFromStringNilIfEmpty(newComponentProps.title);
_controller.title = _title;
}

if (newComponentProps.orientation != oldComponentProps.orientation) {
_orientation =
rnscreens::conversion::RNSOrientationFromRNSBottomTabsScreenOrientation(newComponentProps.orientation);
tabScreenOrientationNeedsUpdate = YES;
}

if (newComponentProps.tabKey != oldComponentProps.tabKey) {
RCTAssert(!newComponentProps.tabKey.empty(), @"[RNScreens] tabKey must not be empty!");
_tabKey = RCTNSStringFromString(newComponentProps.tabKey);
Expand Down Expand Up @@ -291,6 +301,10 @@ - (void)updateProps:(const facebook::react::Props::Shared &)props
[_controller tabItemAppearanceHasChanged];
}

if (tabScreenOrientationNeedsUpdate) {
[_controller tabScreenOrientationHasChanged];
}

[super updateProps:props oldProps:oldProps];
}

Expand Down Expand Up @@ -353,6 +367,11 @@ - (void)didSetProps:(NSArray<NSString *> *)changedProps
[_controller tabItemAppearanceHasChanged];
_tabItemNeedsAppearanceUpdate = NO;
}

if (_tabScreenOrientationNeedsUpdate) {
[_controller tabScreenOrientationHasChanged];
_tabScreenOrientationNeedsUpdate = NO;
}
}

#pragma mark - LEGACY prop setters
Expand Down Expand Up @@ -480,6 +499,12 @@ - (void)setOverrideScrollViewContentInsetAdjustmentBehavior:(BOOL)overrideScroll
// when the prop is undefined in JS and default value is used instead of calling this setter.
}

- (void)setOrientation:(RNSOrientation)orientation
{
_orientation = orientation;
_tabScreenOrientationNeedsUpdate = YES;
}

- (void)setOnWillAppear:(RCTDirectEventBlock)onWillAppear
{
[self.reactEventEmitter setOnWillAppear:onWillAppear];
Expand Down
1 change: 1 addition & 0 deletions ios/bottom-tabs/RNSBottomTabsScreenComponentViewManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ - (UIView *)view

RCT_REMAP_VIEW_PROPERTY(isFocused, isSelectedScreen, BOOL);
RCT_EXPORT_VIEW_PROPERTY(title, NSString);
RCT_EXPORT_VIEW_PROPERTY(orientation, RNSOrientation);
RCT_EXPORT_VIEW_PROPERTY(badgeValue, NSString);
RCT_EXPORT_VIEW_PROPERTY(tabBarBackgroundColor, UIColor);
RCT_EXPORT_VIEW_PROPERTY(tabBarBlurEffect, RNSBlurEffectStyle);
Expand Down
Loading
Loading