Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 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
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
7beb52c
Fixes for PR
gosha212 Feb 3, 2025
b815cab
Merge branch 'master' into feat/rn76-oldarch
gosha212 Feb 3, 2025
960085e
Fixed ios build
gosha212 Feb 3, 2025
465b63c
Test commit
gosha212 Feb 6, 2025
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
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ module.exports = {
plugins: ['@typescript-eslint'],
env: {
jest: true,
'jest/globals': true,
},
};
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,4 @@ Mock.js
Mock.d.ts

Gemfile.lock
/playground/ios/.xcode.env.local
2 changes: 1 addition & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = function (api) {
api && api.cache(false);
return {
presets: ['module:metro-react-native-babel-preset'],
presets: ['module:@react-native/babel-preset'],
plugins: [
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-proposal-export-default-from',
Expand Down
5 changes: 4 additions & 1 deletion 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 } = Utils;
const { elementByLabel, elementById, sleep } = Utils;

describe('static lifecycle events', () => {
beforeEach(async () => {
Expand Down Expand Up @@ -93,6 +93,9 @@ describe('static lifecycle events', () => {
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();
});

Expand Down
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.
44 changes: 29 additions & 15 deletions lib/Mock/Components/ComponentScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { View, Text, TouchableOpacity, Image, ImageURISource} from 'react-native';
import { Navigation, ImageResource} from 'react-native-navigation';
import { View, Text, TouchableOpacity, Image, ImageURISource } from 'react-native';
import { Navigation, ImageResource } from 'react-native-navigation';
import { ComponentProps } from '../ComponentProps';
import { VISIBLE_SCREEN_TEST_ID } from '../constants';
import { LayoutStore } from '../Stores/LayoutStore';
Expand All @@ -10,8 +10,7 @@ import { events } from '../Stores/EventsStore';
import _ from 'lodash';
import { switchTabByIndex } from '../actions/layoutActions';


function isURISource(src: ImageResource| undefined): src is ImageURISource {
function isURISource(src: ImageResource | undefined): src is ImageURISource {
return !!src && typeof src === 'object' && 'uri' in src;
}

Expand All @@ -36,12 +35,15 @@ export const ComponentScreen = connect(
if (bottomTabsOptions?.visible === false) return null;
const buttons = bottomTabs!.children!.map((child, i) => {
const bottomTabOptions = child.resolveOptions().bottomTab;
const icon = (bottomTabs as any).selectedIndex === i ? bottomTabOptions?.selectedIcon : bottomTabOptions?.icon;
const icon =
(bottomTabs as any).selectedIndex === i
? bottomTabOptions?.selectedIcon
: bottomTabOptions?.icon;
const iconURI = isURISource(icon) ? icon.uri : undefined;
return (
<View key={`tab-${i}`}>
<TouchableOpacity
style={{padding:10}}
style={{ padding: 10 }}
testID={bottomTabOptions?.testID}
onPress={() => {
events.invokeBottomTabPressed({
Expand All @@ -51,22 +53,34 @@ export const ComponentScreen = connect(
switchTabByIndex(this.props.layoutNode.getBottomTabs(), i);
}}
>
<View style={{justifyContent: 'center', alignItems: 'center'}}>
<Text>{bottomTabOptions?.badge}</Text>
{iconURI && <Image style={{width: 18, height: 18, marginBottom: 5}} source={{uri: iconURI}}/>}
<Text style={{fontSize: 12}}>{bottomTabOptions?.text || ''}</Text>
</View>
<View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Text>{bottomTabOptions?.badge}</Text>
{iconURI && (
<Image
style={{ width: 18, height: 18, marginBottom: 5 }}
source={{ uri: iconURI }}
/>
)}
<Text style={{ fontSize: 12 }}>{bottomTabOptions?.text || ''}</Text>
</View>
</TouchableOpacity>
</View>
);
});

return (
<View
testID={bottomTabsOptions?.testID}
style={{flexDirection: 'row',justifyContent: 'center', width: '100%', backgroundColor: '#F0F2F5'}}>
<View
testID={bottomTabsOptions?.testID}
style={{
flexDirection: 'row',
justifyContent: 'center',
width: '100%',
backgroundColor: '#F0F2F5',
}}
>
{buttons}
</View>);
</View>
);
}

render() {
Expand Down
4 changes: 2 additions & 2 deletions lib/Mock/Components/LayoutComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export const LayoutComponent = class extends Component<ComponentProps> {
return <View />;
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
const err = new Error(
`Error while trying to render layout ${this.props.layoutNode.nodeId} of type ${this.props.layoutNode.type}: ${error}\n${errorInfo?.componentStack}`,
const err = new Error(
`Error while trying to render layout ${this.props.layoutNode.nodeId} of type ${this.props.layoutNode.type}: ${error}\n${errorInfo?.componentStack}`
);
(err as any).cause = error;
throw err;
Expand Down
1 change: 1 addition & 0 deletions lib/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def DEFAULT_KOTLIN_STDLIB = 'kotlin-stdlib-jdk8'
def kotlinVersion = safeExtGet("RNNKotlinVersion", DEFAULT_KOTLIN_VERSION)
def kotlinStdlib = safeExtGet('RNNKotlinStdlib',DEFAULT_KOTLIN_STDLIB )
def kotlinCoroutinesCore = safeExtGet('RNNKotlinCoroutinesCore', '1.5.2')

android {
namespace 'com.reactnativenavigation'
compileSdkVersion safeExtGetFallbackLowerBound('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.soloader.OpenSourceMergedSoMapping;
import com.facebook.soloader.SoLoader;
import com.reactnativenavigation.react.ReactGateway;
import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -23,7 +25,11 @@ public abstract class NavigationApplication extends Application implements React
public void onCreate() {
super.onCreate();
instance = this;
SoLoader.init(this, false);
try {
SoLoader.init(this, OpenSourceMergedSoMapping.INSTANCE);
} catch (IOException e) {
throw new RuntimeException(e);
}
reactGateway = createReactGateway();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@
import android.os.Bundle;
import android.view.MotionEvent;

import androidx.annotation.RestrictTo;

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;
import com.reactnativenavigation.viewcontrollers.viewcontroller.ScrollEventListener;
import com.reactnativenavigation.react.events.ComponentType;
import com.reactnativenavigation.react.events.EventEmitter;
import com.reactnativenavigation.viewcontrollers.viewcontroller.IReactView;
import com.reactnativenavigation.viewcontrollers.viewcontroller.ScrollEventListener;
import com.reactnativenavigation.views.component.Renderable;

import androidx.annotation.RestrictTo;

@SuppressLint("ViewConstructor")
public class ReactView extends ReactRootView implements IReactView, Renderable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ open class ModalHostLayout(reactContext: ThemedReactContext) : ViewGroup(reactCo
}

@TargetApi(23)
override fun dispatchProvideStructure(structure: ViewStructure?) {
override fun dispatchProvideStructure(structure: ViewStructure) {
mHostView.dispatchProvideStructure(structure)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.views.text.ReactFontManager;
import com.facebook.react.views.text.ReactTextShadowNode;
import java.util.ArrayList;
Expand Down Expand Up @@ -96,12 +97,12 @@ public static Typeface applyStyles(

int want = 0;
if ((weight == Typeface.BOLD)
|| ((oldStyle & Typeface.BOLD) != 0 && weight == ReactTextShadowNode.UNSET)) {
|| ((oldStyle & Typeface.BOLD) != 0 && weight == ReactConstants.UNSET)) {
want |= Typeface.BOLD;
}

if ((style == Typeface.ITALIC)
|| ((oldStyle & Typeface.ITALIC) != 0 && style == ReactTextShadowNode.UNSET)) {
|| ((oldStyle & Typeface.ITALIC) != 0 && style == ReactConstants.UNSET)) {
want |= Typeface.ITALIC;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.reactnativenavigation.utils

import com.facebook.react.views.view.ReactViewBackgroundDrawable
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
import com.facebook.react.views.view.ReactViewGroup

@OptIn(UnstableReactNativeAPI::class)
val ReactViewGroup.borderRadius: Float
get() = (background as? ReactViewBackgroundDrawable)?.fullBorderRadius ?: 0f
get() = (background as? CSSBackgroundDrawable)?.fullBorderWidth ?: 0f
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
import android.view.ViewGroup;
import android.view.ViewParent;

import com.facebook.react.views.view.ReactViewBackgroundDrawable;

import java.util.ArrayList;
import java.util.List;

import androidx.annotation.Nullable;

import static com.reactnativenavigation.utils.ObjectUtils.perform;

import com.facebook.react.common.annotations.UnstableReactNativeAPI;
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable;

public class ViewUtils {
@Nullable
public static <T extends View> T findChildByClass(ViewGroup root, Class<T> clazz) {
Expand Down Expand Up @@ -107,9 +108,10 @@ public static int getIndexInParent(View view) {
return ((ViewGroup) parent).indexOfChild(view);
}

@UnstableReactNativeAPI
public static int getBackgroundColor(View view) {
if (view.getBackground() instanceof ReactViewBackgroundDrawable) {
return ((ReactViewBackgroundDrawable) view.getBackground()).getColor();
if (view.getBackground() instanceof CSSBackgroundDrawable) {
return ((CSSBackgroundDrawable) view.getBackground()).getColor();
}
throw new RuntimeException(view.getBackground().getClass().getSimpleName() + " is not ReactViewBackgroundDrawable");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.reactnativenavigation.viewcontrollers.viewcontroller

import android.annotation.SuppressLint
import com.facebook.react.ReactInstanceManager
import com.facebook.react.modules.i18nmanager.I18nUtil
import com.reactnativenavigation.options.Options

class LayoutDirectionApplier {
fun apply(root: ViewController<*>, options: Options, instanceManager: ReactInstanceManager) {
if (options.layout.direction.hasValue() && instanceManager.currentReactContext != null) {
@SuppressLint("WrongConstant")
fun apply(root: ViewController<*>, options: Options) {
val currentContext = root.view?.context ?: return

if (options.layout.direction.hasValue()) {
root.activity.window.decorView.layoutDirection = options.layout.direction.get()
I18nUtil.getInstance().allowRTL(instanceManager.currentReactContext, options.layout.direction.isRtl)
I18nUtil.getInstance().forceRTL(instanceManager.currentReactContext, options.layout.direction.isRtl)
I18nUtil.instance.allowRTL(currentContext, options.layout.direction.isRtl)
I18nUtil.instance.forceRTL(currentContext, options.layout.direction.isRtl)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public RootPresenter(RootAnimator animator, LayoutDirectionApplier layoutDirecti
}

public void setRoot(ViewController appearingRoot, ViewController<?> disappearingRoot, Options defaultOptions, CommandListener listener, ReactInstanceManager reactInstanceManager) {
layoutDirectionApplier.apply(appearingRoot, defaultOptions, reactInstanceManager);
layoutDirectionApplier.apply(appearingRoot, defaultOptions);
rootLayout.addView(appearingRoot.getView(), matchParentWithBehaviour(new BehaviourDelegate(appearingRoot)));
Options options = appearingRoot.resolveCurrentOptions(defaultOptions);
AnimationOptions enter = options.animations.setRoot.getEnter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@ import android.animation.Animator
import android.animation.ObjectAnimator
import android.view.View
import android.view.ViewGroup
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
import com.facebook.react.views.text.ReactTextView
import com.facebook.react.views.view.ReactViewBackgroundDrawable
import com.reactnativenavigation.options.SharedElementTransitionOptions
import com.reactnativenavigation.utils.*

@OptIn(UnstableReactNativeAPI::class)
class BackgroundColorAnimator(from: View, to: View) : PropertyAnimatorCreator<ViewGroup>(from, to) {
override fun shouldAnimateProperty(fromChild: ViewGroup, toChild: ViewGroup): Boolean {
return fromChild.background is ReactViewBackgroundDrawable &&
toChild.background is ReactViewBackgroundDrawable && (fromChild.background as ReactViewBackgroundDrawable).color != (toChild.background as ReactViewBackgroundDrawable).color
return fromChild.background is CSSBackgroundDrawable &&
toChild.background is CSSBackgroundDrawable && (fromChild.background as CSSBackgroundDrawable).color != (toChild.background as CSSBackgroundDrawable).color
}

override fun excludedViews() = listOf(ReactTextView::class.java)

override fun create(options: SharedElementTransitionOptions): Animator {
val backgroundColorEvaluator = BackgroundColorEvaluator(to.background as ReactViewBackgroundDrawable)
val backgroundColorEvaluator = BackgroundColorEvaluator(to.background as CSSBackgroundDrawable)
val fromColor = ColorUtils.colorToLAB(ViewUtils.getBackgroundColor(from))
val toColor = ColorUtils.colorToLAB(ViewUtils.getBackgroundColor(to))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package com.reactnativenavigation.views.element.animators

import android.animation.TypeEvaluator
import androidx.core.graphics.ColorUtils
import com.facebook.react.views.view.ReactViewBackgroundDrawable
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable

class BackgroundColorEvaluator(private val background: ReactViewBackgroundDrawable) : TypeEvaluator<DoubleArray> {
class BackgroundColorEvaluator @OptIn(UnstableReactNativeAPI::class) constructor(private val background: CSSBackgroundDrawable) : TypeEvaluator<DoubleArray> {
private val color = DoubleArray(3)

@OptIn(UnstableReactNativeAPI::class)
override fun evaluate(ratio: Float, from: DoubleArray, to: DoubleArray): DoubleArray {
ColorUtils.blendLAB(from, to, ratio.toDouble(), color)
background.color = com.reactnativenavigation.utils.ColorUtils.labToColor(color)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,17 @@ class ModalContentLayout(context: Context?) : ReactViewGroup(context), RootView{
updateFirstChildView()
}
}
override fun onChildStartedNativeGesture(child: View, androidEvent: MotionEvent?) {
override fun onChildStartedNativeGesture(child: View, androidEvent: MotionEvent) {
mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, this.getEventDispatcher())
}
override fun onChildStartedNativeGesture(androidEvent: MotionEvent?) {
override fun onChildStartedNativeGesture(androidEvent: MotionEvent) {
mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, this.getEventDispatcher())
}
override fun onChildEndedNativeGesture(child: View, androidEvent: MotionEvent?) {
override fun onChildEndedNativeGesture(child: View, androidEvent: MotionEvent) {
mJSTouchDispatcher.onChildEndedNativeGesture(androidEvent, this.getEventDispatcher())
}
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
private fun getEventDispatcher(): EventDispatcher? {
private fun getEventDispatcher(): EventDispatcher {
val reactContext: ReactContext = this.getReactContext()
return reactContext.getNativeModule(UIManagerModule::class.java)!!.eventDispatcher
}
Expand All @@ -73,12 +73,12 @@ class ModalContentLayout(context: Context?) : ReactViewGroup(context), RootView{
return this.context as ReactContext
}

override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher())
return super.onInterceptTouchEvent(event)
}

override fun onTouchEvent(event: MotionEvent?): Boolean {
override fun onTouchEvent(event: MotionEvent): Boolean {
mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher())
super.onTouchEvent(event)
return true
Expand Down
Loading