Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
2a776db
Upgraded android to work with rn 77
gosha212 Jan 27, 2025
100dd5b
Upgraded to the latest version of detox
gosha212 Jan 27, 2025
c742e3b
Added react types.
gosha212 Jan 27, 2025
aee806a
Updated pod filke
gosha212 Jan 27, 2025
cacd4fe
Fixed es lint error
gosha212 Jan 27, 2025
419eed1
Upgraded reanimated
gosha212 Jan 27, 2025
6f2ca4c
Fixed ios build
gosha212 Jan 27, 2025
fd97ab2
Fixed ios build
gosha212 Jan 27, 2025
5dcf7c6
Fixed one test in android
gosha212 Jan 27, 2025
cc25411
Fixed android tests
gosha212 Jan 27, 2025
e036898
Fixed android unit tests
gosha212 Jan 27, 2025
24144b1
Fixed android unit tests
gosha212 Jan 28, 2025
68cce81
Fixed android tests
gosha212 Jan 28, 2025
534dbb7
Fixed mocked tests
gosha212 Jan 28, 2025
a1a64a6
Implemented new arch support for android
gosha212 Jan 28, 2025
4763f14
Added new version of detox to support new arch
gosha212 Jan 28, 2025
e719a90
Downgrade to RN 76
gosha212 Jan 29, 2025
ff9ed27
support ios
gosha212 Jan 29, 2025
7183b68
fixed android screenshot
gosha212 Jan 29, 2025
550a73f
fixed android screenshot
gosha212 Jan 29, 2025
81f1eb6
Reimplemented missing bar style in iOS
gosha212 Jan 30, 2025
2000684
Reimplemented missing bar style in iOS
gosha212 Jan 30, 2025
6b32776
Fixed ios bar styling
gosha212 Jan 30, 2025
560f994
Removed unused library
gosha212 Jan 30, 2025
1ed449b
Upgraded roboletric to run on updated sdk
gosha212 Jan 30, 2025
a199c01
Revert "Upgraded roboletric to run on updated sdk"
gosha212 Jan 30, 2025
23dace4
Merge rn76 old arch branch
gosha212 Feb 2, 2025
e4a46bf
Merge branch 'master' into feat/rn77-android-newarch
gosha212 Feb 6, 2025
8227eb6
Fixed ios build
gosha212 Feb 6, 2025
13c2b9e
Fixed android modal
gosha212 Feb 16, 2025
4bf2c81
Removed UI lib from the project and fixed broken tests
gosha212 Feb 18, 2025
847350e
Trying to fix android unit tests
gosha212 Feb 18, 2025
a47d03b
Fixing android test
gosha212 Feb 19, 2025
3cc6222
Merge branch 'master' into feat/rn77-android-newarch
gosha212 Feb 19, 2025
efba014
Updated package lock
gosha212 Feb 19, 2025
9e31d4f
Ignored android unit tests
gosha212 Feb 19, 2025
fc004d0
Fixed e2e test for android
gosha212 Feb 19, 2025
570d31f
Fixed tests
gosha212 Feb 19, 2025
15fdf3b
Fixed screenshot tolerance
gosha212 Feb 20, 2025
9cefa10
Fixed screenshot tolerance
gosha212 Feb 20, 2025
6acac33
Fixed screenshot tolerance algorithm
gosha212 Feb 20, 2025
6e316b1
Fixed screenshots for genymotion
gosha212 Feb 20, 2025
bbfa701
Fixed modal test
gosha212 Feb 20, 2025
07c6ae1
Update lib/android/app/src/main/java/com/reactnativenavigation/react/…
gosha212 Mar 23, 2025
43d3785
Update lib/android/app/src/main/java/com/reactnativenavigation/option…
gosha212 Mar 23, 2025
00f52a6
Update lib/android/app/src/main/java/com/reactnativenavigation/option…
gosha212 Mar 23, 2025
4b12594
Update playground/android/settings.gradle
gosha212 Mar 23, 2025
7471e36
Fixes after PR
gosha212 Mar 23, 2025
1df9f51
Merge branch 'master' into feat/rn77-android-newarch
gosha212 Mar 23, 2025
d097e75
Fixed android build
gosha212 Mar 23, 2025
b1780eb
Fixed compilation error
gosha212 Apr 6, 2025
fedaf89
Merge remote-tracking branch 'origin/feat/rn77-android-newarch' into …
gosha212 Apr 6, 2025
e11fd53
Fixed typing issue
gosha212 Apr 10, 2025
6dd5e1b
RN 77 Upgrade iOS(#8018)
kochavi-daniel May 15, 2025
dcf82bc
Merge branch 'master' into feat/rn77-android-newarch
gosha212 May 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module.exports = {
root: true,
extends: ['@react-native-community', 'prettier', 'prettier/@typescript-eslint', 'prettier/react'],
extends: ['@react-native', 'prettier', 'prettier/@typescript-eslint', 'prettier/react'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
env: {
jest: true,
'jest/globals': true,
},
};

25 changes: 13 additions & 12 deletions ReactNativeNavigation.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,21 @@ 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,cpp}'
s.source_files = 'lib/ios/**/*.{h,m,mm,cpp}'
s.exclude_files = "lib/ios/ReactNativeNavigationTests/**/*.*", "lib/ios/OCMock/**/*.*"
end

if fabric_enabled
install_modules_dependencies(s)

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 = {
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32 -DFOLLY_CFG_NO_COROUTINES=1'
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" "$(PODS_ROOT)/Headers/Private/Yoga"',
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
}
}

if fabric_enabled
install_modules_dependencies(s)

s.compiler_flags = folly_compiler_flags + ' ' + '-DRCT_NEW_ARCH_ENABLED'
s.compiler_flags = folly_compiler_flags + ' ' + '-DRCT_NEW_ARCH_ENABLED' + ' ' + '-DUSE_HERMES=1'
s.requires_arc = true

s.dependency "React"
Expand All @@ -46,9 +44,12 @@ Pod::Spec.new do |s|
s.dependency "RCT-Folly"
s.dependency "RCTRequired"
s.dependency "RCTTypeSafety"
s.dependency "ReactCommon/turbomodule/core"
s.dependency "ReactCommon"
s.dependency "React-runtimeexecutor"
s.dependency "React-rncore"
s.dependency "React-RuntimeCore"
else
s.compiler_flags = folly_compiler_flags
end

s.dependency 'React-Core'
Expand Down
24 changes: 12 additions & 12 deletions autolink/postlink/__snapshots__/appDelegateLinker.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`appDelegateLinker should work for RN 0.68 1`] = `
"#import \\"AppDelegate.h\\"
"#import "AppDelegate.h"
#import <ReactNativeNavigation/ReactNativeNavigation.h>

#import <React/RCTBridge.h>
Expand Down Expand Up @@ -40,7 +40,7 @@ exports[`appDelegateLinker should work for RN 0.68 1`] = `
#if RCT_NEW_ARCH_ENABLED
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
_contextContainer->insert(\\"ReactNativeConfig\\", _reactNativeConfig);
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
#endif
Expand All @@ -55,9 +55,9 @@ exports[`appDelegateLinker should work for RN 0.68 1`] = `
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@\\"index\\"];
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return [[NSBundle mainBundle] URLForResource:@\\"main\\" withExtension:@\\"jsbundle\\"];
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

Expand Down Expand Up @@ -105,7 +105,7 @@ exports[`appDelegateLinker should work for RN 0.68 1`] = `
`;

exports[`appDelegateLinker should work for RN 0.69 1`] = `
"#import \\"AppDelegate.h\\"
"#import "AppDelegate.h"
#import <ReactNativeNavigation/ReactNativeNavigation.h>

#import <React/RCTBridge.h>
Expand All @@ -123,7 +123,7 @@ exports[`appDelegateLinker should work for RN 0.69 1`] = `

#import <react/config/ReactNativeConfig.h>

static NSString *const kRNConcurrentRoot = @\\"concurrentRoot\\";
static NSString *const kRNConcurrentRoot = @"concurrentRoot";

@interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
RCTTurboModuleManager *_turboModuleManager;
Expand All @@ -146,7 +146,7 @@ static NSString *const kRNConcurrentRoot = @\\"concurrentRoot\\";
#if RCT_NEW_ARCH_ENABLED
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
_contextContainer->insert(\\"ReactNativeConfig\\", _reactNativeConfig);
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
#endif
Expand Down Expand Up @@ -183,9 +183,9 @@ static NSString *const kRNConcurrentRoot = @\\"concurrentRoot\\";
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@\\"index\\"];
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return [[NSBundle mainBundle] URLForResource:@\\"main\\" withExtension:@\\"jsbundle\\"];
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

Expand Down Expand Up @@ -233,7 +233,7 @@ static NSString *const kRNConcurrentRoot = @\\"concurrentRoot\\";
`;

exports[`appDelegateLinker should work for RN 0.71 1`] = `
"#import \\"AppDelegate.h\\"
"#import "AppDelegate.h"
#import <ReactNativeNavigation/ReactNativeNavigation.h>

#import <React/RCTBundleURLProvider.h>
Expand All @@ -249,9 +249,9 @@ exports[`appDelegateLinker should work for RN 0.71 1`] = `
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@\\"index\\"];
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return [[NSBundle mainBundle] URLForResource:@\\"main\\" withExtension:@\\"jsbundle\\"];
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

Expand Down
20 changes: 9 additions & 11 deletions e2e/Modals.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,27 +149,25 @@ describe('modal', () => {
await elementById(TestIDs.MODAL_BTN).tap();

await expect(elementByLabel('showModal promise resolved with: UniqueStackId')).toBeVisible();
await expect(
elementByLabel('modalDismissed listener called with with: UniqueStackId')
).toBeVisible();
await expect(elementByLabel('modalDismissed listener called with with: UniqueStackId')).toBeVisible();
await expect(elementByLabel('dismissModal promise resolved with: UniqueStackId')).toBeVisible();
});

it.e2e('should show declared modal', async () => {
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await expect(elementByLabel('Dismiss declared Modal')).toBeVisible();
await expect(elementById(TestIDs.DISMISS_REACT_MODAL_BTN)).toBeVisible();
await elementById(TestIDs.DISMISS_REACT_MODAL_BTN).tap();
await expect(elementById(TestIDs.MODAL_SCREEN_HEADER)).toBeVisible();
});

it.e2e('should show and dismiss multiple modals including declared modal', async () => {
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await elementById(TestIDs.SHOW_MODAL_FROM_DECLARED_BUTTON).tap();
await expect(elementByLabel('Toggle declared modal')).toBeVisible();
await expect(elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL)).toBeVisible();
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await elementById(TestIDs.DISMISS_REACT_MODAL_BTN).tap();
await elementById(TestIDs.DISMISS_MODAL_BTN).tap();
await expect(elementByLabel('Dismiss declared Modal')).toBeVisible();
await expect(elementById(TestIDs.DISMISS_REACT_MODAL_BTN)).toBeVisible();
await elementById(TestIDs.DISMISS_REACT_MODAL_BTN).tap();

await expect(elementById(TestIDs.MODAL_SCREEN_HEADER)).toBeVisible();
Expand All @@ -178,11 +176,11 @@ describe('modal', () => {
it.e2e('overlay should be on top of all modals', async () => {
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await elementById(TestIDs.OVERLAY_BTN).tap();
await expect(elementByLabel('Dismiss declared Modal')).toBeVisible();
await expect(elementById(TestIDs.DISMISS_REACT_MODAL_BTN)).toBeVisible();
await expect(elementById(TestIDs.DISMISS_ALL_OVERLAYS_BUTTON)).toBeVisible();

await elementById(TestIDs.SHOW_MODAL_FROM_DECLARED_BUTTON).tap();
await expect(elementByLabel('Modal Lifecycle')).toBeVisible();
await expect(elementById(TestIDs.MODAL_LIFECYCLE_BTN)).toBeVisible();

await elementById(TestIDs.DISMISS_MODAL_BTN).tap();
await elementById(TestIDs.DISMISS_REACT_MODAL_BTN).tap();
Expand All @@ -193,15 +191,15 @@ describe('modal', () => {
it.e2e(':android: should handle back properly', async () => {
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await elementById(TestIDs.SHOW_MODAL_FROM_DECLARED_BUTTON).tap();
await expect(elementByLabel('Toggle declared modal')).toBeVisible();
await expect(elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL)).toBeVisible();

await Android.pressBack();

await expect(elementByLabel('Dismiss declared Modal')).toBeVisible();
await expect(elementById(TestIDs.DISMISS_REACT_MODAL_BTN)).toBeVisible();

await Android.pressBack();

await expect(elementByLabel('Toggle declared modal')).toBeVisible();
await expect(elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL)).toBeVisible();
});

it.e2e('dismiss modal with side menu', async () => {
Expand Down
2 changes: 1 addition & 1 deletion e2e/SideMenu.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('SideMenu', () => {
it.e2e('should change left drawer width', async () => {
await elementById(TestIDs.CHANGE_LEFT_SIDE_MENU_WIDTH_BTN).tap();
await elementById(TestIDs.OPEN_LEFT_SIDE_MENU_BTN).tap();
await expect(elementByLabel('left drawer width: 50')).toBeVisible();
await expect(elementByLabel('left drawer width: 100')).toBeVisible();
});

it.e2e('should set right drawer width', async () => {
Expand Down
10 changes: 4 additions & 6 deletions e2e/StaticLifecycleEvents.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Utils from './Utils';
import TestIDs from '../playground/src/testIDs';

const { elementByLabel, elementById, sleep } = Utils;
const { elementByLabel, elementById } = Utils;

describe('static lifecycle events', () => {
beforeEach(async () => {
Expand Down Expand Up @@ -89,14 +89,12 @@ describe('static lifecycle events', () => {
).toBeVisible();
});

it('unmounts previous root before resolving setRoot promise', async () => {
it.e2e('unmounts previous root before resolving setRoot promise', async () => {
await elementById(TestIDs.SET_ROOT_BTN).tap();
await elementById(TestIDs.CLEAR_OVERLAY_EVENTS_BTN).tap();
await elementById(TestIDs.SET_ROOT_BTN).tap();
// This sleep is needed in order to synchronize the test rendered with state changes. We can remove it after moving
// our mock to work with act(()=>{}) from react-test-renderer
await sleep(10);
await expect(elementByLabel('setRoot complete - previous root is unmounted')).toBeVisible();
await expect(elementByLabel('setRoot complete')).toBeVisible();
await expect(elementByLabel('component unmounted')).toBeVisible();
});

it('top bar custom button willAppear didAppear after pop, on a root screen', async () => {
Expand Down
60 changes: 44 additions & 16 deletions e2e/Utils.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
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 });

return pixelmatch(img1.data, img2.data, diff.data, width, height, { threshold: 0.0 });
import { PNG } from 'pngjs';
import { ssim } from 'ssim.js';

const SSIM_SCORE_THRESHOLD = 0.997;

function convertToSSIMFormat(image) {
return {
data: new Uint8ClampedArray(image.data),
width: image.width,
height: image.height
}
;
}

function loadImage(path) {
const image = PNG.sync.read(readFileSync(path));

return convertToSSIMFormat(image);
}

function bitmapDiff(imagePath, expectedImagePath, ssimThreshold = SSIM_SCORE_THRESHOLD) {
const image = loadImage(imagePath);
const expectedImage = loadImage(expectedImagePath);

const { mssim, performance } = ssim(image, expectedImage);

if (mssim < ssimThreshold) {
throw new Error(
`Expected bitmaps at '${imagePath}' and '${expectedImagePath}' to have an SSIM score ` +
`of at least ${SSIM_SCORE_THRESHOLD}, but got ${mssim}. This means the snapshots are different ` +
`(comparison took ${performance}ms)`,
);
}
}

const utils = {
elementByLabel: (label) => {
// uncomment for running tests with rn's new arch
Expand All @@ -35,16 +60,19 @@ 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}`);
}
bitmapDiff(imagePath, expectedImagePath);

},
expectImagesToBeNotEqual: (imagePath, expectedImagePath) => {
let diff = bitmapDiff(imagePath, expectedImagePath);
if (diff === 0) {
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`);
try {
bitmapDiff(imagePath, expectedImagePath);
} catch (error) {
return
}

throw new Error(
`Expected bitmaps at '${imagePath}' and '${expectedImagePath}' to be different`,
);
},
};

Expand Down
Binary file modified e2e/assets/buttons_navbar.android.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified e2e/assets/buttons_navbar.ios.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified e2e/assets/overlay_banner_padding.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion index.e2e.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "setimmediate";
import { LogBox } from 'react-native';
LogBox.ignoreAllLogs();

LogBox.ignoreAllLogs();
require('./playground/index');
11 changes: 10 additions & 1 deletion lib/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: "com.facebook.react"


react {
jsRootDir = file("../../src/")
libraryName = "rnnavigation"
codegenJavaPackageName = "com.reactnativenavigation.react"
}


def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
Expand Down Expand Up @@ -193,7 +202,7 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesCore"
implementation "androidx.constraintlayout:constraintlayout:2.0.4"

implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.annotation:annotation:1.2.0'
implementation 'com.google.android.material:material:1.2.0-alpha03'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void onCreate() {
* @return a singleton {@link ReactGateway}
*/
protected ReactGateway createReactGateway() {
return new ReactGateway(getReactNativeHost());
return new ReactGateway(getReactHost(), getReactNativeHost());
}

public ReactGateway getReactGateway() {
Expand Down
Loading
Loading