Add support for nested components in legacy interop

Summary: changelog: [internal]

Reviewed By: ShikaSD

Differential Revision: D34173837

fbshipit-source-id: 09fbf12e9d8eb13a170ff92afff97f203d0ef805
This commit is contained in:
Samuel Susla 2022-02-18 07:10:07 -08:00 коммит произвёл Facebook GitHub Bot
Родитель 8bc324fd34
Коммит 5e88223d85
7 изменённых файлов: 125 добавлений и 35 удалений

Просмотреть файл

@ -15,3 +15,9 @@ RCT_EXTERN NSString *const RCTUserInterfaceStyleDidChangeNotificationTraitCollec
*/
RCT_EXTERN BOOL RCTExperimentGetPreemptiveViewAllocationDisabled(void);
RCT_EXTERN void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value);
/*
* Interop layer keep view hierarchy.
*/
RCT_EXTERN BOOL RCTGetInteropLayerKeepViewHierarchy(void);
RCT_EXTERN void RCTSetInteropLayerKeepViewHierarchy(BOOL value);

Просмотреть файл

@ -24,3 +24,18 @@ void RCTExperimentSetPreemptiveViewAllocationDisabled(BOOL value)
{
RCTExperimentPreemptiveViewAllocationDisabled = value;
}
/*
* Preemptive View Allocation
*/
static BOOL RCTInteropLayerKeepViewHierarchy = NO;
BOOL RCTGetInteropLayerKeepViewHierarchy()
{
return RCTInteropLayerKeepViewHierarchy;
}
void RCTSetInteropLayerKeepViewHierarchy(BOOL value)
{
RCTInteropLayerKeepViewHierarchy = value;
}

Просмотреть файл

@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (BOOL)isSupported:(NSString *)componentName;
+ (void)supportLegacyViewManagerWithName:(NSString *)componentName;
+ (void)supportLegacyViewManagersWithPrefix:(NSString *)prefix;
@end

Просмотреть файл

@ -8,6 +8,7 @@
#import "RCTLegacyViewManagerInteropComponentView.h"
#import <React/RCTAssert.h>
#import <React/RCTConstants.h>
#import <React/UIView+React.h>
#import <react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.h>
#import <react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h>
@ -24,6 +25,7 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
NSMutableArray<UIView *> *_viewsToBeUnmounted;
RCTLegacyViewManagerInteropCoordinatorAdapter *_adapter;
LegacyViewManagerInteropShadowNode::ConcreteState::Shared _state;
BOOL _hasInvokedForwardingWarning;
}
- (instancetype)initWithFrame:(CGRect)frame
@ -33,6 +35,7 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
_props = defaultProps;
_viewsToBeMounted = [NSMutableArray new];
_viewsToBeUnmounted = [NSMutableArray new];
_hasInvokedForwardingWarning = NO;
}
return self;
@ -49,37 +52,7 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
return result;
}
+ (NSMutableSet<NSString *> *)supportedViewManagers
{
static NSMutableSet<NSString *> *supported = [NSMutableSet setWithObjects:@"DatePicker",
@"ProgressView",
@"SegmentedControl",
@"MaskedView",
@"ARTSurfaceView",
@"ARTText",
@"ARTShape",
@"ARTGroup",
nil];
return supported;
}
+ (BOOL)isSupported:(NSString *)componentName
{
RCTLogNotAllowedForNewArchitecture(
self,
[NSString
stringWithFormat:
@"Legacy ViewManagers should be migrated to Fabric ComponentViews in the new architecture to reduce risk. Component using interop layer: %@",
componentName]);
return [[RCTLegacyViewManagerInteropComponentView supportedViewManagers] containsObject:componentName];
}
+ (void)supportLegacyViewManagerWithName:(NSString *)componentName
{
[[RCTLegacyViewManagerInteropComponentView supportedViewManagers] addObject:componentName];
}
- (RCTLegacyViewManagerInteropCoordinator *)coordinator
- (RCTLegacyViewManagerInteropCoordinator *)_coordinator
{
if (_state != nullptr) {
const auto &state = _state->getData();
@ -96,6 +69,80 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
return coordinator.componentViewName;
}
#pragma mark - Method forwarding
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if (!_hasInvokedForwardingWarning) {
_hasInvokedForwardingWarning = YES;
NSLog(
@"Invoked unsupported method on RCTLegacyViewManagerInteropComponentView. Resulting to noop instead of a crash.");
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [super methodSignatureForSelector:aSelector] ?: [self.contentView methodSignatureForSelector:aSelector];
}
#pragma mark - Supported ViewManagers
+ (NSMutableSet<NSString *> *)supportedViewManagers
{
static NSMutableSet<NSString *> *supported = [NSMutableSet setWithObjects:@"DatePicker",
@"ProgressView",
@"SegmentedControl",
@"MaskedView",
@"ARTSurfaceView",
@"ARTText",
@"ARTShape",
@"ARTGroup",
nil];
return supported;
}
+ (NSMutableSet<NSString *> *)supportedViewManagersPrefixes
{
static NSMutableSet<NSString *> *supported = [NSMutableSet new];
return supported;
}
+ (BOOL)isSupported:(NSString *)componentName
{
RCTLogNotAllowedForNewArchitecture(
self,
[NSString
stringWithFormat:
@"Legacy ViewManagers should be migrated to Fabric ComponentViews in the new architecture to reduce risk. Component using interop layer: %@",
componentName]);
// Step 1: check if ViewManager with specified name is supported.
BOOL isComponentNameSupported =
[[RCTLegacyViewManagerInteropComponentView supportedViewManagers] containsObject:componentName];
if (isComponentNameSupported) {
return YES;
}
// Step 2: check if component has supported prefix.
for (NSString *item in [RCTLegacyViewManagerInteropComponentView supportedViewManagersPrefixes]) {
if ([componentName hasPrefix:item]) {
return YES;
}
}
return NO;
}
+ (void)supportLegacyViewManagersWithPrefix:(NSString *)prefix
{
[[RCTLegacyViewManagerInteropComponentView supportedViewManagersPrefixes] addObject:prefix];
}
+ (void)supportLegacyViewManagerWithName:(NSString *)componentName
{
[[RCTLegacyViewManagerInteropComponentView supportedViewManagers] addObject:componentName];
}
#pragma mark - RCTComponentViewProtocol
- (void)prepareForRecycle
@ -105,6 +152,7 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
[_viewsToBeUnmounted removeAllObjects];
_state.reset();
self.contentView = nil;
_hasInvokedForwardingWarning = NO;
[super prepareForRecycle];
}
@ -140,7 +188,7 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
[super finalizeUpdates:updateMask];
if (!_adapter) {
_adapter = [[RCTLegacyViewManagerInteropCoordinatorAdapter alloc] initWithCoordinator:self.coordinator
_adapter = [[RCTLegacyViewManagerInteropCoordinatorAdapter alloc] initWithCoordinator:[self _coordinator]
reactTag:self.tag];
__weak __typeof(self) weakSelf = self;
_adapter.eventInterceptor = ^(std::string eventName, folly::dynamic event) {
@ -157,7 +205,16 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
for (NSDictionary *mountInstruction in _viewsToBeMounted) {
NSNumber *index = mountInstruction[kRCTLegacyInteropChildIndexKey];
UIView *childView = mountInstruction[kRCTLegacyInteropChildComponentKey];
[_adapter.paperView insertReactSubview:childView atIndex:index.integerValue];
if (RCTGetInteropLayerKeepViewHierarchy()) {
if ([childView isKindOfClass:[RCTLegacyViewManagerInteropComponentView class]]) {
UIView *target = ((RCTLegacyViewManagerInteropComponentView *)childView).contentView;
[_adapter.paperView insertReactSubview:target atIndex:index.integerValue];
} else {
[_adapter.paperView insertReactSubview:childView atIndex:index.integerValue];
}
} else {
[_adapter.paperView insertReactSubview:childView atIndex:index.integerValue];
}
}
[_viewsToBeMounted removeAllObjects];

Просмотреть файл

@ -263,6 +263,10 @@ static BackgroundExecutor RCTGetBackgroundExecutor()
RCTExperimentSetPreemptiveViewAllocationDisabled(YES);
}
RCTSetInteropLayerKeepViewHierarchy(
reactNativeConfig &&
reactNativeConfig->getBool("react_native_new_architecture:interop_layer_keep_view_hierarchy"));
auto componentRegistryFactory =
[factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)](
EventDispatcher::Weak const &eventDispatcher, ContextContainer::Shared const &contextContainer) {

Просмотреть файл

@ -43,6 +43,11 @@ static std::string moduleNameFromComponentName(const std::string &componentName)
return componentName + "Manager";
}
std::string rnPrefix("RN");
if (std::mismatch(rnPrefix.begin(), rnPrefix.end(), componentName.begin()).first == rnPrefix.end()) {
return componentName + "Manager";
}
return "RCT" + componentName + "Manager";
}

Просмотреть файл

@ -86,8 +86,10 @@ using namespace facebook::react;
- (void)setProps:(folly::dynamic const &)props forView:(UIView *)view
{
NSDictionary<NSString *, id> *convertedProps = convertFollyDynamicToId(props);
[_componentData setProps:convertedProps forView:view];
if (props.isObject()) {
NSDictionary<NSString *, id> *convertedProps = convertFollyDynamicToId(props);
[_componentData setProps:convertedProps forView:view];
}
}
- (NSString *)componentViewName