ssap_app/node_modules/react-native-screens/ios/bottom-tabs/RNSTabBarController.mm

251 lines
6.6 KiB
Plaintext

#import "RNSTabBarController.h"
#import <React/RCTAssert.h>
#import <React/RCTLog.h>
#import "RNSLog.h"
#import "RNSScreenWindowTraits.h"
@implementation RNSTabBarController {
NSArray<RNSTabsScreenViewController *> *_Nullable _tabScreenControllers;
#if !RCT_NEW_ARCH_ENABLED
BOOL _isControllerFlushBlockScheduled;
#endif // !RCT_NEW_ARCH_ENABLED
}
- (instancetype)init
{
if (self = [super init]) {
_tabScreenControllers = nil;
_tabBarAppearanceCoordinator = [RNSTabBarAppearanceCoordinator new];
_tabsHostComponentView = nil;
#if !RCT_NEW_ARCH_ENABLED
_isControllerFlushBlockScheduled = NO;
#endif // !RCT_NEW_ARCH_ENABLED
}
return self;
}
- (instancetype)initWithTabsHostComponentView:(nullable RNSBottomTabsHostComponentView *)tabsHostComponentView
{
if (self = [self init]) {
_tabsHostComponentView = tabsHostComponentView;
}
return self;
}
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
RNSLog(@"TabBar: %@ didSelectItem: %@", tabBar, item);
}
#pragma mark-- Signals
- (void)childViewControllersHaveChangedTo:(NSArray<RNSTabsScreenViewController *> *)reactChildControllers
{
_tabScreenControllers = reactChildControllers;
self.needsUpdateOfReactChildrenControllers = true;
}
- (void)setNeedsUpdateOfReactChildrenControllers:(bool)needsReactChildrenUpdate
{
_needsUpdateOfReactChildrenControllers = true;
self.needsUpdateOfSelectedTab = true;
#if !RCT_NEW_ARCH_ENABLED
[self scheduleControllerUpdateIfNeeded];
#endif // !RCT_NEW_ARCH_ENABLED
}
- (void)setNeedsUpdateOfSelectedTab:(bool)needsSelectedTabUpdate
{
_needsUpdateOfSelectedTab = needsSelectedTabUpdate;
if (needsSelectedTabUpdate) {
_needsOrientationUpdate = true;
}
#if !RCT_NEW_ARCH_ENABLED
[self scheduleControllerUpdateIfNeeded];
#endif // !RCT_NEW_ARCH_ENABLED
}
- (void)setNeedsUpdateOfTabBarAppearance:(bool)needsUpdateOfTabBarAppearance
{
_needsUpdateOfTabBarAppearance = needsUpdateOfTabBarAppearance;
#if !RCT_NEW_ARCH_ENABLED
[self scheduleControllerUpdateIfNeeded];
#endif // !RCT_NEW_ARCH_ENABLED
}
- (void)setNeedsOrientationUpdate:(bool)needsOrientationUpdate
{
_needsOrientationUpdate = needsOrientationUpdate;
#if !RCT_NEW_ARCH_ENABLED
[self scheduleControllerUpdateIfNeeded];
#endif // !RCT_NEW_ARCH_ENABLED
}
#pragma mark-- RNSReactTransactionObserving
- (void)reactMountingTransactionWillMount
{
RNSLog(@"TabBarCtrl mountintTransactionWillMount");
}
- (void)reactMountingTransactionDidMount
{
RNSLog(@"TabBarCtrl mountintTransactionDidMount running updates");
[self updateReactChildrenControllersIfNeeded];
[self updateSelectedViewControllerIfNeeded];
[self updateTabBarAppearanceIfNeeded];
[self updateOrientationIfNeeded];
}
#pragma mark-- Signals related
- (void)updateReactChildrenControllersIfNeeded
{
if (_needsUpdateOfReactChildrenControllers) {
[self updateReactChildrenControllers];
}
}
- (void)updateReactChildrenControllers
{
RNSLog(@"TabBarCtrl updateReactChildrenControllers");
_needsUpdateOfReactChildrenControllers = false;
if (_tabScreenControllers == nil) {
RCTLogWarn(@"[RNScreens] Attempt to update react children while the _updatedChildren array is nil!");
return;
}
[self setViewControllers:_tabScreenControllers animated:[[self viewControllers] count] != 0];
}
- (void)updateSelectedViewControllerIfNeeded
{
if (_needsUpdateOfSelectedTab) {
[self updateSelectedViewController];
}
}
- (void)updateSelectedViewController
{
RNSLog(@"TabBarCtrl updateSelectedViewController");
_needsUpdateOfSelectedTab = false;
#if !defined(NDEBUG)
[self assertExactlyOneFocusedTab];
#endif
RNSTabsScreenViewController *_Nullable selectedViewController = nil;
for (RNSTabsScreenViewController *tabViewController in self.viewControllers) {
RNSLog(
@"Update Selected View Controller [%ld] isFocused %d",
tabViewController.tabScreenComponentView.tag,
tabViewController.tabScreenComponentView.isSelectedScreen);
if (tabViewController.tabScreenComponentView.isSelectedScreen == true) {
selectedViewController = tabViewController;
break;
}
}
RCTAssert(selectedViewController != nil, @"[RNScreens] No selected view controller!");
RNSLog(@"Change selected view controller to: %@", selectedViewController);
[selectedViewController.tabScreenComponentView overrideScrollViewBehaviorInFirstDescendantChainIfNeeded];
[self setSelectedViewController:selectedViewController];
}
- (void)updateTabBarAppearanceIfNeeded
{
if (_needsUpdateOfTabBarAppearance) {
[self updateTabBarAppearance];
}
}
- (void)updateTabBarAppearance
{
RNSLog(@"TabBarCtrl updateTabBarAppearance");
_needsUpdateOfTabBarAppearance = false;
[_tabBarAppearanceCoordinator updateAppearanceOfTabBar:[self tabBar]
withHostComponentView:self.tabsHostComponentView
tabScreenControllers:_tabScreenControllers
imageLoader:[self.tabsHostComponentView reactImageLoader]];
}
#if !defined(NDEBUG)
- (void)assertExactlyOneFocusedTab
{
int selectedCount = 0;
for (RNSTabsScreenViewController *tabViewController in _tabScreenControllers) {
if (tabViewController.tabScreenComponentView.isSelectedScreen) {
++selectedCount;
}
}
RCTAssert(
selectedCount == 1, @"[RNScreens] Invariant violation. Expected exactly 1 focused tab, got: %d", selectedCount);
}
#endif
#if !RCT_NEW_ARCH_ENABLED
#pragma mark - LEGACY Paper scheduling methods
// TODO: These could be moved to separate scheduler class
- (void)scheduleControllerUpdateIfNeeded
{
if (_isControllerFlushBlockScheduled) {
return;
}
_isControllerFlushBlockScheduled = YES;
auto *__weak weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
auto *strongSelf = weakSelf;
if (strongSelf == nil) {
return;
}
strongSelf->_isControllerFlushBlockScheduled = NO;
[strongSelf reactMountingTransactionWillMount];
[strongSelf reactMountingTransactionDidMount];
});
}
#endif // !RCT_NEW_ARCH_ENABLED
- (void)updateOrientationIfNeeded
{
if (_needsOrientationUpdate) {
[self updateOrientation];
}
}
- (void)updateOrientation
{
_needsOrientationUpdate = false;
[RNSScreenWindowTraits enforceDesiredDeviceOrientation];
}
#pragma mark - RNSOrientationProviding
#if !TARGET_OS_TV
- (RNSOrientation)evaluateOrientation
{
if ([self.selectedViewController respondsToSelector:@selector(evaluateOrientation)]) {
id<RNSOrientationProviding> selected = static_cast<id<RNSOrientationProviding>>(self.selectedViewController);
return [selected evaluateOrientation];
}
return RNSOrientationInherit;
}
#endif // !TARGET_OS_TV
@end