Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add RNTester example for native command Array param #41897

Closed
wants to merge 2 commits into from
Closed
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
3 changes: 2 additions & 1 deletion packages/react-native-codegen/src/CodegenSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ export type CommandParamTypeAnnotation =
| Int32TypeAnnotation
| DoubleTypeAnnotation
| FloatTypeAnnotation
| StringTypeAnnotation;
| StringTypeAnnotation
| ArrayTypeAnnotation;

export type ReservedTypeAnnotation = $ReadOnly<{
type: 'ReservedTypeAnnotation',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ function getObjCParamType(param: Param): string {
return 'NSInteger';
case 'StringTypeAnnotation':
return 'NSString *';
case 'ArrayTypeAnnotation':
return 'const NSArray *';
default:
(typeAnnotation.type: empty);
throw new Error('Received invalid param type annotation');
Expand Down Expand Up @@ -199,6 +201,8 @@ function getObjCExpectedKindParamType(param: Param): string {
return '[NSNumber class]';
case 'StringTypeAnnotation':
return '[NSString class]';
case 'ArrayTypeAnnotation':
return '[NSArray class]';
default:
(typeAnnotation.type: empty);
throw new Error('Received invalid param type annotation');
Expand Down Expand Up @@ -227,6 +231,8 @@ function getReadableExpectedKindParamType(param: Param): string {
return 'number';
case 'StringTypeAnnotation':
return 'string';
case 'ArrayTypeAnnotation':
return 'array';
default:
(typeAnnotation.type: empty);
throw new Error('Received invalid param type annotation');
Expand Down Expand Up @@ -258,6 +264,8 @@ function getObjCRightHandAssignmentParamType(
return `[(NSNumber *)arg${index} intValue]`;
case 'StringTypeAnnotation':
return `(NSString *)arg${index}`;
case 'ArrayTypeAnnotation':
return `(NSArray *)arg${index}`;
default:
(typeAnnotation.type: empty);
throw new Error('Received invalid param type annotation');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ function getCommandArgJavaType(
return `args.getInt(${index})`;
case 'StringTypeAnnotation':
return `args.getString(${index})`;
case 'ArrayTypeAnnotation':
return `args.getArray(${index})`;
default:
(typeAnnotation.type: empty);
throw new Error(`Receieved invalid type: ${typeAnnotation.type}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ function getCommandArgJavaType(param: NamedShape<CommandParamTypeAnnotation>) {
return 'int';
case 'StringTypeAnnotation':
return 'String';
case 'ArrayTypeAnnotation':
return 'ReadableArray';
default:
(typeAnnotation.type: empty);
throw new Error('Receieved invalid typeAnnotation');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ function getImports(
}
});

component.commands.forEach(command => {
command.typeAnnotation.params.forEach(param => {
const cmdParamType = param.typeAnnotation.type;
if (cmdParamType === 'ArrayTypeAnnotation') {
imports.add('import com.facebook.react.bridge.ReadableArray;');
}
});
});

return imports;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,28 @@ const COMMANDS_AND_PROPS: SchemaType = {
},
},
},
{
name: 'addItems',
optional: false,
typeAnnotation: {
type: 'FunctionTypeAnnotation',
params: [
{
name: 'items',
optional: false,
typeAnnotation: {
type: 'ArrayTypeAnnotation',
elementType: {
type: 'StringTypeAnnotation',
},
},
},
],
returnTypeAnnotation: {
type: 'VoidTypeAnnotation',
},
},
},
],
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ NS_ASSUME_NONNULL_BEGIN
@protocol RCTCommandNativeComponentViewProtocol <NSObject>
- (void)handleRootTag:(double)rootTag;
- (void)hotspotUpdate:(NSInteger)x y:(NSInteger)y;
- (void)addItems:(const NSArray *)items;
@end

RCT_EXTERN inline void RCTCommandNativeComponentHandleCommand(
Expand Down Expand Up @@ -277,6 +278,26 @@ NSObject *arg1 = args[1];
return;
}

if ([commandName isEqualToString:@\\"addItems\\"]) {
#if RCT_DEBUG
if ([args count] != 1) {
RCTLogError(@\\"%@ command %@ received %d arguments, expected %d.\\", @\\"CommandNativeComponent\\", commandName, (int)[args count], 1);
return;
}
#endif

NSObject *arg0 = args[0];
#if RCT_DEBUG
if (!RCTValidateTypeOfViewCommandArgument(arg0, [NSArray class], @\\"array\\", @\\"CommandNativeComponent\\", commandName, @\\"1st\\")) {
return;
}
#endif
const NSArray * items = (NSArray *)arg0;

[componentView addItems:items];
return;
}

#if RCT_DEBUG
RCTLogError(@\\"%@ received command %@, which is not a supported command.\\", @\\"CommandNativeComponent\\", commandName);
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ public class CommandNativeComponentManagerDelegate<T extends View, U extends Bas
case \\"hotspotUpdate\\":
mViewManager.hotspotUpdate(view, args.getInt(0), args.getInt(1));
break;
case \\"addItems\\":
mViewManager.addItems(view, args.getArray(0));
break;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,13 @@ package com.facebook.react.viewmanagers;

import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;

public interface CommandNativeComponentManagerInterface<T extends View> {
void setAccessibilityHint(T view, @Nullable String value);
void handleRootTag(T view, double rootTag);
void hotspotUpdate(T view, int x, int y);
void addItems(T view, ReadableArray items);
}
",
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ export const Commands = {

hotspotUpdate(ref, x, y) {
dispatchCommand(ref, \\"hotspotUpdate\\", [x, y]);
},

addItems(ref, items) {
dispatchCommand(ref, \\"addItems\\", [items]);
}
};
",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
'use strict';

import type {
CommandParamTypeAnnotation,
CommandTypeAnnotation,
NamedShape,
} from '../../../CodegenSchema.js';
Expand All @@ -21,7 +22,24 @@ const {getValueFromTypes} = require('../utils.js');
// $FlowFixMe[unclear-type] there's no flowtype for ASTs
type EventTypeAST = Object;

function buildCommandSchema(property: EventTypeAST, types: TypeDeclarationMap) {
function buildCommandSchema(
property: EventTypeAST,
types: TypeDeclarationMap,
): $ReadOnly<{
name: string,
optional: boolean,
typeAnnotation: {
type: 'FunctionTypeAnnotation',
params: $ReadOnlyArray<{
name: string,
optional: boolean,
typeAnnotation: CommandParamTypeAnnotation,
}>,
returnTypeAnnotation: {
type: 'VoidTypeAnnotation',
},
},
}> {
const name = property.key.name;
const optional = property.optional;
const value = getValueFromTypes(property.value, types);
Expand All @@ -48,7 +66,7 @@ function buildCommandSchema(property: EventTypeAST, types: TypeDeclarationMap) {
paramValue.type === 'GenericTypeAnnotation'
? paramValue.id.name
: paramValue.type;
let returnType;
let returnType: CommandParamTypeAnnotation;

switch (type) {
case 'RootTag':
Expand Down Expand Up @@ -82,6 +100,14 @@ function buildCommandSchema(property: EventTypeAST, types: TypeDeclarationMap) {
type: 'StringTypeAnnotation',
};
break;
case 'Array':
case '$ReadOnlyArray':
case 'ArrayTypeAnnotation':
returnType = {
type: 'ArrayTypeAnnotation',
elementType: paramValue.elementType,
};
break;
default:
(type: empty);
throw new Error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import <React/RCTUIManager.h>
#import <React/RCTViewManager.h>
#import "RNTLegacyView.h"
#import "RNTMyNativeViewCommon.h"
#import "RNTMyNativeViewComponentView.h"

@interface RNTMyLegacyNativeViewManager : RCTViewManager
Expand Down Expand Up @@ -46,18 +47,33 @@ + (BOOL)requiresMainQueueSetup
return;
}

unsigned rgbValue = 0;
NSString *colorString = [NSString stringWithCString:std::string([color UTF8String]).c_str()
encoding:[NSString defaultCStringEncoding]];
NSScanner *scanner = [NSScanner scannerWithString:colorString];
[scanner setScanLocation:1]; // bypass '#' character
[scanner scanHexInt:&rgbValue];

UIColor *newColor = [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16) / 255.0
green:((rgbValue & 0xFF00) >> 8) / 255.0
blue:(rgbValue & 0xFF) / 255.0
alpha:1.0];
view.backgroundColor = newColor;
[RNTMyNativeViewCommon setBackgroundColor:view colorString:color];
}];
}

RCT_EXPORT_METHOD(addOverlays : (nonnull NSNumber *)reactTag overlayColors : (NSArray *)overlayColors)
{
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
UIView *view = viewRegistry[reactTag];
if (!view || ![view isKindOfClass:[RNTLegacyView class]]) {
RCTLogError(@"Cannot find RNTLegacyView with tag #%@", reactTag);
return;
}

[RNTMyNativeViewCommon addOverlays:view overlayColors:overlayColors];
}];
}

RCT_EXPORT_METHOD(removeOverlays : (nonnull NSNumber *)reactTag)
{
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
UIView *view = viewRegistry[reactTag];
if (!view || ![view isKindOfClass:[RNTLegacyView class]]) {
RCTLogError(@"Cannot find RNTLegacyView with tag #%@", reactTag);
return;
}

[RNTMyNativeViewCommon removeOverlays:view];
}];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <React/RCTComponent.h>
#import <UIKit/UIKit.h>
#import <string>

NS_ASSUME_NONNULL_BEGIN

@interface RNTMyNativeViewCommon : NSObject

+ (void)setBackgroundColor:(UIView *)view colorString:(NSString *)colorString;
+ (void)addOverlays:(UIView *)view overlayColors:(const NSArray *)overlayColors;
+ (void)removeOverlays:(UIView *)view;
+ (UIColor *)UIColorFromHexString:(const std::string)hexString;

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import "RNTMyNativeViewCommon.h"

@implementation RNTMyNativeViewCommon {
}

+ (void)setBackgroundColor:(UIView *)view colorString:(NSString *)colorString
{
UIColor *color = [self UIColorFromHexString:std::string([colorString UTF8String])];
view.backgroundColor = color;
}

+ (void)addOverlays:(UIView *)view overlayColors:(const NSArray *)overlayColors
{
CGRect viewBounds = view.bounds;
CGFloat width = viewBounds.size.width / [overlayColors count];
int i;
for (i = 0; i < [overlayColors count]; i++) {
id colorString = [overlayColors objectAtIndex:i];
CGRect rect = CGRectMake(viewBounds.origin.x + width * i, viewBounds.origin.y, width, viewBounds.size.height);
UIView *overlayView = [[UIView alloc] initWithFrame:rect];
UIColor *color = [self UIColorFromHexString:std::string([colorString UTF8String])];
overlayView.backgroundColor = color;
[view addSubview:overlayView];
}
}

+ (void)removeOverlays:(UIView *)view
{
NSArray *viewsToRemove = [view subviews];
for (UIView *subview in viewsToRemove) {
[subview removeFromSuperview];
}
}

+ (UIColor *)UIColorFromHexString:(const std::string)hexString
{
unsigned rgbValue = 0;
NSString *colorString = [NSString stringWithCString:hexString.c_str() encoding:[NSString defaultCStringEncoding]];
NSScanner *scanner = [NSScanner scannerWithString:colorString];
[scanner setScanLocation:1]; // bypass '#' character
[scanner scanHexInt:&rgbValue];
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16) / 255.0
green:((rgbValue & 0xFF00) >> 8) / 255.0
blue:(rgbValue & 0xFF) / 255.0
alpha:1.0];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ NS_ASSUME_NONNULL_BEGIN

@property (nonatomic, copy) RCTBubblingEventBlock onIntArrayChanged;

- (UIColor *)UIColorFromHexString:(const std::string)hexString;

@end

NS_ASSUME_NONNULL_END
Loading
Loading