Skip to content

Commit

Permalink
feat(ios): add Fabric support (#657)
Browse files Browse the repository at this point in the history
* Initial changes

* test fabric in CI

* Sending picker size to shadow node

* Fix E2E config

* Update Xcode in CI

* Adding more comments

* cleanup

Co-authored-by: Alfonso Curbelo <[email protected]>
  • Loading branch information
alfonsocj and alfonsocj-cb authored Sep 27, 2022
1 parent 9e35e45 commit 8df590b
Show file tree
Hide file tree
Showing 23 changed files with 573 additions and 53 deletions.
5 changes: 1 addition & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
e2e_release_ios:
executor:
name: rn/macos
xcode_version: '13.1.0'
xcode_version: '14.0.0'
steps:
- checkout
- run:
Expand All @@ -52,9 +52,6 @@ jobs:
name: bundle js
- rn/pod_install:
pod_install_directory: 'example/ios'
- run:
command: curl https://raw.githubusercontent.com/facebook/react-native/6334ac35ac3cbc2c84b2d46d46ec118bf9bf714d/scripts/find-node.sh > node_modules/react-native/scripts/find-node.sh
name: fix issue with nvm # will be fixed in RN 67 (https://github.com/react-native-community/upgrade-support/issues/138)
- run:
command: yarn detox:ios:build:release
name: build app for e2e tests
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ DerivedData
*.ipa
*.xcuserstate
project.xcworkspace
IDEWorkspaceChecks.plist

#Detox
#
Expand Down
27 changes: 27 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,30 @@ An existing Android emulator is required to match the name defined in `detox.con
yarn detox:android:build:release
yarn detox:android:test:release
```

### Fabric

Fabric is the new React Native rendering system ([read more about it here](https://reactnative.dev/architecture/fabric-renderer)).

#### iOS

```
yarn start
cd "example/ios" && RCT_NEW_ARCH_ENABLED=1 npx pod-install && cd -
yarn start:ios
```
If you want to go back to the old renderer (Paper),
remove `ios/build`, run `pod-install` without the `RCT_NEW_ARCH_ENABLED=1` and build again
```
rm -r "example/ios/build"
cd "example/ios" && npx pod-install && cd -
yarn start:ios
```
#### Android
The date time picker does not have a native UI component for Android but a native module.
([read more about native modules here](https://reactnative.dev/docs/native-modules-intro)).
33 changes: 31 additions & 2 deletions RNDateTimePicker.podspec
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require 'json'

fabric_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'

package = JSON.parse(File.read(File.join(__dir__, 'package.json')))

Pod::Spec.new do |s|
Expand All @@ -12,8 +14,35 @@ Pod::Spec.new do |s|
s.homepage = package['homepage']
s.platform = :ios, "11.0"
s.source = { :git => "https://github.com/react-native-community/datetimepicker", :tag => "v#{s.version}" }
s.source_files = "ios/*.{h,m}"
s.source_files = "ios/**/*.{h,m,mm,cpp}"
s.requires_arc = true

s.dependency "React-Core"
if fabric_enabled
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'

s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
s.pod_target_xcconfig = {
'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/boost" "$(PODS_ROOT)/boost-for-react-native" "$(PODS_ROOT)/RCT-Folly"',
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
}

s.dependency "React"
s.dependency "React-RCTFabric"
s.dependency "React-Codegen"
s.dependency "RCT-Folly"
s.dependency "RCTRequired"
s.dependency "RCTTypeSafety"
s.dependency "ReactCommon/turbomodule/core"

s.subspec "cpp" do |ss|
ss.source_files = "cpp/**/*.{cpp,h}"
ss.header_dir = "rndatetimepicker"
ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/cpp\"" }
end

else
s.exclude_files = "ios/fabric"

s.dependency "React-Core"
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
* and copied to the cpp directory to override the adopt function and set the size of the shadow node based
* on the state.
* @generated by codegen project: GenerateComponentDescriptorH.js
*/

#pragma once

#include "ShadowNodes.h"
#include <react/renderer/core/ConcreteComponentDescriptor.h>

namespace facebook {
namespace react {

class RNDateTimePickerComponentDescriptor final : public ConcreteComponentDescriptor<RNDateTimePickerShadowNode> {
public:
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;

void adopt(ShadowNode::Unshared const &shadowNode) const override {
react_native_assert(std::dynamic_pointer_cast<RNDateTimePickerShadowNode>(shadowNode));
auto pickerShadowNode = std::static_pointer_cast<RNDateTimePickerShadowNode>(shadowNode);

react_native_assert(
std::dynamic_pointer_cast<YogaLayoutableShadowNode>(pickerShadowNode));
auto layoutableShadowNode =
std::static_pointer_cast<YogaLayoutableShadowNode>(pickerShadowNode);

auto state = std::static_pointer_cast<const RNDateTimePickerShadowNode::ConcreteState>(shadowNode->getState());
auto stateData = state->getData();

if(stateData.frameSize.width != 0 && stateData.frameSize.height != 0) {
layoutableShadowNode->setSize(Size{stateData.frameSize.width, stateData.frameSize.height});
}

ConcreteComponentDescriptor::adopt(shadowNode);
}
};

} // namespace react
} // namespace facebook
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Custom state to store frameSize that the component descriptor will use to modify the
* shadow node layout.
*/

#include "RNDateTimePickerState.h"

namespace facebook {
namespace react {

} // namespace react
} // namespace facebook
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Custom state to store frameSize that the component descriptor will use to modify the
* shadow node layout.
*/

#pragma once

#include <react/renderer/graphics/Geometry.h>

namespace facebook {
namespace react {

class RNDateTimePickerState final {
public:
using Shared = std::shared_ptr<const RNDateTimePickerState>;
RNDateTimePickerState(){};
RNDateTimePickerState(Size frameSize_) : frameSize(frameSize_){};

Size frameSize{};
};

} // namespace react
} // namespace facebook
17 changes: 17 additions & 0 deletions cpp/react/renderer/components/RNDateTimePicker/ShadowNodes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen)
* and copied to the cpp directory to add custom state and set shadow node trait as a LeafYogaNode.
*
* @generated by codegen project: GenerateShadowNodeCpp.js
*/

#include "ShadowNodes.h"

namespace facebook {
namespace react {

extern const char RNDateTimePickerComponentName[] = "RNDateTimePicker";

} // namespace react
} // namespace facebook
39 changes: 39 additions & 0 deletions cpp/react/renderer/components/RNDateTimePicker/ShadowNodes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen)
* and copied to the cpp directory to add custom state and set shadow node trait as a LeafYogaNode.
*
* @generated by codegen project: GenerateShadowNodeH.js
*/

#pragma once

#include "RNDateTimePickerState.h"
#include <react/renderer/components/RNDateTimePicker/EventEmitters.h>
#include <react/renderer/components/RNDateTimePicker/Props.h>
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
#include <jsi/jsi.h>
#include <react/renderer/core/LayoutContext.h>

namespace facebook {
namespace react {

JSI_EXPORT extern const char RNDateTimePickerComponentName[];

/*
* `ShadowNode` for <RNDateTimePicker> component.
*/
class JSI_EXPORT RNDateTimePickerShadowNode final : public ConcreteViewShadowNode<RNDateTimePickerComponentName, RNDateTimePickerProps, RNDateTimePickerEventEmitter, RNDateTimePickerState> {

public:
using ConcreteViewShadowNode::ConcreteViewShadowNode;

static ShadowNodeTraits BaseTraits() {
auto traits = ConcreteViewShadowNode::BaseTraits();
traits.set(ShadowNodeTraits::Trait::LeafYogaNode);
return traits;
}
};

} // namespace react
} // namespace facebook
2 changes: 1 addition & 1 deletion example/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
Switch,
} from 'react-native';
import DateTimePicker from '@react-native-community/datetimepicker';
import SegmentedControl from '@react-native-segmented-control/segmented-control';
import SegmentedControl from './SegmentedControl';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import React, {useRef, useState} from 'react';
import {Picker} from 'react-native-windows';
Expand Down
7 changes: 7 additions & 0 deletions example/SegmentedControl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import SegmentedControl from '@react-native-segmented-control/segmented-control';
import JSSegmentedControl from '@react-native-segmented-control/segmented-control/js/SegmentedControl.js';

const isFabricEnabled = global.nativeFabricUIManager !== null;

// Forcing the JS implementation for Fabric as the native module is not compatible with Fabric yet.
export default isFabricEnabled ? JSSegmentedControl : SegmentedControl;
4 changes: 3 additions & 1 deletion example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require_relative '../../node_modules/react-native-test-app/test_app'

use_flipper!
# Flipper causes the build to fail on release when fabric is enabled
# https://github.com/facebook/react-native/issues/33764
use_flipper!()

workspace 'date-time-picker-example.xcworkspace'

Expand Down
3 changes: 2 additions & 1 deletion example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ PODS:
- React-logger (= 0.70.0)
- React-perflogger (= 0.70.0)
- React-runtimeexecutor (= 0.70.0)
- RCT-Folly/Fabric (= 2021.07.22.00)
- React-jsi (0.70.0):
- boost (= 1.76.0)
- DoubleConversion
Expand Down Expand Up @@ -570,7 +571,7 @@ SPEC CHECKSUMS:
ReactCommon: de55f940495d7bf87b5d7bf55b5b15cdd50d7d7b
ReactTestApp-DevSupport: 8a8cff38c37cd8145a12ac7d7d0503dd08f97d65
ReactTestApp-Resources: ff5f151e465e890010b417ce65ca6c5de6aeccbb
RNDateTimePicker: 4f1fc917f5af9d9ae4c5fc0c63a4474d61338693
RNDateTimePicker: 9d66f002d6095cc89fcb66d0dc54bc6191c9ab0d
RNLocalize: cbcb55d0e19c78086ea4eea20e03fe8000bbbced
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: 82c9e8f652789f67d98bed5aef9d6653f71b04a9
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions ios/fabric/RNDateTimePickerComponentView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* RNDateTimePickerComponentView is only be available when fabric is enabled.
*/

#import <React/RCTViewComponentView.h>

NS_ASSUME_NONNULL_BEGIN

@interface RNDateTimePickerComponentView : RCTViewComponentView

@end

NS_ASSUME_NONNULL_END
Loading

0 comments on commit 8df590b

Please sign in to comment.