From d29f3d2a6b84c17ad057f4e9c8dc35b3fe16fb19 Mon Sep 17 00:00:00 2001 From: Sota Ogo Date: Wed, 17 Nov 2021 16:00:16 -0800 Subject: [PATCH] Add a simple fabric component example Summary: This diff adds a very simple example to show the use of new architecture in a component. Changelog: [internal] Reviewed By: cortinico Differential Revision: D32045059 fbshipit-source-id: f388bfb765241122de425fbef61cea0620cd31ac --- .../MyNativeView.podspec | 47 ++++++++++ .../ios/RNTMyNativeViewComponentView.h | 19 +++++ .../ios/RNTMyNativeViewComponentView.mm | 85 +++++++++++++++++++ .../ios/RNTMyNativeViewManager.mm | 48 +++++++++++ .../NativeComponentExample/js/MyNativeView.js | 62 ++++++++++++++ .../js/MyNativeViewNativeComponent.js | 38 +++++++++ 6 files changed, 299 insertions(+) create mode 100644 packages/rn-tester/NativeComponentExample/MyNativeView.podspec create mode 100644 packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.h create mode 100644 packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm create mode 100644 packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewManager.mm create mode 100644 packages/rn-tester/NativeComponentExample/js/MyNativeView.js create mode 100644 packages/rn-tester/NativeComponentExample/js/MyNativeViewNativeComponent.js diff --git a/packages/rn-tester/NativeComponentExample/MyNativeView.podspec b/packages/rn-tester/NativeComponentExample/MyNativeView.podspec new file mode 100644 index 00000000000..f3cf2720a2c --- /dev/null +++ b/packages/rn-tester/NativeComponentExample/MyNativeView.podspec @@ -0,0 +1,47 @@ +# 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. + +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "../" "package.json"))) + +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' +folly_version = '2021.06.28.00-v2' +boost_version = '1.76.0' +boost_compiler_flags = '-Wno-documentation' + +Pod::Spec.new do |s| + s.name = "MyNativeView" + s.version = package["version"] + s.summary = package["description"] + s.description = "my-native-view" + s.homepage = "https://github.com/sota000/my-native-view.git" + s.license = "MIT" + s.platforms = { :ios => "11.0", :tvos => "11.0" } + s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags + ' -Wno-nullability-completeness' + s.author = "Facebook, Inc. and its affiliates" + s.source = { :git => "https://github.com/facebook/my-native-view.git", :tag => "#{s.version}" } + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/boost\"" + } + + s.source_files = "ios/**/*.{h,m,mm,cpp}" + s.requires_arc = true + + s.dependency "React" + s.dependency "React-RCTFabric" + s.dependency "React-Codegen" + s.dependency "RCTRequired" + s.dependency "RCTTypeSafety" + s.dependency "ReactCommon/turbomodule/core" + + # Enable codegen for this library + use_react_native_codegen!(s, { + :library_name => "MyNativeViewSpec", + :react_native_path => "../../../", + :js_srcs_dir => "./js", + :library_type => "components" + }) +end diff --git a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.h b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.h new file mode 100644 index 00000000000..548703f6501 --- /dev/null +++ b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.h @@ -0,0 +1,19 @@ +/* + * 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 +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface RNTMyNativeViewComponentView : RCTViewComponentView + +- (UIColor *)UIColorFromHexString: (const std::string)hexString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm new file mode 100644 index 00000000000..73f470c5df6 --- /dev/null +++ b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm @@ -0,0 +1,85 @@ +/* + * 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 "RNTMyNativeViewComponentView.h" + +#import +#import +#import +#import + +#import "RCTFabricComponentsPlugins.h" + +using namespace facebook::react; + +@interface RNTMyNativeViewComponentView () +@end + +@implementation RNTMyNativeViewComponentView { + UIView *_view; +} + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + + _view = [[UIView alloc] init]; + _view.backgroundColor = [UIColor redColor]; + + self.contentView = _view; + } + + return self; +} + +- (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]; +} + +- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps +{ + [super updateProps:props oldProps:oldProps]; +} + +- (void)onChange:(UIView *)sender +{ +// No-op +// std::dynamic_pointer_cast(_eventEmitter) +// ->onChange(ViewEventEmitter::OnChange{.value = static_cast(sender.on)}); +} + +#pragma mark - Native Commands + +- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args +{ + RCTRNTMyNativeViewHandleCommand(self, commandName, args); +} + +- (void)callNativeMethodToChangeBackgroundColor:(NSString *)colorString +{ + UIColor *color = [self UIColorFromHexString:std::string([colorString UTF8String])]; + _view.backgroundColor = color; +} +@end + +Class RNTMyNativeViewCls(void) +{ + return RNTMyNativeViewComponentView.class; +} diff --git a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewManager.mm b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewManager.mm new file mode 100644 index 00000000000..47084d74570 --- /dev/null +++ b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewManager.mm @@ -0,0 +1,48 @@ +/* + * 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 +#import +#import + +@interface RNTMyNativeViewManager : RCTViewManager +@end + +@implementation RNTMyNativeViewManager + +RCT_EXPORT_MODULE(RNTMyNativeView) + +RCT_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor) + +RCT_EXPORT_METHOD(callNativeMethodToChangeBackgroundColor:(nonnull NSNumber *)reactTag + color:(NSString *)color +) { + [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { + UIView *view = viewRegistry[reactTag]; + if (!view || ![view isKindOfClass:[UIView class]]) { + RCTLogError(@"Cannot find NativeView with tag #%@", reactTag); + 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]; + + view.backgroundColor = [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0]; + }]; + +} + +- (UIView *)view +{ + return [[UIView alloc] init]; +} + +@end diff --git a/packages/rn-tester/NativeComponentExample/js/MyNativeView.js b/packages/rn-tester/NativeComponentExample/js/MyNativeView.js new file mode 100644 index 00000000000..b45203adc1a --- /dev/null +++ b/packages/rn-tester/NativeComponentExample/js/MyNativeView.js @@ -0,0 +1,62 @@ +/** + * 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. + * + * @flow strict-local + * @format + */ + +import * as React from 'react'; +import {useRef, useState} from 'react'; +import {View, Button} from 'react-native'; +import RNTMyNativeView, { + Commands as RNTMyNativeViewCommands, +} from './MyNativeViewNativeComponent'; +import type {MyNativeViewType} from './MyNativeViewNativeComponent'; + +const colors = [ + '#0000FF', + '#FF0000', + '#00FF00', + '#003300', + '#330000', + '#000033', +]; + +// This is an example component that migrates to use the new architecture. +export default function MyNativeView(props: {}): React.Node { + const ref = useRef | null>(null); + const [opacity, setOpacity] = useState(1.0); + return ( + + +