mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
2160377574
Summary: Refs: [0.62 release](https://reactnative.dev/blog/#moving-apple-tv-to-react-native-tvos), https://github.com/facebook/react-native/issues/28706, https://github.com/facebook/react-native/issues/28743, https://github.com/facebook/react-native/issues/29018 This PR removes most of the tvOS remnants in the code. Most of the changes are related to the tvOS platform removal from `.podspec` files, tvOS specific conditionals removal (Obj-C + JS) or tvOS CI/testing pipeline related code. In addition to the changes listed above I have removed the deprecated `Platform.isTVOS` method. I'm not sure how `Platform.isTV` method is correlated with Android TV devices support which is technically not deprecated in the core so I left this method untouched for now. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> * **[Internal] [Removed]** - remove most of tvOS remnants from the code: * `TVEventHandler`, `TVTouchable`, `RCTTVView`, `RCTTVRemoteHandler` and `RCTTVNavigationEventEmitter` * **[Internal] [Removed]** - remove `TARGET_TV_OS` flag and all the usages * **[iOS] [Removed]** - remove deprecated `Platform.isTVOS` method * **[iOS] [Removed]** - remove deprecated and TV related props from View: * `isTVSelectable`, `hasTVPreferredFocus` and `tvParallaxProperties` * **[iOS] [Removed]** - remove `BackHandler` utility implementation Pull Request resolved: https://github.com/facebook/react-native/pull/29407 Test Plan: Local tests (and iOS CI run) do not yield any errors, but I'm not sure how the CI pipeline would react to those changes. That is the reason why this PR is being posted as Draft. Some tweaks and code adjustment could be required. Reviewed By: PeteTheHeat Differential Revision: D22619441 Pulled By: shergin fbshipit-source-id: 9aaf3840c5e8bd469c2cfcfa7c5b441ef71b30b6
204 lines
6.1 KiB
Objective-C
204 lines
6.1 KiB
Objective-C
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#import "RCTModalHostView.h"
|
|
|
|
#import <UIKit/UIKit.h>
|
|
|
|
#import "RCTAssert.h"
|
|
#import "RCTBridge.h"
|
|
#import "RCTModalHostViewController.h"
|
|
#import "RCTTouchHandler.h"
|
|
#import "RCTUIManager.h"
|
|
#import "RCTUtils.h"
|
|
#import "UIView+React.h"
|
|
|
|
@implementation RCTModalHostView {
|
|
__weak RCTBridge *_bridge;
|
|
BOOL _isPresented;
|
|
RCTModalHostViewController *_modalViewController;
|
|
RCTTouchHandler *_touchHandler;
|
|
UIView *_reactSubview;
|
|
UIInterfaceOrientation _lastKnownOrientation;
|
|
}
|
|
|
|
RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
|
|
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : coder)
|
|
|
|
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
|
{
|
|
if ((self = [super initWithFrame:CGRectZero])) {
|
|
_bridge = bridge;
|
|
_modalViewController = [RCTModalHostViewController new];
|
|
UIView *containerView = [UIView new];
|
|
containerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
|
|
_modalViewController.view = containerView;
|
|
_touchHandler = [[RCTTouchHandler alloc] initWithBridge:bridge];
|
|
_isPresented = NO;
|
|
|
|
__weak typeof(self) weakSelf = self;
|
|
_modalViewController.boundsDidChangeBlock = ^(CGRect newBounds) {
|
|
[weakSelf notifyForBoundsChange:newBounds];
|
|
};
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)notifyForBoundsChange:(CGRect)newBounds
|
|
{
|
|
if (_reactSubview && _isPresented) {
|
|
[_bridge.uiManager setSize:newBounds.size forView:_reactSubview];
|
|
[self notifyForOrientationChange];
|
|
}
|
|
}
|
|
|
|
- (void)notifyForOrientationChange
|
|
{
|
|
if (!_onOrientationChange) {
|
|
return;
|
|
}
|
|
|
|
UIInterfaceOrientation currentOrientation = [RCTSharedApplication() statusBarOrientation];
|
|
if (currentOrientation == _lastKnownOrientation) {
|
|
return;
|
|
}
|
|
_lastKnownOrientation = currentOrientation;
|
|
|
|
BOOL isPortrait = currentOrientation == UIInterfaceOrientationPortrait ||
|
|
currentOrientation == UIInterfaceOrientationPortraitUpsideDown;
|
|
NSDictionary *eventPayload = @{
|
|
@"orientation" : isPortrait ? @"portrait" : @"landscape",
|
|
};
|
|
_onOrientationChange(eventPayload);
|
|
}
|
|
|
|
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
|
|
{
|
|
RCTAssert(_reactSubview == nil, @"Modal view can only have one subview");
|
|
[super insertReactSubview:subview atIndex:atIndex];
|
|
[_touchHandler attachToView:subview];
|
|
|
|
[_modalViewController.view insertSubview:subview atIndex:0];
|
|
_reactSubview = subview;
|
|
}
|
|
|
|
- (void)removeReactSubview:(UIView *)subview
|
|
{
|
|
RCTAssert(subview == _reactSubview, @"Cannot remove view other than modal view");
|
|
// Superclass (category) removes the `subview` from actual `superview`.
|
|
[super removeReactSubview:subview];
|
|
[_touchHandler detachFromView:subview];
|
|
_reactSubview = nil;
|
|
}
|
|
|
|
- (void)didUpdateReactSubviews
|
|
{
|
|
// Do nothing, as subview (singular) is managed by `insertReactSubview:atIndex:`
|
|
}
|
|
|
|
- (void)dismissModalViewController
|
|
{
|
|
if (_isPresented) {
|
|
[_delegate dismissModalHostView:self withViewController:_modalViewController animated:[self hasAnimationType]];
|
|
_isPresented = NO;
|
|
}
|
|
}
|
|
|
|
- (void)didMoveToWindow
|
|
{
|
|
[super didMoveToWindow];
|
|
|
|
// In the case where there is a LayoutAnimation, we will be reinserted into the view hierarchy but only for aesthetic
|
|
// purposes. In such a case, we should NOT represent the <Modal>.
|
|
if (!self.userInteractionEnabled && ![self.superview.reactSubviews containsObject:self]) {
|
|
return;
|
|
}
|
|
|
|
if (!_isPresented && self.window) {
|
|
RCTAssert(self.reactViewController, @"Can't present modal view controller without a presenting view controller");
|
|
|
|
_modalViewController.supportedInterfaceOrientations = [self supportedOrientationsMask];
|
|
|
|
if ([self.animationType isEqualToString:@"fade"]) {
|
|
_modalViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
|
|
} else if ([self.animationType isEqualToString:@"slide"]) {
|
|
_modalViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
|
|
}
|
|
if (self.presentationStyle != UIModalPresentationNone) {
|
|
_modalViewController.modalPresentationStyle = self.presentationStyle;
|
|
}
|
|
[_delegate presentModalHostView:self withViewController:_modalViewController animated:[self hasAnimationType]];
|
|
_isPresented = YES;
|
|
}
|
|
}
|
|
|
|
- (void)didMoveToSuperview
|
|
{
|
|
[super didMoveToSuperview];
|
|
|
|
if (_isPresented && !self.superview) {
|
|
[self dismissModalViewController];
|
|
}
|
|
}
|
|
|
|
- (void)invalidate
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[self dismissModalViewController];
|
|
});
|
|
}
|
|
|
|
- (BOOL)isTransparent
|
|
{
|
|
return _modalViewController.modalPresentationStyle == UIModalPresentationOverFullScreen;
|
|
}
|
|
|
|
- (BOOL)hasAnimationType
|
|
{
|
|
return ![self.animationType isEqualToString:@"none"];
|
|
}
|
|
|
|
- (void)setTransparent:(BOOL)transparent
|
|
{
|
|
if (self.isTransparent != transparent) {
|
|
return;
|
|
}
|
|
|
|
_modalViewController.modalPresentationStyle =
|
|
transparent ? UIModalPresentationOverFullScreen : UIModalPresentationFullScreen;
|
|
}
|
|
|
|
- (UIInterfaceOrientationMask)supportedOrientationsMask
|
|
{
|
|
if (_supportedOrientations.count == 0) {
|
|
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
|
|
return UIInterfaceOrientationMaskAll;
|
|
} else {
|
|
return UIInterfaceOrientationMaskPortrait;
|
|
}
|
|
}
|
|
|
|
UIInterfaceOrientationMask supportedOrientations = 0;
|
|
for (NSString *orientation in _supportedOrientations) {
|
|
if ([orientation isEqualToString:@"portrait"]) {
|
|
supportedOrientations |= UIInterfaceOrientationMaskPortrait;
|
|
} else if ([orientation isEqualToString:@"portrait-upside-down"]) {
|
|
supportedOrientations |= UIInterfaceOrientationMaskPortraitUpsideDown;
|
|
} else if ([orientation isEqualToString:@"landscape"]) {
|
|
supportedOrientations |= UIInterfaceOrientationMaskLandscape;
|
|
} else if ([orientation isEqualToString:@"landscape-left"]) {
|
|
supportedOrientations |= UIInterfaceOrientationMaskLandscapeLeft;
|
|
} else if ([orientation isEqualToString:@"landscape-right"]) {
|
|
supportedOrientations |= UIInterfaceOrientationMaskLandscapeRight;
|
|
}
|
|
}
|
|
return supportedOrientations;
|
|
}
|
|
|
|
@end
|