Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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,
},
};
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
3 changes: 2 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,7 @@ 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();
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
3 changes: 3 additions & 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 Expand Up @@ -214,5 +215,7 @@ dependencies {
testImplementation 'org.mockito:mockito-inline:3.4.0'
testImplementation "org.mockito.kotlin:mockito-kotlin:4.0.0"
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
testImplementation "io.mockk:mockk:1.13.16"

}
}
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 @@ -9,6 +9,7 @@
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags;
import com.facebook.react.uimanager.JSTouchDispatcher;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.EventDispatcher;
Expand All @@ -35,7 +36,7 @@ public ReactView(final Context context, ReactInstanceManager reactInstanceManage
this.componentId = componentId;
this.componentName = componentName;
jsTouchDispatcher = new JSTouchDispatcher(this);
setIsFabric(ReactFeatureFlags.enableFabricRenderer);
setIsFabric(ReactNativeFeatureFlags.enableFabricRenderer());
}

@Override
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
Loading