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

feat: refactor snapshots when going back on Fabric #2134

Merged
merged 26 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b975b0e
feat: first look at working version on fabric
WoLewicki May 14, 2024
639b67d
feat: move listener to cpp folder
WoLewicki May 15, 2024
dae22d1
chore: dont build from sources
WoLewicki May 15, 2024
ef3baa4
chore: merge current main
WoLewicki May 15, 2024
1e2bebb
feat: rename listeners and remove code handling it in ScreenStack
WoLewicki May 15, 2024
d1af500
chore: move listeners to cpp on Android
WoLewicki May 15, 2024
99be7d1
chore: merge current main
WoLewicki May 15, 2024
ca2f34e
feat: make it work on both platforms and archs
WoLewicki May 16, 2024
3de04f5
chore: format all cpp
WoLewicki May 16, 2024
7909666
fix: indents and comment and restore init in other place
WoLewicki May 16, 2024
7cf4390
chore: merge current main
WoLewicki May 17, 2024
05dfb34
fix: clean up cmakelists
WoLewicki May 17, 2024
16f9498
fix: swipe refresh case
WoLewicki Jun 10, 2024
8fd8ae7
chore: merge current main
WoLewicki Jun 10, 2024
33a6ac5
Merge branch 'main' into @wolewicki/fix-android-fabric-goback
WoLewicki Jun 11, 2024
f467091
Merge branch 'main' into @wolewicki/fix-android-fabric-goback
WoLewicki Jun 12, 2024
b28c1c5
fix: hopefully working version
WoLewicki Jun 13, 2024
18a7aaa
feat: use ConcurrentHashMap
WoLewicki Jun 14, 2024
c8e4ba7
chore: merge current main
WoLewicki Jul 16, 2024
31c2f2e
feat: apply review comments
WoLewicki Jul 16, 2024
1019731
fix: review
WoLewicki Jul 17, 2024
d0c24ff
fix: android header buttons
WoLewicki Jul 19, 2024
bd7a30e
Merge branch 'main' into @wolewicki/fix-android-fabric-goback
WoLewicki Jul 19, 2024
8dfcdb0
chore: merge current main
WoLewicki Jul 31, 2024
e127cde
chore: format
WoLewicki Jul 31, 2024
0cfd980
fix: revert changing react-navigation
WoLewicki Jul 31, 2024
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
2 changes: 1 addition & 1 deletion FabricTestExample/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ GEM
i18n (1.14.5)
concurrent-ruby (~> 1.0)
json (2.7.2)
minitest (5.22.3)
minitest (5.22.2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's going on here, why do we change that?

molinillo (0.8.0)
nanaimo (0.3.0)
nap (1.1.0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
/* Begin PBXBuildFile section */
00E356F31AD99517003FC87E /* FabricTestExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* FabricTestExampleTests.m */; };
0C80B921A6F3F58F76C31292 /* libPods-FabricTestExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-FabricTestExample.a */; };
0C8DC70031F6A0EB3918E89A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 80611F1F396BDF1BBA4C9072 /* PrivacyInfo.xcprivacy */; };
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
7699B88040F8A987B510C191 /* libPods-FabricTestExample-FabricTestExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-FabricTestExample-FabricTestExampleTests.a */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
C96B4031A93002B8F66309BB /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = F2DBEFF9ED5BC3397C47CBFB /* PrivacyInfo.xcprivacy */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -43,10 +43,10 @@
5709B34CF0A7D63546082F79 /* Pods-FabricTestExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FabricTestExample.release.xcconfig"; path = "Target Support Files/Pods-FabricTestExample/Pods-FabricTestExample.release.xcconfig"; sourceTree = "<group>"; };
5B7EB9410499542E8C5724F5 /* Pods-FabricTestExample-FabricTestExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FabricTestExample-FabricTestExampleTests.debug.xcconfig"; path = "Target Support Files/Pods-FabricTestExample-FabricTestExampleTests/Pods-FabricTestExample-FabricTestExampleTests.debug.xcconfig"; sourceTree = "<group>"; };
5DCACB8F33CDC322A6C60F78 /* libPods-FabricTestExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-FabricTestExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
80611F1F396BDF1BBA4C9072 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = FabricTestExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = FabricTestExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
89C6BE57DB24E9ADA2F236DE /* Pods-FabricTestExample-FabricTestExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FabricTestExample-FabricTestExampleTests.release.xcconfig"; path = "Target Support Files/Pods-FabricTestExample-FabricTestExampleTests/Pods-FabricTestExample-FabricTestExampleTests.release.xcconfig"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
F2DBEFF9ED5BC3397C47CBFB /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = FabricTestExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -96,7 +96,7 @@
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
13B07FB71A68108700A75B9A /* main.m */,
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
80611F1F396BDF1BBA4C9072 /* PrivacyInfo.xcprivacy */,
F2DBEFF9ED5BC3397C47CBFB /* PrivacyInfo.xcprivacy */,
);
name = FabricTestExample;
sourceTree = "<group>";
Expand Down Expand Up @@ -248,7 +248,7 @@
files = (
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
0C8DC70031F6A0EB3918E89A /* PrivacyInfo.xcprivacy in Resources */,
C96B4031A93002B8F66309BB /* PrivacyInfo.xcprivacy in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion FabricTestExample/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1568,4 +1568,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 67b3d295da87c29349179e51bb3526b67059b646

COCOAPODS: 1.15.2
COCOAPODS: 1.14.3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we shouldn't introduce some policy of using chosen version of cocoapods to omit this sort of changes from Podfiles 🤔 what do you think?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, would be nice to just hardcode it so it does not land in many PRs by mistake

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This depends on cocoapods version you have installed locally I believe. I don't think we should include this in your PR, especially that it's a lower version, and there should be no need to downgrade.

2 changes: 1 addition & 1 deletion RNScreens.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package = JSON.parse(File.read(File.join(__dir__, "package.json")))

new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
platform = new_arch_enabled ? "11.0" : "9.0"
source_files = new_arch_enabled ? 'ios/**/*.{h,m,mm,cpp}' : ["ios/**/*.{h,m,mm}", "cpp/**/*.{cpp,h}"]
source_files = new_arch_enabled ? 'ios/**/*.{h,m,mm,cpp}' : ["ios/**/*.{h,m,mm}", "cpp/RNScreensTurboModule.cpp", "cpp/RNScreensTurboModule.h"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we're not scoping all .cpp and .h files right now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the new files added to the folder should not be compiled on old arch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's worth to consider grouping the files. E.g. place screen-transition related staff in a cpp/transition / cpp/turbomodule directory & new screen listeners into cpp/mounting or sth similar.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do a cleanup of those in the follow-up PR?


folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'

Expand Down
53 changes: 44 additions & 9 deletions android/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,27 +1,62 @@
cmake_minimum_required(VERSION 3.9.0)

project(rnscreens)
set(CMAKE_CXX_STANDARD 20)

if(${IS_NEW_ARCHITECTURE_ENABLED})
add_library(rnscreens
SHARED
../cpp/RNScreensTurboModule.cpp
../cpp/RNSScreenRemovalListener.cpp
./src/main/cpp/jni-adapter.cpp
./src/main/cpp/NativeProxy.cpp
./src/main/cpp/OnLoad.cpp
)
else()
add_library(rnscreens
SHARED
../cpp/RNScreensTurboModule.cpp
./src/main/cpp/jni-adapter.cpp
)
endif()

include_directories(
../cpp
)

set_target_properties(rnscreens PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we replace setting properties on particular target with setting the non-target-scoped variable CMAKE_CXX_STANDARD? Also why do we drop standard requirement, turning off extensions and enabling -fpic explicitly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why I removed it, reverted.

target_compile_definitions(
rnscreens
PRIVATE
-DFOLLY_NO_CONFIG=1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
-DFOLLY_NO_CONFIG=1
FOLLY_NO_CONFIG=1

I believe you can omit -D prefix in target_compile_definition (link)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't work if I remove it so I think it is not true.

Copy link
Member

@kkafar kkafar Jul 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not gonna lie, I'm surprised as CMake docs I've linked explicitly state that you can omit -D, but that's a nitpick anyway, we can proceed w/o this change.

)

find_package(ReactAndroid REQUIRED CONFIG)

target_link_libraries(rnscreens
ReactAndroid::jsi
android
)
if(${IS_NEW_ARCHITECTURE_ENABLED})
find_package(fbjni REQUIRED CONFIG)

target_link_libraries(
rnscreens
ReactAndroid::jsi
ReactAndroid::react_nativemodule_core
ReactAndroid::react_utils
ReactAndroid::reactnativejni
ReactAndroid::fabricjni
ReactAndroid::react_debug
ReactAndroid::react_render_core
ReactAndroid::runtimeexecutor
ReactAndroid::react_render_graphics
ReactAndroid::rrc_view
ReactAndroid::yoga
ReactAndroid::rrc_text
ReactAndroid::glog
ReactAndroid::react_render_componentregistry
fbjni::fbjni
android
)
WoLewicki marked this conversation as resolved.
Show resolved Hide resolved
else()
target_link_libraries(rnscreens
ReactAndroid::jsi
android
)
endif()
11 changes: 7 additions & 4 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def reactProperties = new Properties()
file("$reactNativeRootDir/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }
def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME")
def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger()
def IS_NEW_ARCHITECTURE_ENABLED = isNewArchitectureEnabled()

android {
compileSdkVersion safeExtGet('compileSdkVersion', rnsDefaultCompileSdkVersion)
Expand All @@ -102,13 +103,14 @@ android {
targetSdkVersion safeExtGet('targetSdkVersion', rnsDefaultTargetSdkVersion)
versionCode 1
versionName "1.0"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", IS_NEW_ARCHITECTURE_ENABLED.toString()
ndk {
abiFilters (*reactNativeArchitectures())
}
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"
arguments "-DANDROID_STL=c++_shared",
"-DIS_NEW_ARCHITECTURE_ENABLED=${IS_NEW_ARCHITECTURE_ENABLED}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"-DIS_NEW_ARCHITECTURE_ENABLED=${IS_NEW_ARCHITECTURE_ENABLED}"
"-DRNS_NEW_ARCH_ENABLED=${IS_NEW_ARCHITECTURE_ENABLED}"

won't insist here, my only intention is to keep it consistent with iOS (I believe we even use RCT_ prefix there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
}
}
Expand Down Expand Up @@ -139,13 +141,14 @@ android {
"META-INF/**",
"**/libjsi.so",
"**/libc++_shared.so",
"**/libreact_render*.so"
"**/libreact_render*.so",
"**/libreactnativejni.so"
]
}
sourceSets.main {
ext.androidResDir = "src/main/res"
java {
if (isNewArchitectureEnabled()) {
if (IS_NEW_ARCHITECTURE_ENABLED) {
srcDirs += [
"src/fabric/java",
]
Expand Down
49 changes: 49 additions & 0 deletions android/src/fabric/java/com/swmansion/rnscreens/NativeProxy.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.swmansion.rnscreens

import android.util.Log
import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.fabric.FabricUIManager
import java.lang.ref.WeakReference
import java.util.concurrent.ConcurrentHashMap

class NativeProxy {
@DoNotStrip
@Suppress("unused")
private val mHybridData: HybridData

init {
mHybridData = initHybrid()
}

private external fun initHybrid(): HybridData
external fun nativeAddMutationsListener(fabricUIManager: FabricUIManager)

companion object {
// we use ConcurrentHashMap here since it will be read on the JS thread,
// and written to on the UI thread.
private val viewsMap = ConcurrentHashMap<Int, WeakReference<Screen>>()

fun addScreenToMap(tag: Int, view: Screen) {
viewsMap[tag] = WeakReference(view)
}

fun removeScreenFromMap(tag: Int) {
viewsMap.remove(tag)
}

fun clearMapOnInvalidate() {
viewsMap.clear()
}
}

@DoNotStrip
public fun notifyScreenRemoved(screenTag: Int) {
val screen = viewsMap[screenTag]?.get()
if (screen is Screen) {
screen.startRemovalTransition()
} else {
Log.w("[RNScreens]", "Did not find view with tag ${screenTag}.")
}
}
}
51 changes: 51 additions & 0 deletions android/src/main/cpp/NativeProxy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <fbjni/fbjni.h>
#include <react/fabric/Binding.h>
#include <react/renderer/scheduler/Scheduler.h>

#include <string>

#include "NativeProxy.h"

using namespace facebook;
using namespace react;

namespace rnscreens {

NativeProxy::NativeProxy(jni::alias_ref<NativeProxy::javaobject> jThis)
: javaPart_(jni::make_global(jThis)) {}

NativeProxy::~NativeProxy() {}

void NativeProxy::registerNatives() {
registerHybrid(
{makeNativeMethod("initHybrid", NativeProxy::initHybrid),
makeNativeMethod(
"nativeAddMutationsListener",
NativeProxy::nativeAddMutationsListener)});
}

void NativeProxy::nativeAddMutationsListener(
jni::alias_ref<facebook::react::JFabricUIManager::javaobject>
fabricUIManager) {
auto uiManager =
fabricUIManager->getBinding()->getScheduler()->getUIManager();
screenRemovalListener_ =
std::make_shared<RNSScreenRemovalListener>([this](int tag) {
static const auto method =
javaPart_->getClass()->getMethod<void(jint)>("notifyScreenRemoved");
method(javaPart_, tag);
});

uiManager->getShadowTreeRegistry().enumerate(
[this](const facebook::react::ShadowTree &shadowTree, bool &stop) {
shadowTree.getMountingCoordinator()->setMountingOverrideDelegate(
screenRemovalListener_);
});
}
Comment on lines +39 to +44
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're setting the MountingOverrideDelegate here on every registered shadowtree within the registry. This is RN's public C++ API. My question is: do we expect collision issues with other libraries such as reanimated? E.i. do we expect to override other lib's delegate / other lib to be able to override our delegate?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cause if that is the case, we might want keep the old approach on iOS.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With RN 0.74 it is possible that it will be overriden. I think I'll target 0.75 with this PR though since there is my commit already: facebook/react-native@358fe46


jni::local_ref<NativeProxy::jhybriddata> NativeProxy::initHybrid(
jni::alias_ref<jhybridobject> jThis) {
return makeCxxInstance(jThis);
}

} // namespace rnscreens
35 changes: 35 additions & 0 deletions android/src/main/cpp/NativeProxy.h
WoLewicki marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include <fbjni/fbjni.h>
#include <react/fabric/JFabricUIManager.h>
#include "RNSScreenRemovalListener.h"

#include <string>

namespace rnscreens {
using namespace facebook;
using namespace facebook::jni;

class NativeProxy : public jni::HybridClass<NativeProxy> {
public:
std::shared_ptr<RNSScreenRemovalListener> screenRemovalListener_;
static auto constexpr kJavaDescriptor =
"Lcom/swmansion/rnscreens/NativeProxy;";
static jni::local_ref<jhybriddata> initHybrid(
jni::alias_ref<jhybridobject> jThis);
static void registerNatives();

~NativeProxy();

private:
friend HybridBase;
jni::global_ref<NativeProxy::javaobject> javaPart_;

explicit NativeProxy(jni::alias_ref<NativeProxy::javaobject> jThis);

void nativeAddMutationsListener(
jni::alias_ref<facebook::react::JFabricUIManager::javaobject>
fabricUIManager);
};

} // namespace rnscreens
8 changes: 8 additions & 0 deletions android/src/main/cpp/OnLoad.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <fbjni/fbjni.h>

#include "NativeProxy.h"

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return facebook::jni::initialize(
vm, [] { rnscreens::NativeProxy::registerNatives(); });
}
36 changes: 36 additions & 0 deletions android/src/main/java/com/swmansion/rnscreens/Screen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.graphics.Paint
import android.os.Parcelable
import android.util.SparseArray
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.webkit.WebView
Expand Down Expand Up @@ -35,6 +36,7 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
var screenOrientation: Int? = null
private set
var isStatusBarAnimated: Boolean? = null
private var isBeingRemoved = false

init {
// we set layout params as WindowManager.LayoutParams to workaround the issue with TextInputs
Expand Down Expand Up @@ -246,6 +248,40 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {

var nativeBackButtonDismissalEnabled: Boolean = true

fun startRemovalTransition() {
if (!isBeingRemoved) {
isBeingRemoved = true
startTransitionRecursive(this)
}
Comment on lines +286 to +289
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have it called multiple times? Why do we have the multiple-entry guard here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, when navigating from JS it is called from the cpp and after that from removeViewAt in ScreenStackViewManager.kt. When navigating from native, which is not used by default right now but still, it would be other way round.

}

private fun startTransitionRecursive(parent: ViewGroup?) {
parent?.let {
for (i in 0 until it.childCount) {
val child = it.getChildAt(i)
if (child.javaClass.simpleName.equals("CircleImageView")) {
// SwipeRefreshLayout class which has CircleImageView as a child,
// does not handle `startViewTransition` properly.
// It has a custom `getChildDrawingOrder` method which returns
// wrong index if we called `startViewTransition` on the views on new arch.
// We add a simple View to make bump the number of children so it works.
// TODO: find a better way to handle this scenario
it.addView(View(context), i)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wild 🙈

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it is something similar @maciekstosio is handling with the not respected zIndex during pop transition in custom header.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I spent enough time trying to handle it correctly and I have no idea how to do it better.

} else {
child?.let { view -> it.startViewTransition(view) }
}
if (child is ScreenStackHeaderConfig) {
// we want to start transition on children of the toolbar too,
// which is not a child of ScreenStackHeaderConfig
startTransitionRecursive(child.toolbar)
}
if (child is ViewGroup) {
startTransitionRecursive(child)
}
}
}
}

private fun calculateHeaderHeight(): Pair<Double, Double> {
val actionBarTv = TypedValue()
val resolvedActionBarSize = context.theme.resolveAttribute(android.R.attr.actionBarSize, actionBarTv, true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class ScreenStackHeaderConfigViewManager : ViewGroupManager<ScreenStackHeaderCon

// TODO: Find better way to handle platform specific props
private fun logNotAvailable(propName: String) {
Log.w("RN SCREENS", "$propName prop is not available on Android")
Log.w("[RNScreens]", "$propName prop is not available on Android")
}

override fun setBackTitle(view: ScreenStackHeaderConfig?, value: String?) {
Expand Down
Loading
Loading