react-native-screens 3.31.0 → 3.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +6 -0
  2. package/RNScreens.podspec +1 -0
  3. package/android/build.gradle +83 -4
  4. package/android/src/main/cpp/jni-adapter.cpp +86 -93
  5. package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +2 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +2 -0
  7. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +17 -3
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +14 -1
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +3 -2
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +6 -2
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +4 -0
  12. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +5 -0
  13. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +19 -2
  14. package/android/src/main/java/com/swmansion/rnscreens/ScreensModule.kt +1 -1
  15. package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +82 -27
  16. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +0 -1
  17. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarBlurEvent.kt +1 -1
  18. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarFocusEvent.kt +1 -1
  19. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContainerManagerDelegate.java +25 -0
  20. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContainerManagerInterface.java +16 -0
  21. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +3 -0
  22. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +1 -0
  23. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +3 -0
  24. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +1 -0
  25. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerDelegate.java +99 -0
  26. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerInterface.java +37 -0
  27. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenComponentDescriptor.h +8 -9
  28. package/common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.h +8 -7
  29. package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +7 -9
  30. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +6 -6
  31. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.cpp +2 -1
  32. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.h +8 -10
  33. package/cpp/RNScreensTurboModule.cpp +31 -23
  34. package/cpp/RNScreensTurboModule.h +17 -20
  35. package/ios/RNSConvert.h +6 -0
  36. package/ios/RNSConvert.mm +24 -0
  37. package/ios/RNSModule.mm +1 -2
  38. package/ios/RNSScreen.mm +8 -0
  39. package/ios/RNSScreenContainer.mm +1 -1
  40. package/ios/RNSScreenStack.mm +71 -13
  41. package/ios/RNSScreenStackHeaderConfig.h +2 -0
  42. package/ios/RNSScreenStackHeaderConfig.mm +44 -17
  43. package/ios/RNSSearchBar.h +5 -5
  44. package/ios/RNSSearchBar.mm +11 -11
  45. package/ios/utils/RCTSurfaceTouchHandler+RNSUtility.h +15 -0
  46. package/ios/utils/RCTSurfaceTouchHandler+RNSUtility.mm +14 -0
  47. package/ios/utils/RCTTouchHandler+RNSUtility.h +15 -0
  48. package/ios/utils/RCTTouchHandler+RNSUtility.mm +15 -0
  49. package/lib/commonjs/components/Screen.js +119 -127
  50. package/lib/commonjs/components/Screen.js.map +1 -1
  51. package/lib/commonjs/components/SearchBar.js +39 -36
  52. package/lib/commonjs/components/SearchBar.js.map +1 -1
  53. package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
  54. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  55. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  56. package/lib/commonjs/native-stack/views/HeaderConfig.js +2 -0
  57. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
  58. package/lib/commonjs/native-stack/views/NativeStackView.js +2 -0
  59. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  60. package/lib/module/components/Screen.js +118 -126
  61. package/lib/module/components/Screen.js.map +1 -1
  62. package/lib/module/components/SearchBar.js +39 -36
  63. package/lib/module/components/SearchBar.js.map +1 -1
  64. package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
  65. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  66. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  67. package/lib/module/native-stack/views/HeaderConfig.js +2 -0
  68. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
  69. package/lib/module/native-stack/views/NativeStackView.js +2 -0
  70. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  71. package/lib/typescript/TransitionProgressContext.d.ts +1 -1
  72. package/lib/typescript/TransitionProgressContext.d.ts.map +1 -1
  73. package/lib/typescript/components/Screen.d.ts +3 -14
  74. package/lib/typescript/components/Screen.d.ts.map +1 -1
  75. package/lib/typescript/components/SearchBar.d.ts +14 -21
  76. package/lib/typescript/components/SearchBar.d.ts.map +1 -1
  77. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +11 -10
  78. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
  79. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +11 -10
  80. package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
  81. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +5 -3
  82. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  83. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts +1 -1
  84. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
  85. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts +1 -1
  86. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts.map +1 -1
  87. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts +9 -9
  88. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts.map +1 -1
  89. package/lib/typescript/gesture-handler/RNScreensTurboModule.d.ts +1 -1
  90. package/lib/typescript/gesture-handler/RNScreensTurboModule.d.ts.map +1 -1
  91. package/lib/typescript/native-stack/types.d.ts +29 -14
  92. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  93. package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts +1 -1
  94. package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts.map +1 -1
  95. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts +1 -1
  96. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts.map +1 -1
  97. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts +1 -1
  98. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts.map +1 -1
  99. package/lib/typescript/native-stack/views/HeaderConfig.d.ts +2 -2
  100. package/lib/typescript/native-stack/views/HeaderConfig.d.ts.map +1 -1
  101. package/lib/typescript/native-stack/views/NativeStackView.d.ts +1 -1
  102. package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
  103. package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts +1 -1
  104. package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts.map +1 -1
  105. package/lib/typescript/types.d.ts +29 -13
  106. package/lib/typescript/types.d.ts.map +1 -1
  107. package/lib/typescript/useTransitionProgress.d.ts +3 -3
  108. package/native-stack/README.md +7 -0
  109. package/package.json +13 -7
  110. package/src/components/Screen.tsx +27 -33
  111. package/src/components/SearchBar.tsx +77 -65
  112. package/src/fabric/ModalScreenNativeComponent.ts +1 -0
  113. package/src/fabric/ScreenNativeComponent.ts +1 -0
  114. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +3 -0
  115. package/src/fabric/SearchBarNativeComponent.ts +6 -6
  116. package/src/native-stack/types.tsx +15 -0
  117. package/src/native-stack/views/HeaderConfig.tsx +2 -0
  118. package/src/native-stack/views/NativeStackView.tsx +2 -0
  119. package/src/types.tsx +16 -0
package/README.md CHANGED
@@ -106,6 +106,7 @@ Screens are already integrated with the React Native's most popular navigation l
106
106
 
107
107
  | library version | react-native version |
108
108
  | ------- | -------------------- |
109
+ | 3.32.0+ | 0.71.0+ |
109
110
  | 3.30.0+ | 0.68.0+ |
110
111
  | 3.14.0+ | 0.64.0+ |
111
112
  | 3.0.0+ | 0.62.0+ |
@@ -119,6 +120,7 @@ Here's a table with summary of supported `react-native` versions when Fabric is
119
120
 
120
121
  | library version | react-native version |
121
122
  | ------- | -------------------- |
123
+ | 3.32.0+ | 0.74.0+ |
122
124
  | 3.28.0+ | 0.73.0+ |
123
125
  | 3.21.0+ | 0.72.0+ |
124
126
  | 3.19.0+ | 0.71.0+ |
@@ -233,3 +235,7 @@ This project has been build and is maintained thanks to the support from [Shopif
233
235
  [![shopify](https://avatars1.githubusercontent.com/u/8085?v=3&s=100 'Shopify.com')](https://shopify.com)
234
236
  [![expo](https://avatars2.githubusercontent.com/u/12504344?v=3&s=100 'Expo.io')](https://expo.io)
235
237
  [![swm](https://logo.swmansion.com/logo?color=white&variant=desktop&width=150&tag=react-native-reanimated-github 'Software Mansion')](https://swmansion.com)
238
+
239
+ ## React Native Screens is created by Software Mansion
240
+
241
+ Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues. We can help you build your next dream product – [Hire us](https://swmansion.com/contact/projects?utm_source=screens&utm_medium=readme).
package/RNScreens.podspec CHANGED
@@ -63,6 +63,7 @@ Pod::Spec.new do |s|
63
63
  s.platforms = { :ios => platform, :tvos => "11.0", :visionos => "1.0" }
64
64
  s.source = { :git => "https://github.com/software-mansion/react-native-screens.git", :tag => "#{s.version}" }
65
65
  s.source_files = source_files
66
+ s.project_header_files = "cpp/**/*.h" # Don't expose C++ headers publicly to allow importing framework into Swift files
66
67
  s.requires_arc = true
67
68
 
68
69
  if defined?(install_modules_dependencies()) != nil
@@ -22,6 +22,10 @@ buildscript {
22
22
  }
23
23
  }
24
24
 
25
+ def isRunningInContextOfScreensRepo() {
26
+ return project == rootProject
27
+ }
28
+
25
29
  def isNewArchitectureEnabled() {
26
30
  // To opt-in for the New Architecture, you can either:
27
31
  // - Set `newArchEnabled` to true inside the `gradle.properties` file
@@ -31,7 +35,7 @@ def isNewArchitectureEnabled() {
31
35
  }
32
36
 
33
37
  // spotless is only accessible within react-native-screens repo
34
- if (project == rootProject) {
38
+ if (isRunningInContextOfScreensRepo()) {
35
39
  apply from: 'spotless.gradle'
36
40
  }
37
41
 
@@ -58,7 +62,7 @@ def resolveReactNativeDirectory() {
58
62
  }
59
63
 
60
64
  def reactNativeFromAppNodeModules = file("${projectDir}/../../react-native")
61
- if (reactNativeFromAppNodeModules.exists()) {
65
+ if (!isRunningInContextOfScreensRepo() && reactNativeFromAppNodeModules.exists()) {
62
66
  return reactNativeFromAppNodeModules
63
67
  }
64
68
 
@@ -68,7 +72,7 @@ def resolveReactNativeDirectory() {
68
72
  }
69
73
 
70
74
  throw new GradleException(
71
- "[RNScreens] Unable to resolve react-native location in node_modules. You should project extension property (in `app/build.gradle`) `REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
75
+ "[RNScreens] Unable to resolve react-native location in node_modules. You should add project extension property (in `app/build.gradle`) `REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
72
76
  )
73
77
  }
74
78
 
@@ -152,7 +156,6 @@ android {
152
156
  } else {
153
157
  srcDirs += [
154
158
  "src/paper/java",
155
- "build/generated/source/codegen/java"
156
159
  ]
157
160
  }
158
161
  }
@@ -193,3 +196,79 @@ dependencies {
193
196
  }
194
197
  }
195
198
  }
199
+
200
+ def isScreensExampleApp() {
201
+ return project.hasProperty('isScreensExampleApp') && project.property('isScreensExampleApp') == "true"
202
+ }
203
+
204
+ def getAbsoluteCodegenArtifactsPaperDestination() {
205
+ if (!project.hasProperty('codegenArtifactsPaperDestination')) {
206
+ throw new Exception('[RNScreens] Please fill codegenArtifactsPaperDestination variable in android/gradle.properties correct path to paper paper destination')
207
+ }
208
+
209
+ return "${project.rootDir}/../../${project.property('codegenArtifactsPaperDestination')}"
210
+ }
211
+
212
+ def getAbsoluteCodegenArtifactsSource() {
213
+ if (!project.hasProperty('codegenArtifactsSource')) {
214
+ throw new Exception('[RNScreens] Please fill codegenArtifactsSource variable in android/gradle.properties correct path to codegenerated artifacts')
215
+ }
216
+
217
+ return "${project.rootDir}/../../${project.property('codegenArtifactsSource')}"
218
+ }
219
+
220
+
221
+ tasks.register("copyCodegenArtifacts") {
222
+ group 'After build tasks'
223
+ description 'Tasks which copy codegen artifacts to paper architecture'
224
+
225
+ if (!isScreensExampleApp() || !isNewArchitectureEnabled()) {
226
+ return
227
+ }
228
+
229
+ dependsOn tasks.generateCodegenArtifactsFromSchema
230
+
231
+ doLast {
232
+
233
+ def absoluteCodegenArtifactsPaperDestination = getAbsoluteCodegenArtifactsPaperDestination()
234
+ def absoluteCodegenArtifactsSource = getAbsoluteCodegenArtifactsSource()
235
+
236
+ def existingFiles = fileTree(absoluteCodegenArtifactsPaperDestination).matching {
237
+ include '**/*.java'
238
+ }
239
+
240
+ def generatedFiles = fileTree(absoluteCodegenArtifactsSource).matching {
241
+ include '**/*.java'
242
+ }
243
+
244
+ def existingFilesMap = [:]
245
+
246
+ existingFiles.forEach { existingFile ->
247
+ existingFilesMap[existingFile.name] = 1
248
+ }
249
+
250
+ generatedFiles.forEach { generatedFile ->
251
+ if (!existingFilesMap.containsKey(generatedFile.name)) {
252
+ logger.warn("[RNScreens] ${generatedFile.name} not found in paper dir, if it's used in Android you need to copy it manually and implement yourself before using auto-copy feature")
253
+ }
254
+ }
255
+
256
+ if (existingFiles.size() == 0) {
257
+ logger.warn("[RNScreens] Paper destination with codegen interfaces is empty. This might be okay if you don't have any interfaces/delegates used in Android, if that's not the case please check if codegenArtifactsPaperDestination in android/gradle.properties is correct")
258
+ }
259
+
260
+ if (existingFiles.size() > generatedFiles.size()) {
261
+ throw new Exception("[RNScreens] Number od generated artifacts should be greather then or equal to paper interfaces. Please check if codegenArtifactsSource in android/gradle.properties is correct")
262
+ }
263
+
264
+ copy {
265
+ from absoluteCodegenArtifactsSource
266
+ include existingFiles.collect { it.name }
267
+ into absoluteCodegenArtifactsPaperDestination
268
+ }
269
+ }
270
+ }
271
+
272
+ if (isScreensExampleApp() && isNewArchitectureEnabled()) {
273
+ tasks.generateCodegenArtifactsFromSchema.finalizedBy('copyCodegenArtifacts')
274
+ }
@@ -1,110 +1,103 @@
1
- #include <array>
2
- #include <mutex>
3
1
  #include <jni.h>
4
2
  #include <jsi/jsi.h>
3
+ #include <array>
4
+ #include <mutex>
5
5
  #include "RNScreensTurboModule.h"
6
6
 
7
7
  using namespace facebook;
8
8
 
9
9
  jobject globalThis;
10
10
 
11
- extern "C"
12
- JNIEXPORT void JNICALL
13
- Java_com_swmansion_rnscreens_ScreensModule_nativeInstall(JNIEnv *env, jobject thiz, jlong jsiPtr) {
14
- auto runtime = reinterpret_cast<jsi::Runtime*>(jsiPtr);
15
- if (!runtime) {
16
- return;
17
- }
18
- jsi::Runtime &rt = *runtime;
19
- globalThis = env->NewGlobalRef(thiz);
20
- JavaVM* jvm;
21
- env->GetJavaVM(&jvm);
11
+ extern "C" JNIEXPORT void JNICALL
12
+ Java_com_swmansion_rnscreens_ScreensModule_nativeInstall(
13
+ JNIEnv *env,
14
+ jobject thiz,
15
+ jlong jsiPtr) {
16
+ auto runtime = reinterpret_cast<jsi::Runtime *>(jsiPtr);
17
+ if (!runtime) {
18
+ return;
19
+ }
20
+ jsi::Runtime &rt = *runtime;
21
+ globalThis = env->NewGlobalRef(thiz);
22
+ JavaVM *jvm;
23
+ env->GetJavaVM(&jvm);
22
24
 
23
- const auto &startTransition = [jvm](int stackTag) -> std::array<int, 2> {
24
- JNIEnv* currentEnv;
25
- if (jvm->AttachCurrentThread(&currentEnv, nullptr) != JNI_OK) {
26
- return {0, 0};
27
- }
28
- jclass javaClass = currentEnv->GetObjectClass(globalThis);
29
- jmethodID methodID = currentEnv->GetMethodID(
30
- javaClass,
31
- "startTransition",
32
- "(Ljava/lang/Integer;)[I"
33
- );
34
- jclass integerClass = currentEnv->FindClass("java/lang/Integer");
35
- jmethodID integerConstructor = currentEnv->GetMethodID(integerClass, "<init>", "(I)V");
36
- jobject integerArg = currentEnv->NewObject(integerClass, integerConstructor, stackTag);
37
- jintArray resultArray = (jintArray) currentEnv->CallObjectMethod(
38
- globalThis,
39
- methodID,
40
- integerArg
41
- );
42
- std::array<int, 2> result = {-1, -1};
43
- jint* elements = currentEnv->GetIntArrayElements(resultArray, nullptr);
44
- if (elements != nullptr) {
45
- result[0] = elements[0];
46
- result[1] = elements[1];
47
- currentEnv->ReleaseIntArrayElements(resultArray, elements, JNI_ABORT);
48
- }
49
- return result;
50
- };
25
+ const auto &startTransition = [jvm](int stackTag) -> std::array<int, 2> {
26
+ JNIEnv *currentEnv;
27
+ if (jvm->AttachCurrentThread(&currentEnv, nullptr) != JNI_OK) {
28
+ return {0, 0};
29
+ }
30
+ jclass javaClass = currentEnv->GetObjectClass(globalThis);
31
+ jmethodID methodID = currentEnv->GetMethodID(
32
+ javaClass, "startTransition", "(Ljava/lang/Integer;)[I");
33
+ jclass integerClass = currentEnv->FindClass("java/lang/Integer");
34
+ jmethodID integerConstructor =
35
+ currentEnv->GetMethodID(integerClass, "<init>", "(I)V");
36
+ jobject integerArg =
37
+ currentEnv->NewObject(integerClass, integerConstructor, stackTag);
38
+ jintArray resultArray = (jintArray)currentEnv->CallObjectMethod(
39
+ globalThis, methodID, integerArg);
40
+ std::array<int, 2> result = {-1, -1};
41
+ jint *elements = currentEnv->GetIntArrayElements(resultArray, nullptr);
42
+ if (elements != nullptr) {
43
+ result[0] = elements[0];
44
+ result[1] = elements[1];
45
+ currentEnv->ReleaseIntArrayElements(resultArray, elements, JNI_ABORT);
46
+ }
47
+ return result;
48
+ };
51
49
 
52
- const auto &updateTransition = [jvm](int stackTag, double progress){
53
- JNIEnv* currentEnv;
54
- if (jvm->AttachCurrentThread(&currentEnv, nullptr) != JNI_OK) {
55
- return;
56
- }
57
- jclass javaClass = currentEnv->GetObjectClass(globalThis);
58
- jmethodID methodID = currentEnv->GetMethodID(
59
- javaClass,
60
- "updateTransition",
61
- "(D)V"
62
- );
63
- currentEnv->CallVoidMethod(globalThis, methodID, progress);
64
- };
50
+ const auto &updateTransition = [jvm](int stackTag, double progress) {
51
+ JNIEnv *currentEnv;
52
+ if (jvm->AttachCurrentThread(&currentEnv, nullptr) != JNI_OK) {
53
+ return;
54
+ }
55
+ jclass javaClass = currentEnv->GetObjectClass(globalThis);
56
+ jmethodID methodID =
57
+ currentEnv->GetMethodID(javaClass, "updateTransition", "(D)V");
58
+ currentEnv->CallVoidMethod(globalThis, methodID, progress);
59
+ };
65
60
 
66
- const auto &finishTransition = [jvm](int stackTag, bool canceled){
67
- JNIEnv* currentEnv;
68
- if (jvm->AttachCurrentThread(&currentEnv, nullptr) != JNI_OK) {
69
- return;
70
- }
71
- jclass javaClass = currentEnv->GetObjectClass(globalThis);
72
- jmethodID methodID = currentEnv->GetMethodID(
73
- javaClass,
74
- "finishTransition",
75
- "(Ljava/lang/Integer;Z)V"
76
- );
77
- jclass integerClass = currentEnv->FindClass("java/lang/Integer");
78
- jmethodID integerConstructor = currentEnv->GetMethodID(integerClass, "<init>", "(I)V");
79
- jobject integerArg = currentEnv->NewObject(integerClass, integerConstructor, stackTag);
80
- currentEnv->CallVoidMethod(globalThis, methodID, integerArg, canceled);
81
- };
61
+ const auto &finishTransition = [jvm](int stackTag, bool canceled) {
62
+ JNIEnv *currentEnv;
63
+ if (jvm->AttachCurrentThread(&currentEnv, nullptr) != JNI_OK) {
64
+ return;
65
+ }
66
+ jclass javaClass = currentEnv->GetObjectClass(globalThis);
67
+ jmethodID methodID = currentEnv->GetMethodID(
68
+ javaClass, "finishTransition", "(Ljava/lang/Integer;Z)V");
69
+ jclass integerClass = currentEnv->FindClass("java/lang/Integer");
70
+ jmethodID integerConstructor =
71
+ currentEnv->GetMethodID(integerClass, "<init>", "(I)V");
72
+ jobject integerArg =
73
+ currentEnv->NewObject(integerClass, integerConstructor, stackTag);
74
+ currentEnv->CallVoidMethod(globalThis, methodID, integerArg, canceled);
75
+ };
82
76
 
83
- const auto &disableSwipeBackForTopScreen = [](int _stackTag){
84
- // no implementation for Android
85
- };
77
+ const auto &disableSwipeBackForTopScreen = [](int _stackTag) {
78
+ // no implementation for Android
79
+ };
86
80
 
87
- auto rnScreensModule = std::make_shared<RNScreens::RNScreensTurboModule>(
88
- startTransition,
89
- updateTransition,
90
- finishTransition,
91
- disableSwipeBackForTopScreen
92
- );
93
- auto rnScreensModuleHostObject = jsi::Object::createFromHostObject(rt, rnScreensModule);
94
- rt.global().setProperty(
95
- rt,
96
- RNScreens::RNScreensTurboModule::MODULE_NAME,
97
- std::move(rnScreensModuleHostObject)
98
- );
81
+ auto rnScreensModule = std::make_shared<RNScreens::RNScreensTurboModule>(
82
+ startTransition,
83
+ updateTransition,
84
+ finishTransition,
85
+ disableSwipeBackForTopScreen);
86
+ auto rnScreensModuleHostObject =
87
+ jsi::Object::createFromHostObject(rt, rnScreensModule);
88
+ rt.global().setProperty(
89
+ rt,
90
+ RNScreens::RNScreensTurboModule::MODULE_NAME,
91
+ std::move(rnScreensModuleHostObject));
99
92
  }
100
93
 
101
94
  void JNICALL JNI_OnUnload(JavaVM *jvm, void *) {
102
- JNIEnv *env;
103
- if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
104
- return;
105
- }
106
- if (globalThis != nullptr) {
107
- env->DeleteGlobalRef(globalThis);
108
- globalThis = nullptr;
109
- }
95
+ JNIEnv *env;
96
+ if (jvm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
97
+ return;
98
+ }
99
+ if (globalThis != nullptr) {
100
+ env->DeleteGlobalRef(globalThis);
101
+ globalThis = nullptr;
102
+ }
110
103
  }
@@ -1,10 +1,12 @@
1
1
  package com.swmansion.rnscreens
2
2
 
3
+ import android.annotation.SuppressLint
3
4
  import android.content.Context
4
5
  import androidx.activity.OnBackPressedCallback
5
6
  import androidx.appcompat.widget.SearchView
6
7
  import androidx.fragment.app.Fragment
7
8
 
9
+ @SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
8
10
  class CustomSearchView(context: Context, fragment: Fragment) : SearchView(context) {
9
11
  /*
10
12
  CustomSearchView uses some variables from SearchView. They are listed below with links to documentation
@@ -1,7 +1,9 @@
1
1
  package com.swmansion.rnscreens
2
2
 
3
+ import android.annotation.SuppressLint
3
4
  import android.content.Context
4
5
  import androidx.appcompat.widget.Toolbar
5
6
 
6
7
  // This class is used to store config closer to search bar
8
+ @SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
7
9
  open class CustomToolbar(context: Context, val config: ScreenStackHeaderConfig) : Toolbar(context)
@@ -18,7 +18,7 @@ import com.facebook.react.uimanager.UIManagerHelper
18
18
  import com.facebook.react.uimanager.UIManagerModule
19
19
  import com.swmansion.rnscreens.events.HeaderHeightChangeEvent
20
20
 
21
- @SuppressLint("ViewConstructor")
21
+ @SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
22
22
  class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
23
23
  val fragment: Fragment?
24
24
  get() = fragmentWrapper?.fragment
@@ -80,7 +80,7 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
80
80
  private fun updateScreenSizePaper(width: Int, height: Int) {
81
81
  val reactContext = context as ReactContext
82
82
  reactContext.runOnNativeModulesQueueThread(
83
- object : GuardedRunnable(reactContext) {
83
+ object : GuardedRunnable(reactContext.exceptionHandler) {
84
84
  override fun runGuarded() {
85
85
  reactContext
86
86
  .getNativeModule(UIManagerModule::class.java)
@@ -216,6 +216,20 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
216
216
  fragmentWrapper?.let { ScreenWindowTraits.setNavigationBarColor(this, it.tryGetActivity()) }
217
217
  }
218
218
 
219
+ var isNavigationBarTranslucent: Boolean? = null
220
+ set(navigationBarTranslucent) {
221
+ if (navigationBarTranslucent != null) {
222
+ ScreenWindowTraits.applyDidSetNavigationBarAppearance()
223
+ }
224
+ field = navigationBarTranslucent
225
+ fragmentWrapper?.let {
226
+ ScreenWindowTraits.setNavigationBarTranslucent(
227
+ this,
228
+ it.tryGetActivity(),
229
+ )
230
+ }
231
+ }
232
+
219
233
  var isNavigationBarHidden: Boolean? = null
220
234
  set(navigationBarHidden) {
221
235
  if (navigationBarHidden != null) {
@@ -276,6 +290,6 @@ class Screen(context: ReactContext?) : FabricEnabledViewGroup(context) {
276
290
  }
277
291
 
278
292
  enum class WindowTraits {
279
- ORIENTATION, COLOR, STYLE, TRANSLUCENT, HIDDEN, ANIMATED, NAVIGATION_BAR_COLOR, NAVIGATION_BAR_HIDDEN
293
+ ORIENTATION, COLOR, STYLE, TRANSLUCENT, HIDDEN, ANIMATED, NAVIGATION_BAR_COLOR, NAVIGATION_BAR_TRANSLUCENT, NAVIGATION_BAR_HIDDEN
280
294
  }
281
295
  }
@@ -6,9 +6,22 @@ import com.facebook.react.module.annotations.ReactModule
6
6
  import com.facebook.react.uimanager.LayoutShadowNode
7
7
  import com.facebook.react.uimanager.ThemedReactContext
8
8
  import com.facebook.react.uimanager.ViewGroupManager
9
+ import com.facebook.react.uimanager.ViewManagerDelegate
10
+ import com.facebook.react.viewmanagers.RNSScreenContainerManagerDelegate
11
+ import com.facebook.react.viewmanagers.RNSScreenContainerManagerInterface
9
12
 
10
13
  @ReactModule(name = ScreenContainerViewManager.REACT_CLASS)
11
- class ScreenContainerViewManager : ViewGroupManager<ScreenContainer>() {
14
+ class ScreenContainerViewManager : ViewGroupManager<ScreenContainer>(), RNSScreenContainerManagerInterface<ScreenContainer> {
15
+ private val delegate: ViewManagerDelegate<ScreenContainer>
16
+
17
+ init {
18
+ delegate = RNSScreenContainerManagerDelegate<ScreenContainer, ScreenContainerViewManager>(this)
19
+ }
20
+
21
+ protected override fun getDelegate(): ViewManagerDelegate<ScreenContainer> {
22
+ return delegate
23
+ }
24
+
12
25
  override fun getName(): String = REACT_CLASS
13
26
 
14
27
  override fun createViewInstance(reactContext: ThemedReactContext): ScreenContainer = ScreenContainer(reactContext)
@@ -62,7 +62,8 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
62
62
 
63
63
  override fun setToolbarShadowHidden(hidden: Boolean) {
64
64
  if (isToolbarShadowHidden != hidden) {
65
- appBarLayout?.targetElevation = if (hidden) 0f else PixelUtil.toPixelFromDIP(4f)
65
+ appBarLayout?.elevation = if (hidden) 0f else PixelUtil.toPixelFromDIP(4f)
66
+ appBarLayout?.stateListAnimator = null
66
67
  isToolbarShadowHidden = hidden
67
68
  }
68
69
  }
@@ -125,7 +126,7 @@ class ScreenStackFragment : ScreenFragment, ScreenStackFragmentWrapper {
125
126
 
126
127
  view?.addView(appBarLayout)
127
128
  if (isToolbarShadowHidden) {
128
- appBarLayout?.targetElevation = 0f
129
+ appBarLayout?.elevation = 0f
129
130
  }
130
131
  toolbar?.let { appBarLayout?.addView(recycleView(it)) }
131
132
  setHasOptionsMenu(true)
@@ -2,12 +2,14 @@ package com.swmansion.rnscreens
2
2
 
3
3
  import android.content.Context
4
4
  import android.graphics.PorterDuff
5
+ import android.graphics.PorterDuffColorFilter
5
6
  import android.os.Build
6
7
  import android.text.TextUtils
7
8
  import android.util.TypedValue
8
9
  import android.view.Gravity
9
10
  import android.view.View.OnClickListener
10
11
  import android.view.ViewGroup
12
+ import android.view.WindowInsets
11
13
  import android.widget.ImageView
12
14
  import android.widget.TextView
13
15
  import androidx.appcompat.app.AppCompatActivity
@@ -82,7 +84,9 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
82
84
  // we want to save the top inset before the status bar can be hidden, which would resolve in
83
85
  // inset being 0
84
86
  if (headerTopInset == null) {
85
- headerTopInset = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
87
+ headerTopInset = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
88
+ rootWindowInsets.getInsets(WindowInsets.Type.systemBars()).top
89
+ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
86
90
  rootWindowInsets.systemWindowInsetTop
87
91
  else
88
92
  // Hacky fallback for old android. Before Marshmallow, the status bar height was always 25
@@ -228,7 +232,7 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
228
232
 
229
233
  // color
230
234
  if (tintColor != 0) {
231
- toolbar.navigationIcon?.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP)
235
+ toolbar.navigationIcon?.colorFilter = PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP)
232
236
  }
233
237
 
234
238
  // subviews
@@ -201,4 +201,8 @@ class ScreenStackHeaderConfigViewManager : ViewGroupManager<ScreenStackHeaderCon
201
201
  override fun setDisableBackButtonMenu(view: ScreenStackHeaderConfig?, value: Boolean) {
202
202
  logNotAvailable("disableBackButtonMenu")
203
203
  }
204
+
205
+ override fun setBackButtonDisplayMode(view: ScreenStackHeaderConfig?, value: String?) {
206
+ logNotAvailable("backButtonDisplayMode")
207
+ }
204
208
  }
@@ -142,6 +142,11 @@ open class ScreenViewManager : ViewGroupManager<Screen>(), RNSScreenManagerInter
142
142
  view.navigationBarColor = navigationBarColor
143
143
  }
144
144
 
145
+ @ReactProp(name = "navigationBarTranslucent")
146
+ override fun setNavigationBarTranslucent(view: Screen, navigationBarTranslucent: Boolean) {
147
+ view.isNavigationBarTranslucent = navigationBarTranslucent
148
+ }
149
+
145
150
  @ReactProp(name = "navigationBarHidden")
146
151
  override fun setNavigationBarHidden(view: Screen, navigationBarHidden: Boolean) {
147
152
  view.isNavigationBarHidden = navigationBarHidden
@@ -11,6 +11,7 @@ import android.os.Build
11
11
  import android.view.ViewParent
12
12
  import androidx.core.graphics.Insets
13
13
  import androidx.core.view.ViewCompat
14
+ import androidx.core.view.WindowCompat
14
15
  import androidx.core.view.WindowInsetsCompat
15
16
  import androidx.core.view.WindowInsetsControllerCompat
16
17
  import com.facebook.react.bridge.GuardedRunnable
@@ -60,7 +61,7 @@ object ScreenWindowTraits {
60
61
  val animated = screenForAnimated?.isStatusBarAnimated ?: false
61
62
 
62
63
  UiThreadUtil.runOnUiThread(
63
- object : GuardedRunnable(context) {
64
+ object : GuardedRunnable(context.exceptionHandler) {
64
65
  override fun runGuarded() {
65
66
  val window = activity.window
66
67
  val curColor: Int = window.statusBarColor
@@ -105,7 +106,7 @@ object ScreenWindowTraits {
105
106
  val screenForTranslucent = findScreenForTrait(screen, WindowTraits.TRANSLUCENT)
106
107
  val translucent = screenForTranslucent?.isStatusBarTranslucent ?: false
107
108
  UiThreadUtil.runOnUiThread(
108
- object : GuardedRunnable(context) {
109
+ object : GuardedRunnable(context.exceptionHandler) {
109
110
  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
110
111
  override fun runGuarded() {
111
112
  // If the status bar is translucent hook into the window insets calculations
@@ -185,6 +186,20 @@ object ScreenWindowTraits {
185
186
  window.navigationBarColor = color
186
187
  }
187
188
 
189
+ internal fun setNavigationBarTranslucent(screen: Screen, activity: Activity?) {
190
+ if (activity == null) {
191
+ return
192
+ }
193
+
194
+ val window = activity.window
195
+
196
+ val screenForNavBarTranslucent = findScreenForTrait(screen, WindowTraits.NAVIGATION_BAR_TRANSLUCENT)
197
+ val translucent = screenForNavBarTranslucent?.isNavigationBarTranslucent ?: false
198
+
199
+ // Following method controls whether to display edge-to-edge content that draws behind the navigation bar
200
+ WindowCompat.setDecorFitsSystemWindows(window, !translucent)
201
+ }
202
+
188
203
  internal fun setNavigationBarHidden(screen: Screen, activity: Activity?) {
189
204
  if (activity == null) {
190
205
  return
@@ -221,6 +236,7 @@ object ScreenWindowTraits {
221
236
  }
222
237
  if (didSetNavigationBarAppearance) {
223
238
  setNavigationBarColor(screen, activity)
239
+ setNavigationBarTranslucent(screen, activity)
224
240
  setNavigationBarHidden(screen, activity)
225
241
  }
226
242
  }
@@ -281,6 +297,7 @@ object ScreenWindowTraits {
281
297
  WindowTraits.HIDDEN -> screen.isStatusBarHidden != null
282
298
  WindowTraits.ANIMATED -> screen.isStatusBarAnimated != null
283
299
  WindowTraits.NAVIGATION_BAR_COLOR -> screen.navigationBarColor != null
300
+ WindowTraits.NAVIGATION_BAR_TRANSLUCENT -> screen.isNavigationBarTranslucent != null
284
301
  WindowTraits.NAVIGATION_BAR_HIDDEN -> screen.isNavigationBarHidden != null
285
302
  }
286
303
  }
@@ -25,7 +25,7 @@ class ScreensModule(private val reactContext: ReactApplicationContext)
25
25
  } else {
26
26
  Log.e("[RNScreens]", "Could not install JSI bindings.")
27
27
  }
28
- } catch (exception: Exception) {
28
+ } catch (exception: UnsatisfiedLinkError) {
29
29
  Log.w("[RNScreens]", "Could not load RNScreens module.")
30
30
  }
31
31
  }