Skip to content
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

React Native 0.76.x #7915

Open
1 task
Tracked by #7905
ertugruldogan opened this issue Sep 19, 2024 · 14 comments
Open
1 task
Tracked by #7905

React Native 0.76.x #7915

ertugruldogan opened this issue Sep 19, 2024 · 14 comments

Comments

@ertugruldogan
Copy link

ertugruldogan commented Sep 19, 2024

#7905 previous topic 0.75.x

The Solution for Android 0.76.1

react-native-navigation\lib\android\app\src\main\java\com\reactnativenavigation\utils\ReactTypefaceUtils.java

/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

// This file was copied over from react-native
// to provide backwards compatibility < rn 0.62
//
// TODO: Remove me and use com.facebook.react.views.text.ReactTypefaceUtils
// once we drop support for rn < 0.62

package com.reactnativenavigation.utils;

import android.content.res.AssetManager;
import android.graphics.Typeface;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.views.text.ReactFontManager;
import com.facebook.react.common.ReactConstants;
import java.util.ArrayList;
import java.util.List;

public class ReactTypefaceUtils {
  public static final int UNSET = -1;

  public static int parseFontWeight(@Nullable String fontWeightString) {
    int fontWeightNumeric =
        fontWeightString != null ? parseNumericFontWeight(fontWeightString) : UNSET;
    int fontWeight = fontWeightNumeric != UNSET ? fontWeightNumeric : Typeface.NORMAL;

    if (fontWeight == 700 || "bold".equals(fontWeightString)) fontWeight = Typeface.BOLD;
    else if (fontWeight == 400 || "normal".equals(fontWeightString)) fontWeight = Typeface.NORMAL;

    return fontWeight;
  }

  public static int parseFontStyle(@Nullable String fontStyleString) {
    int fontStyle = UNSET;
    if ("italic".equals(fontStyleString)) {
      fontStyle = Typeface.ITALIC;
    } else if ("normal".equals(fontStyleString)) {
      fontStyle = Typeface.NORMAL;
    }

    return fontStyle;
  }

  public static @Nullable String parseFontVariant(@Nullable ReadableArray fontVariantArray) {
    if (fontVariantArray == null || fontVariantArray.size() == 0) {
      return null;
    }

    List<String> features = new ArrayList<>();
    for (int i = 0; i < fontVariantArray.size(); i++) {
      // see https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist
      String fontVariant = fontVariantArray.getString(i);
      if (fontVariant != null) {
        switch (fontVariant) {
          case "small-caps":
            features.add("'smcp'");
            break;
          case "oldstyle-nums":
            features.add("'onum'");
            break;
          case "lining-nums":
            features.add("'lnum'");
            break;
          case "tabular-nums":
            features.add("'tnum'");
            break;
          case "proportional-nums":
            features.add("'pnum'");
            break;
        }
      }
    }

    return TextUtils.join(", ", features);
  }

  public static Typeface applyStyles(
      @Nullable Typeface typeface,
      int style,
      int weight,
      @Nullable String family,
      AssetManager assetManager) {
    int oldStyle;
    if (typeface == null) {
      oldStyle = 0;
    } else {
      oldStyle = typeface.getStyle();
    }

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

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

    if (family != null) {
      typeface = ReactFontManager.getInstance().getTypeface(family, want, weight, assetManager);
    } else if (typeface != null) {
      // TODO(t9055065): Fix custom fonts getting applied to text children with different style
      typeface = Typeface.create(typeface, want);
    }

    if (typeface != null) {
      return typeface;
    } else {
      return Typeface.defaultFromStyle(want);
    }
  }

  /**
   * Return -1 if the input string is not a valid numeric fontWeight (100, 200, ..., 900), otherwise
   * return the weight.
   */
  private static int parseNumericFontWeight(String fontWeightString) {
    // This should be much faster than using regex to verify input and Integer.parseInt
    return fontWeightString.length() == 3
            && fontWeightString.endsWith("00")
            && fontWeightString.charAt(0) <= '9'
            && fontWeightString.charAt(0) >= '1'
        ? 100 * (fontWeightString.charAt(0) - '0')
        : UNSET;
  }
}

react-native-navigation\lib\android\app\src\main\java\com\reactnativenavigation\utils\ReactViewGroup.kt

package com.reactnativenavigation.utils

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

val ReactViewGroup.borderRadius: Float
    get() =  0f

react-native-navigation\lib\android\app\src\main\java\com\reactnativenavigation\viewcontrollers\viewcontroller\LayoutDirectionApplier.kt

package com.reactnativenavigation.viewcontrollers.viewcontroller

import com.facebook.react.ReactInstanceManager
import com.facebook.react.modules.i18nmanager.I18nUtil
import com.reactnativenavigation.options.Options
import com.facebook.react.bridge.ReactContext

class LayoutDirectionApplier {
    fun apply(root: ViewController<*>, options: Options, instanceManager: ReactInstanceManager) {
        // currentReactContext'in null olup olmadığını kontrol ediyoruz
        val reactContext = instanceManager.currentReactContext as? ReactContext
        if (options.layout.direction.hasValue() && reactContext != null) {
            root.activity.window.decorView.layoutDirection = options.layout.direction.get()
            I18nUtil.getInstance().allowRTL(reactContext, options.layout.direction.isRtl)
            I18nUtil.getInstance().forceRTL(reactContext, options.layout.direction.isRtl)
        }
    }
}

#7930
Hermes Enabled: libhermes_executor.so
Hermes Disabled: libjscexecutor.so
troubleshooting your mistakes
react-native-navigation\lib\android\app\src\main\java\com\reactnativenavigation\NavigationApplication.java

package com.reactnativenavigation;

import android.app.Application;

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

import java.util.HashMap;
import java.util.Map;

import androidx.annotation.NonNull;

public abstract class NavigationApplication extends Application implements ReactApplication {

	private ReactGateway reactGateway;
	public static NavigationApplication instance;
	final Map<String, ExternalComponentCreator> externalComponents = new HashMap<>();

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        try {
            SoLoader.init(this, OpenSourceMergedSoMapping.INSTANCE);
        } catch (Exception e) {
            e.printStackTrace();
        }
        reactGateway = createReactGateway();
    }

    /**
     * Subclasses of NavigationApplication may override this method to create the singleton instance
     * of {@link ReactGateway}. For example, subclasses may wish to provide a custom {@link ReactNativeHost}
     * with the ReactGateway. This method will be called exactly once, in the application's {@link #onCreate()} method.
     *
     * Custom {@link ReactNativeHost}s must be sure to include {@link com.reactnativenavigation.react.NavigationPackage}
     *
     * @return a singleton {@link ReactGateway}
     */
	protected ReactGateway createReactGateway() {
	    return new ReactGateway(getReactNativeHost());
    }
    
	public ReactGateway getReactGateway() {
		return reactGateway;
	}

    /**
     * Generally no need to override this; override for custom permission handling.
     */
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    }

    /**
     * Register a native View which can be displayed using the given {@code name}
     * @param name Unique name used to register the native view
     * @param creator Used to create the view at runtime
     */
    @SuppressWarnings("unused")
    public void registerExternalComponent(String name, ExternalComponentCreator creator) {
        if (externalComponents.containsKey(name)) {
            throw new RuntimeException("A component has already been registered with this name: " + name);
        }
        externalComponents.put(name, creator);
    }

    public final Map<String, ExternalComponentCreator> getExternalComponents() {
        return externalComponents;
    }
}

react-native-navigation\lib\android\app\src\reactNative71\java\com\reactnativenavigation\react\modal\ModalContentLayout.kt

package com.reactnativenavigation.react.modal

import android.content.Context
import android.view.MotionEvent
import android.view.View
import com.facebook.react.bridge.*
import com.facebook.react.uimanager.*
import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.views.view.ReactViewGroup

class ModalContentLayout(context: Context?) : ReactViewGroup(context), RootView {
    private var hasAdjustedSize = false
    private var viewWidth = 0
    private var viewHeight = 0
    private val mJSTouchDispatcher = JSTouchDispatcher(this)

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        viewWidth = w
        viewHeight = h
        this.updateFirstChildView()
    }

    private fun updateFirstChildView() {
        if (this.childCount > 0) {
            hasAdjustedSize = false
            val viewTag = getChildAt(0).id
            val reactContext: ReactContext = this.getReactContext()
            reactContext.runOnNativeModulesQueueThread(object : GuardedRunnable(reactContext) {
                override fun runGuarded() {
                    val uiManager = this@ModalContentLayout.getReactContext().getNativeModule(
                        UIManagerModule::class.java
                    ) as UIManagerModule
                    uiManager.updateNodeSize(
                        viewTag,
                        this@ModalContentLayout.viewWidth,
                        this@ModalContentLayout.viewHeight
                    )
                }
            })
        } else {
            hasAdjustedSize = true
        }
    }

    override fun addView(child: View?, index: Int, params: LayoutParams?) {
        super.addView(child, index, params)
        if (hasAdjustedSize) {
            updateFirstChildView()
        }
    }

    override fun onChildStartedNativeGesture(child: View, androidEvent: MotionEvent?) {
        androidEvent?.let {
            mJSTouchDispatcher.onChildStartedNativeGesture(it, this.getEventDispatcher()!!)
        }
    }

    override fun onChildStartedNativeGesture(androidEvent: MotionEvent?) {
        androidEvent?.let {
            mJSTouchDispatcher.onChildStartedNativeGesture(it, this.getEventDispatcher()!!)
        }
    }

    override fun onChildEndedNativeGesture(child: View, androidEvent: MotionEvent?) {
        androidEvent?.let {
            mJSTouchDispatcher.onChildEndedNativeGesture(it, this.getEventDispatcher()!!)
        }
    }

    override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}

    private fun getEventDispatcher(): EventDispatcher? {
        val reactContext: ReactContext = this.getReactContext()
        return reactContext.getNativeModule(UIManagerModule::class.java)?.eventDispatcher
    }

    override fun handleException(t: Throwable?) {
        getReactContext().handleException(RuntimeException(t))
    }

    private fun getReactContext(): ReactContext {
        return this.context as ReactContext
    }

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

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        event?.let {
            mJSTouchDispatcher.handleTouchEvent(it, getEventDispatcher()!!)
        }
        super.onTouchEvent(event)
        return true
    }
}

react-native: 0.76.1
react-native-navigation: 7.40.3
java: 17
node: 22.5.1
gradle: 8.10
buildToolsVersion = "35.0.0"
minSdkVersion = 24 (react-native-community/discussions-and-proposals#802)
compileSdkVersion = 35
targetSdkVersion = 35
ndkVersion = "27.0.12077973"
kotlinVersion = "2.0.20"

android\gradle.properties
newArchEnabled=false RN 0.76.x by default, it comes true.
hermesEnabled=true

It has only been tested for Android.

Tasks

Preview Give feedback
  1. 0 of 1
    platform: Android type: accepted/bug
@gusilveiramp
Copy link

+1

@gusilveiramp
Copy link

@ertugruldogan any solution?

@ertugruldogan
Copy link
Author

RN v0.76.1 or v0.76.2 I can get it resolved.
React Native 0.75.x there may be problems, including.
It seems as if React-Native-Navigation support is little sought after by the community.

@MohamedAbdElNaby
Copy link

@ertugruldogan are you solve RN V0.76.0
i upgrade from 0.75.4 to 0.76.0 the app crashed when i run it

@ertugruldogan
Copy link
Author

@ertugruldogan are you solve RN V0.76.0 i upgrade from 0.75.4 to 0.76.0 the app crashed when i run it

Not only react-native-navigation library but also many other libraries are currently incompatible. Error details are needed. I suggest you wait for 0.76.1 and 0.76.2.

@MohamedAbdElNaby
Copy link

@ertugruldogan ok thank you

@MohamedAbdElNaby
Copy link

MohamedAbdElNaby commented Nov 4, 2024

@ertugruldogan
I'm reaching out to check if there have been any updates or changes regarding my issue?!

@enahum
Copy link

enahum commented Nov 9, 2024

Any updatrs? And are you looking into enabling the new arch now that is the default?

@MohamedAbdElNaby
Copy link

MohamedAbdElNaby commented Nov 10, 2024

this work with new arch
for android but ios dosnt work with me

@ertugruldogan
Copy link
Author

The Solution for Android 0.76.1
It has been updated.

@MohamedAbdElNaby
Copy link

ertugruldogan any updates for ios ?

@d4vidi
Copy link
Collaborator

d4vidi commented Nov 27, 2024

This is great stuff, everyone. We'll get to working on all of this soon, under #7941

@AdrienPoupa
Copy link

The lack of activity on this (not even merging ready to go PRs when the project fails to compile for the last 2 RN releases) simply shows that Wix no longer considers RNN as a priority. We'll probably migrate to React Navigation as a result.

@rendomnet
Copy link

@d4vidi @MohamedAbdElNaby

Is react-native-navigation functioning correctly with React-native 0.76.3? I wasn’t able to make it work on a blank React-native 0.76.3 setup.

https://github.com/rendomnet/repro-bug-rnn

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants