Skip to content

Commit

Permalink
chore: restore backward compat for new & old architecture (#2730)
Browse files Browse the repository at this point in the history
## Description

Restoring backward compatibility for old architecture - now we require
76. 75 could work, but I've not tested this.

On new architecture we require 77. It should compile on 76, however we
need the fix for the removal of transitioning views that landed in 77.
See here:
#2596.

## Changes

Described mostly down below 👇🏻 in review comments.

## Checklist

I've tested this manually on fresh RN 76 & 78 app, new/old architecture,
iOS/Android.

- [ ] Ensured that CI passes
  • Loading branch information
kkafar authored Feb 21, 2025
1 parent 8f0975d commit b5a0f9f
Show file tree
Hide file tree
Showing 19 changed files with 164 additions and 61 deletions.
7 changes: 7 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,13 @@ android {
} else {
srcDirs += "src/versioned/backgroundcolor/latest"
}

// Native only classes that use PointerEvents
if (REACT_NATIVE_MINOR_VERSION <= 77) {
srcDirs += "src/versioned/pointerevents/77"
} else {
srcDirs += "src/versioned/pointerevents/latest"
}
}
res {
if (safeExtGet(['compileSdkVersion', 'compileSdk'], rnsDefaultCompileSdkVersion) >= 33) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.WindowInsetsCompat
import com.facebook.react.uimanager.PixelUtil
import com.facebook.react.uimanager.PointerEvents
import com.facebook.react.uimanager.ReactPointerEventsView
import com.facebook.react.uimanager.UIManagerHelper
import com.google.android.material.appbar.AppBarLayout
Expand Down Expand Up @@ -722,9 +721,16 @@ class ScreenStackFragment :
private class ScreensCoordinatorLayout(
context: Context,
private val fragment: ScreenStackFragment,
private val pointerEventsImpl: ReactPointerEventsView,
// ) : CoordinatorLayout(context), ReactCompoundViewGroup, ReactHitSlopView {
) : CoordinatorLayout(context),
ReactPointerEventsView {
ReactPointerEventsView by pointerEventsImpl {
constructor(context: Context, fragment: ScreenStackFragment) : this(
context,
fragment,
ScreensCoordinatorLayoutPointerEventsImpl(),
)

override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets = super.onApplyWindowInsets(insets)

private val animationListener: Animation.AnimationListener =
Expand Down Expand Up @@ -801,11 +807,6 @@ class ScreenStackFragment :
// // bottom – The Y coordinate of the bottom of the rectangle
// return Rect(screen.x.toInt(), -screen.y.toInt(), screen.x.toInt() + screen.width, screen.y.toInt() + screen.height)
// }

// We set pointer events to BOX_NONE, because we don't want the ScreensCoordinatorLayout
// to be target of react gestures and effectively prevent interaction with screens
// underneath the current screen (useful in `modal` & `formSheet` presentation).
override val pointerEvents: PointerEvents = PointerEvents.BOX_NONE
}

private class ScreensAnimation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import android.content.Context
import android.graphics.Color
import android.view.MotionEvent
import android.view.ViewGroup
import com.facebook.react.uimanager.PointerEvents
import com.facebook.react.uimanager.ReactCompoundViewGroup
import com.facebook.react.uimanager.ReactPointerEventsView
import com.swmansion.rnscreens.ext.equalWithRespectToEps
Expand All @@ -17,13 +16,24 @@ import com.swmansion.rnscreens.ext.equalWithRespectToEps
* This dimming view has one more additional feature: it blocks gestures if its alpha > 0.
*/
@SuppressLint("ViewConstructor") // Only we instantiate this view
class DimmingView(
internal class DimmingView(
context: Context,
initialAlpha: Float = 0.6F,
private val pointerEventsProxy: DimmingViewPointerEventsProxy
) : ViewGroup(context),
ReactCompoundViewGroup,
ReactPointerEventsView {
private val blockGestures
ReactPointerEventsView by pointerEventsProxy {

constructor(context: Context, initialAlpha: Float = 0.6F) : this(
context, initialAlpha,
DimmingViewPointerEventsProxy(null)
)

init {
pointerEventsProxy.pointerEventsImpl = DimmingViewPointerEventsImpl(this)
}

internal val blockGestures
get() = !alpha.equalWithRespectToEps(0F)

init {
Expand Down Expand Up @@ -59,8 +69,12 @@ class DimmingView(
y: Float,
) = blockGestures

override val pointerEvents: PointerEvents
get() = if (blockGestures) PointerEvents.AUTO else PointerEvents.NONE
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()

// Break reference cycle, since the pointerEventsImpl strongly retains this.
pointerEventsProxy.pointerEventsImpl = null
}

companion object {
const val TAG = "DimmingView"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
package com.facebook.react.viewmanagers;

import android.view.View;
import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;

public interface RNSScreenContainerManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {

public interface RNSScreenContainerManagerInterface<T extends View> {
// No props
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
package com.facebook.react.viewmanagers;

import android.view.View;
import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;

public interface RNSScreenContentWrapperManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {

public interface RNSScreenContentWrapperManagerInterface<T extends View> {
// No props
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
package com.facebook.react.viewmanagers;

import android.view.View;
import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;

public interface RNSScreenFooterManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {

public interface RNSScreenFooterManagerInterface<T extends View> {
// No props
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;

public interface RNSScreenManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {

public interface RNSScreenManagerInterface<T extends View> {
void setSheetAllowedDetents(T view, @Nullable ReadableArray value);
void setSheetLargestUndimmedDetent(T view, int value);
void setSheetGrabberVisible(T view, boolean value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;

public interface RNSScreenStackHeaderConfigManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {

public interface RNSScreenStackHeaderConfigManagerInterface<T extends View> {
void setBackgroundColor(T view, @Nullable Integer value);
void setBackTitle(T view, @Nullable String value);
void setBackTitleFontFamily(T view, @Nullable String value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;

public interface RNSScreenStackHeaderSubviewManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {

public interface RNSScreenStackHeaderSubviewManagerInterface<T extends View> {
void setType(T view, @Nullable String value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
package com.facebook.react.viewmanagers;

import android.view.View;
import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;

public interface RNSScreenStackManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {

public interface RNSScreenStackManagerInterface<T extends View> {
// No props
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;

public interface RNSSearchBarManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {

public interface RNSSearchBarManagerInterface<T extends View> {
void setHideWhenScrolling(T view, boolean value);
void setAutoCapitalize(T view, @Nullable String value);
void setPlaceholder(T view, @Nullable String value);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.swmansion.rnscreens

import com.facebook.react.uimanager.PointerEvents
import com.facebook.react.uimanager.ReactPointerEventsView

internal class ScreensCoordinatorLayoutPointerEventsImpl : ReactPointerEventsView {
// We set pointer events to BOX_NONE, because we don't want the ScreensCoordinatorLayout
// to be target of react gestures and effectively prevent interaction with screens
// underneath the current screen (useful in `modal` & `formSheet` presentation).
override fun getPointerEvents(): PointerEvents = PointerEvents.BOX_NONE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.swmansion.rnscreens.bottomsheet

import com.facebook.react.uimanager.PointerEvents
import com.facebook.react.uimanager.ReactPointerEventsView
import com.swmansion.rnscreens.bottomsheet.DimmingView


internal class DimmingViewPointerEventsImpl(val dimmingView: DimmingView) : ReactPointerEventsView {
override fun getPointerEvents(): PointerEvents = if (dimmingView.blockGestures == false) PointerEvents.AUTO else PointerEvents.NONE
}

internal class DimmingViewPointerEventsProxy(var pointerEventsImpl: DimmingViewPointerEventsImpl?) :
ReactPointerEventsView {
override fun getPointerEvents(): PointerEvents = pointerEventsImpl?.pointerEvents ?: PointerEvents.NONE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.swmansion.rnscreens

import com.facebook.react.uimanager.PointerEvents
import com.facebook.react.uimanager.ReactPointerEventsView

internal class ScreensCoordinatorLayoutPointerEventsImpl() : ReactPointerEventsView {
// We set pointer events to BOX_NONE, because we don't want the ScreensCoordinatorLayout
// to be target of react gestures and effectively prevent interaction with screens
// underneath the current screen (useful in `modal` & `formSheet` presentation).
override val pointerEvents: PointerEvents = PointerEvents.BOX_NONE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.swmansion.rnscreens.bottomsheet

import com.facebook.react.uimanager.PointerEvents
import com.facebook.react.uimanager.ReactPointerEventsView


internal class DimmingViewPointerEventsImpl(val dimmingView: DimmingView) : ReactPointerEventsView {
override val pointerEvents: PointerEvents
get() = if (dimmingView.blockGestures == false) PointerEvents.AUTO else PointerEvents.NONE
}

internal class DimmingViewPointerEventsProxy(var pointerEventsImpl: DimmingViewPointerEventsImpl?) :
ReactPointerEventsView {
override val pointerEvents: PointerEvents
get() = pointerEventsImpl?.pointerEvents ?: PointerEvents.NONE
}
2 changes: 1 addition & 1 deletion ios/RNSScreenStack.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1232,7 +1232,7 @@ - (void)mountingTransactionDidMount:(const facebook::react::MountingTransaction
withSurfaceTelemetry:(const facebook::react::SurfaceTelemetry &)surfaceTelemetry
{
for (const auto &mutation : transaction.getMutations()) {
if (mutation.parentTag == self.tag &&
if (MUTATION_PARENT_TAG(mutation) == self.tag &&
(mutation.type == react::ShadowViewMutation::Type::Insert ||
mutation.type == react::ShadowViewMutation::Type::Remove)) {
// we need to wait until children have their layout set. At this point they don't have the layout
Expand Down
15 changes: 15 additions & 0 deletions ios/utils/RNSDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,18 @@
_Pragma("clang diagnostic ignored \"-Wobjc-missing-super-calls\"")

#define RNS_IGNORE_SUPER_CALL_END _Pragma("clang diagnostic pop")

#if defined __has_include
#if __has_include( \
<React-RCTAppDelegate/RCTReactNativeFactory.h>) // added in 78
#define RNS_REACT_NATIVE_VERSION_MINOR_BELOW_78 0
#else
#define RNS_REACT_NATIVE_VERSION_MINOR_BELOW_78 1
#endif
#endif

#if RNS_REACT_NATIVE_VERSION_MINOR_BELOW_78
#define MUTATION_PARENT_TAG(mutation) mutation.parentShadowView.tag
#else
#define MUTATION_PARENT_TAG(mutation) mutation.parentTag
#endif
Loading

0 comments on commit b5a0f9f

Please sign in to comment.