Skip to content

New architecture support #7744

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

Merged
merged 39 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
ffe332f
Support fabric on iOS
yogevbd Jun 12, 2023
545f6f7
bump react-native to 0.72
yogevbd Jun 26, 2023
2728ac2
Merge remote-tracking branch 'origin' into fabricSupportIOS
yogevbd Jun 26, 2023
4140719
Merge remote-tracking branch 'origin/master' into fabricSupportIOS
yogevbd Jun 26, 2023
316c8dc
remove .detoxrc.js
yogevbd Jun 26, 2023
8865812
f
yogevbd Jun 26, 2023
7c4f53f
f
yogevbd Jun 26, 2023
ffe6dd1
f
yogevbd Jun 26, 2023
228f6fc
Merge branch 'master' into fabricSupportIOS
yogevbd Jul 2, 2023
572d251
fix tests
yogevbd Jul 5, 2023
1fcff3b
Fix fabric layouting
yogevbd Jul 13, 2023
a250a86
f
yogevbd Jul 13, 2023
46d00c9
Update package.json
yogevbd Jul 16, 2023
ff5cf34
Fix iOS e2e
yogevbd Jul 19, 2023
8cc1aa5
Fix js tests
yogevbd Jul 20, 2023
751cdbc
Fix android tests
yogevbd Jul 20, 2023
8dcaaa3
f
yogevbd Jul 20, 2023
c65b9af
Restore setRoot unmounts component test
yogevbd Jul 20, 2023
2c52cb9
f
yogevbd Jul 20, 2023
9a20708
Fix android overlay MotionEvent
yogevbd Jul 30, 2023
7e8757e
Skip tests that fails not because of rnn
yogevbd Jul 30, 2023
6acf4ff
f
yogevbd Jul 30, 2023
6b9e0ae
f
yogevbd Jul 30, 2023
f79329f
Android RN72 support
yogevbd Aug 1, 2023
d6b02de
Fabric support on Android
yogevbd Aug 1, 2023
00b15b6
Fix android build
yogevbd Aug 1, 2023
3a30086
Fix android e2e tests
yogevbd Aug 1, 2023
bb7dfe8
Merge branch 'master' into fabricSupportIOS
yogevbd Aug 1, 2023
091b626
Avoid using RCTAppDelegate for backward compatability
yogevbd Aug 2, 2023
16b8266
Merge branch 'fabricSupportIOS' of github.com:wix/react-native-naviga…
yogevbd Aug 2, 2023
f39c014
Update package.json version to 7.36.0-rc.1 [buildkite skip]
mobile1-internal Aug 2, 2023
6aa233a
Fix auto link script
yogevbd Aug 2, 2023
5e36a70
Merge branch 'fabricSupportIOS' of github.com:wix/react-native-naviga…
yogevbd Aug 2, 2023
2d5d938
Fix appDelegateLinker tests
yogevbd Aug 2, 2023
bc04a15
rename updateReactViewConstraints
yogevbd Aug 2, 2023
4b4e27b
Restore RN modal tests
yogevbd Aug 2, 2023
b8ceb26
f
yogevbd Aug 2, 2023
0895c0f
Update package.json version to 7.36.0-rc.3 [buildkite skip]
mobile1-internal Aug 2, 2023
d8e5b2f
Merge branch 'master' into fabricSupportIOS
yogevbd Aug 2, 2023
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -243,4 +243,6 @@ artifacts/
lib/Mock/*.js
lib/Mock/*.d.ts
Mock.js
Mock.d.ts
Mock.d.ts

Gemfile.lock
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
source 'https://rubygems.org'

# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby '>= 2.6.10'

gem 'cocoapods', '>= 1.11.3'
35 changes: 26 additions & 9 deletions ReactNativeNavigation.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ require 'json'

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

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

Pod::Spec.new do |s|
s.name = "ReactNativeNavigation"
s.version = package['version']
Expand All @@ -17,19 +19,34 @@ Pod::Spec.new do |s|

s.subspec 'Core' do |ss|
s.source = { :git => "https://github.com/wix/react-native-navigation.git", :tag => "#{s.version}" }
s.source_files = "lib/ios/**/*.{h,m,mm}"
s.source_files = 'lib/ios/**/*.{h,m,mm,cpp}'
s.exclude_files = "lib/ios/ReactNativeNavigationTests/**/*.*", "lib/ios/OCMock/**/*.*"
end

# s.subspec 'Fabric' do |ss|
# ss.xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/RCT-Folly\"",
# "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1" }
# ss.dependency 'React-RCTFabric'
# ss.dependency 'React-Fabric'
# ss.dependency 'RCT-Folly/Fabric'
# end

if fabric_enabled
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
fabric_flags = fabric_enabled ? '-DRCT_NEW_ARCH_ENABLED' : ''
s.pod_target_xcconfig = {
'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/boost" "$(PODS_ROOT)/boost-for-react-native" "$(PODS_ROOT)/RCT-Folly" "$(PODS_ROOT)/Headers/Private/React-Core"',
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
}
s.compiler_flags = folly_compiler_flags + ' ' + '-DRCT_NEW_ARCH_ENABLED'
s.requires_arc = true

s.dependency "React"
s.dependency "React-RCTFabric"
s.dependency "React-cxxreact"
s.dependency "React-Fabric"
s.dependency "React-Codegen"
s.dependency "RCT-Folly"
s.dependency "RCTRequired"
s.dependency "RCTTypeSafety"
s.dependency "ReactCommon/turbomodule/core"
s.dependency "React-runtimeexecutor"
s.dependency "React-rncore"
end
s.dependency 'React-Core'
s.dependency 'React-CoreModules'
s.dependency 'React-RCTImage'
s.dependency 'React-RCTText'
s.dependency 'HMSegmentedControl'
Expand Down
21 changes: 2 additions & 19 deletions autolink/postlink/__snapshots__/appDelegateLinker.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ exports[`appDelegateLinker should work for RN 0.68 1`] = `
return YES;
}

- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
return [ReactNativeNavigation extraModulesForBridge:bridge];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
Expand Down Expand Up @@ -184,10 +180,6 @@ static NSString *const kRNConcurrentRoot = @\\"concurrentRoot\\";
return initProps;
}

- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
return [ReactNativeNavigation extraModulesForBridge:bridge];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
Expand Down Expand Up @@ -250,17 +242,8 @@ exports[`appDelegateLinker should work for RN 0.71 1`] = `

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
[ReactNativeNavigation bootstrapWithBridge:bridge];
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};

return YES;
}

- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {
return [ReactNativeNavigation extraModulesForBridge:bridge];

return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
Expand Down
61 changes: 22 additions & 39 deletions autolink/postlink/appDelegateLinker.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var { warnn, logn, infon, debugn, errorn } = require('./log');
class AppDelegateLinker {
constructor() {
this.appDelegatePath = path.appDelegate;
this.appDelegateHeaderPath = path.appDelegateHeader;
this.removeUnneededImportsSuccess = false;
this.removeApplicationLaunchContentSuccess = false;
}
Expand All @@ -22,6 +23,12 @@ class AppDelegateLinker {

var appDelegateContents = fs.readFileSync(this.appDelegatePath, 'utf8');

if (this.appDelegateHeaderPath) {
var appDelegateHeaderContents = fs.readFileSync(this.appDelegateHeaderPath, 'utf8');
appDelegateHeaderContents = this._extendRNNAppDelegate(appDelegateHeaderContents);
fs.writeFileSync(this.appDelegateHeaderPath, appDelegateHeaderContents);
}

try {
appDelegateContents = this._removeUnneededImports(appDelegateContents);
this.removeUnneededImportsSuccess = true;
Expand All @@ -33,8 +40,6 @@ class AppDelegateLinker {

appDelegateContents = this._bootstrapNavigation(appDelegateContents);

appDelegateContents = this._extraModulesForBridge(appDelegateContents);

try {
appDelegateContents = this._removeApplicationLaunchContent(appDelegateContents);
this.removeApplicationLaunchContentSuccess = true;
Expand Down Expand Up @@ -81,6 +86,18 @@ class AppDelegateLinker {
return content;
}

_extendRNNAppDelegate(content) {
return content
.replace(
/#import*.<RCTAppDelegate.h>/,
'#import "RNNAppDelegate.h"'
)
.replace(
/:*.RCTAppDelegate/,
': RNNAppDelegate'
)
}

_importNavigation(content) {
if (!this._doesImportNavigation(content)) {
debugn(' Importing ReactNativeNavigation.h');
Expand All @@ -105,52 +122,18 @@ class AppDelegateLinker {
.replace(
/RCTBridge.*];/,
'RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];\n' +
'[ReactNativeNavigation bootstrapWithBridge:bridge];'
)
.replace(
/return \[super application:application didFinishLaunchingWithOptions:launchOptions\];/,
'return YES;'
'[ReactNativeNavigation bootstrapWithBridge:bridge];'
)
.replace(
/self.moduleName.*;/,
'RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];\n' +
' [ReactNativeNavigation bootstrapWithBridge:bridge];'
/self.moduleName.*;(.|\n)*@{};\n?/,
''
);
}

_doesBootstrapNavigation(content) {
return /ReactNativeNavigation\s+bootstrap/.test(content);
}

_extraModulesForBridge(content) {
if (this._doesImplementsRNNExtraModulesForBridge(content)) {
warnn(' extraModulesForBridge already present.');
return content;
} else if (this._doesImplementsExtraModulesForBridge(content)) {
throw new Error(
'extraModulesForBridge implemented for a different module and needs manual linking. Check the manual installation docs to verify that everything is properly setup:\n https://wix.github.io/react-native-navigation/docs/installing#native-installation'
);
}

debugn(' Implementing extraModulesForBridge');
return content.replace(
/-.*\(NSURL.*\*\)sourceURLForBridge:\(RCTBridge.*\*\)bridge/,
'- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge {\n\
return [ReactNativeNavigation extraModulesForBridge:bridge];\n\
}\n\
\n\
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge'
);
}

_doesImplementsExtraModulesForBridge(content) {
return /-.*\(NSArray.*\*\)extraModulesForBridge:\(RCTBridge.*\*\)bridge/.test(content);
}

_doesImplementsRNNExtraModulesForBridge(content) {
return /ReactNativeNavigation\s+extraModulesForBridge/.test(content);
}

_removeApplicationLaunchContent(content) {
debugn(' Removing Application launch content');

Expand Down
1 change: 1 addition & 0 deletions autolink/postlink/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ exports.appDelegate = glob.sync(
reactNativeVersion < '0.68.0' ? '**/AppDelegate.m' : '**/AppDelegate.mm',
ignoreFolders
)[0];
exports.appDelegateHeader = glob.sync('**/AppDelegate.h', ignoreFolders)[0];
exports.podFile = glob.sync('**/Podfile', ignoreFolders)[0];
exports.plist = glob.sync('**/info.plist', ignoreFolders)[0];
2 changes: 1 addition & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ module.exports = function (api) {
return {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
'react-native-reanimated/plugin',
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-proposal-export-default-from',
'react-native-reanimated/plugin',
],
};
};
14 changes: 7 additions & 7 deletions e2e/Keyboard.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ describe.e2e('Keyboard', () => {
await expect(elementById(testIDs.MAIN_BOTTOM_TABS)).toBeVisible();
});

it('focus keyboard continue to resize content', async () => {
await elementById(TestIDs.TEXT_INPUT2).typeText("Hello");
await elementById(TestIDs.TEXT_INPUT2).tapReturnKey();
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeFocused();
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeVisible();
it(':ios: focus keyboard continue to resize content', async () => {
await elementById(TestIDs.TEXT_INPUT2).typeText("Hello");
await elementById(TestIDs.TEXT_INPUT2).tapReturnKey();
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeFocused();
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeVisible();
});

it('focus keyboard on push', async () => {
it(':ios: focus keyboard on push', async () => {
await elementById(TestIDs.PUSH_FOCUSED_KEYBOARD_SCREEN).tap();
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeFocused();
});

it('focus keyboard on show modal', async () => {
it(':ios: focus keyboard on show modal', async () => {
await elementById(TestIDs.MODAL_FOCUSED_KEYBOARD_SCREEN).tap();
await expect(elementById(TestIDs.TEXT_INPUT1)).toBeFocused();
});
Expand Down
40 changes: 21 additions & 19 deletions e2e/Utils.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { readFileSync } from 'fs';
function bitmapDiff(imagePath, expectedImagePath) {
const PNG = require('pngjs').PNG;
const pixelmatch = require('pixelmatch');
const img1 = PNG.sync.read(readFileSync(imagePath));
const img2 = PNG.sync.read(readFileSync(expectedImagePath));
const {width, height} = img1;
const diff = new PNG({width, height});
function bitmapDiff(imagePath, expectedImagePath) {
const PNG = require('pngjs').PNG;
const pixelmatch = require('pixelmatch');
const img1 = PNG.sync.read(readFileSync(imagePath));
const img2 = PNG.sync.read(readFileSync(expectedImagePath));
const { width, height } = img1;
const diff = new PNG({ width, height });

return pixelmatch(img1.data, img2.data, diff.data, width, height, {threshold: 0.0})
return pixelmatch(img1.data, img2.data, diff.data, width, height, { threshold: 0.0 });
}
const utils = {
elementByLabel: (label) => {
// uncomment for running tests with rn's new arch
// return element(by.label(label)).atIndex(0);
return element(by.text(label));
},
elementById: (id) => {
Expand All @@ -29,18 +31,18 @@ const utils = {
}
},
sleep: (ms) => new Promise((res) => setTimeout(res, ms)),
expectImagesToBeEqual:(imagePath, expectedImagePath)=>{
let diff = bitmapDiff(imagePath,expectedImagePath);
if(diff!==0){
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`)
}
} ,
expectImagesToBeNotEqual:(imagePath, expectedImagePath)=>{
let diff = bitmapDiff(imagePath,expectedImagePath);
if(diff===0){
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`)
}
expectImagesToBeEqual: (imagePath, expectedImagePath) => {
let diff = bitmapDiff(imagePath, expectedImagePath);
if (diff !== 0) {
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`);
}
},
expectImagesToBeNotEqual: (imagePath, expectedImagePath) => {
let diff = bitmapDiff(imagePath, expectedImagePath);
if (diff === 0) {
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`);
}
},
};

export default utils;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.uimanager.JSTouchDispatcher;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.EventDispatcher;
Expand All @@ -34,6 +35,7 @@ public ReactView(final Context context, ReactInstanceManager reactInstanceManage
this.componentId = componentId;
this.componentName = componentName;
jsTouchDispatcher = new JSTouchDispatcher(this);
setIsFabric(ReactFeatureFlags.enableFabricRenderer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.reactnativenavigation.react.modal

import com.facebook.react.bridge.Arguments
import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.events.RCTEventEmitter

Expand All @@ -14,7 +15,7 @@ open class RequestCloseModalEvent(viewTag: Int) : Event<RequestCloseModalEvent>(
}

override fun dispatch(rctEventEmitter: RCTEventEmitter) {
rctEventEmitter.receiveEvent(viewTag, eventName, null)
rctEventEmitter.receiveEvent(viewTag, eventName, Arguments.createMap())
}
}

Expand All @@ -29,6 +30,6 @@ open class ShowModalEvent(viewTag: Int) : Event<ShowModalEvent>(viewTag) {
}

override fun dispatch(rctEventEmitter: RCTEventEmitter) {
rctEventEmitter.receiveEvent(viewTag, eventName, null)
rctEventEmitter.receiveEvent(viewTag, eventName, Arguments.createMap())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,9 @@ fun MotionEvent.coordinatesInsideView(view: View?): Boolean {
view.getHitRect(hitRect)
return hitRect.contains(x.toInt(), y.toInt())
} else {
val viewGroup = (view as? ViewGroup)?.getChildAt(0) as? ViewGroup ?: return false
val viewGroup = (view as? ViewGroup)?.getChildAt(0) as? ViewGroup ?: view

return if (viewGroup.childCount > 0) {
val content = viewGroup.getChildAt(0)
content.getHitRect(hitRect)
hitRect.contains(x.toInt(), y.toInt())
} else {
false
}
viewGroup?.getHitRect(hitRect)
return hitRect.contains(x.toInt(), y.toInt())
}
}
Loading