@amazon-devices/react-native-screens 2.0.1758683737

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 (381) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +223 -0
  3. package/RNScreens.podspec +53 -0
  4. package/SystemBundles/8f5a820b958535e533acb38dbc0c72c1837721b9db075f4a1740e42b9fee3910.bundle +33668 -0
  5. package/SystemBundles/8f5a820b958535e533acb38dbc0c72c1837721b9db075f4a1740e42b9fee3910.map +1 -0
  6. package/SystemModules/amzn__react-native-screens.modules.txt +101 -0
  7. package/SystemModules/amzn__react-native-screens.private.modules.txt +244 -0
  8. package/SystemModules/keplerscript-system-bundle-config.json +7 -0
  9. package/THIRD_PARTY_NOTICES.txt +707 -0
  10. package/android/build.gradle +133 -0
  11. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +49 -0
  12. package/android/src/main/AndroidManifest.xml +5 -0
  13. package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +77 -0
  14. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +7 -0
  15. package/android/src/main/java/com/swmansion/rnscreens/FragmentBackPressOverrider.kt +29 -0
  16. package/android/src/main/java/com/swmansion/rnscreens/FragmentHolder.kt +7 -0
  17. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +21 -0
  18. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +289 -0
  19. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +372 -0
  20. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +40 -0
  21. package/android/src/main/java/com/swmansion/rnscreens/ScreenEventDispatcher.kt +21 -0
  22. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +331 -0
  23. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragmentWrapper.kt +22 -0
  24. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +336 -0
  25. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +282 -0
  26. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragmentWrapper.kt +15 -0
  27. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +398 -0
  28. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +204 -0
  29. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +38 -0
  30. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +41 -0
  31. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +75 -0
  32. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +186 -0
  33. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +296 -0
  34. package/android/src/main/java/com/swmansion/rnscreens/ScreensShadowNode.kt +19 -0
  35. package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +133 -0
  36. package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +178 -0
  37. package/android/src/main/java/com/swmansion/rnscreens/SearchViewFormatter.kt +67 -0
  38. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderAttachedEvent.kt +22 -0
  39. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderBackButtonClickedEvent.kt +22 -0
  40. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderDetachedEvent.kt +22 -0
  41. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +26 -0
  42. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenAppearEvent.kt +18 -0
  43. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDisappearEvent.kt +18 -0
  44. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDismissedEvent.kt +20 -0
  45. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenTransitionProgressEvent.kt +32 -0
  46. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillAppearEvent.kt +18 -0
  47. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillDisappearEvent.kt +18 -0
  48. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarBlurEvent.kt +22 -0
  49. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarChangeTextEvent.kt +28 -0
  50. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarCloseEvent.kt +22 -0
  51. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarFocusEvent.kt +22 -0
  52. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarOpenEvent.kt +22 -0
  53. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarSearchButtonPressEvent.kt +24 -0
  54. package/android/src/main/java/com/swmansion/rnscreens/events/StackFinishTransitioningEvent.kt +18 -0
  55. package/android/src/main/java/com/swmansion/rnscreens/utils/DeviceUtils.kt +12 -0
  56. package/android/src/main/jni/CMakeLists.txt +72 -0
  57. package/android/src/main/jni/rnscreens.cpp +16 -0
  58. package/android/src/main/jni/rnscreens.h +28 -0
  59. package/android/src/main/res/base/anim/rns_default_enter_in.xml +18 -0
  60. package/android/src/main/res/base/anim/rns_default_enter_out.xml +19 -0
  61. package/android/src/main/res/base/anim/rns_default_exit_in.xml +17 -0
  62. package/android/src/main/res/base/anim/rns_default_exit_out.xml +18 -0
  63. package/android/src/main/res/base/anim/rns_fade_from_bottom.xml +14 -0
  64. package/android/src/main/res/base/anim/rns_fade_in.xml +7 -0
  65. package/android/src/main/res/base/anim/rns_fade_out.xml +7 -0
  66. package/android/src/main/res/base/anim/rns_fade_to_bottom.xml +15 -0
  67. package/android/src/main/res/base/anim/rns_no_animation_20.xml +6 -0
  68. package/android/src/main/res/base/anim/rns_no_animation_250.xml +7 -0
  69. package/android/src/main/res/base/anim/rns_no_animation_350.xml +6 -0
  70. package/android/src/main/res/base/anim/rns_no_animation_medium.xml +7 -0
  71. package/android/src/main/res/base/anim/rns_slide_in_from_bottom.xml +7 -0
  72. package/android/src/main/res/base/anim/rns_slide_in_from_left.xml +5 -0
  73. package/android/src/main/res/base/anim/rns_slide_in_from_right.xml +5 -0
  74. package/android/src/main/res/base/anim/rns_slide_out_to_bottom.xml +7 -0
  75. package/android/src/main/res/base/anim/rns_slide_out_to_left.xml +5 -0
  76. package/android/src/main/res/base/anim/rns_slide_out_to_right.xml +5 -0
  77. package/android/src/main/res/base/anim/rns_standard_accelerate_interpolator.xml +6 -0
  78. package/android/src/main/res/v33/anim-v33/rns_default_enter_in.xml +38 -0
  79. package/android/src/main/res/v33/anim-v33/rns_default_enter_out.xml +38 -0
  80. package/android/src/main/res/v33/anim-v33/rns_default_exit_in.xml +38 -0
  81. package/android/src/main/res/v33/anim-v33/rns_default_exit_out.xml +38 -0
  82. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +111 -0
  83. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +44 -0
  84. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +107 -0
  85. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +42 -0
  86. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderSubviewManagerDelegate.java +31 -0
  87. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderSubviewManagerInterface.java +17 -0
  88. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackManagerDelegate.java +25 -0
  89. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackManagerInterface.java +16 -0
  90. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +10 -0
  91. package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +41 -0
  92. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +9 -0
  93. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +30 -0
  94. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.cpp +14 -0
  95. package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.h +45 -0
  96. package/ios/RCTImageComponentView+RNSScreenStackHeaderConfig.h +11 -0
  97. package/ios/RCTImageComponentView+RNSScreenStackHeaderConfig.mm +14 -0
  98. package/ios/RNSConvert.h +36 -0
  99. package/ios/RNSConvert.mm +154 -0
  100. package/ios/RNSEnums.h +71 -0
  101. package/ios/RNSFullWindowOverlay.h +34 -0
  102. package/ios/RNSFullWindowOverlay.mm +241 -0
  103. package/ios/RNSScreen.h +144 -0
  104. package/ios/RNSScreen.mm +1599 -0
  105. package/ios/RNSScreenContainer.h +45 -0
  106. package/ios/RNSScreenContainer.mm +343 -0
  107. package/ios/RNSScreenNavigationContainer.h +16 -0
  108. package/ios/RNSScreenNavigationContainer.mm +66 -0
  109. package/ios/RNSScreenStack.h +37 -0
  110. package/ios/RNSScreenStack.mm +1111 -0
  111. package/ios/RNSScreenStackAnimator.h +8 -0
  112. package/ios/RNSScreenStackAnimator.mm +320 -0
  113. package/ios/RNSScreenStackHeaderConfig.h +74 -0
  114. package/ios/RNSScreenStackHeaderConfig.mm +967 -0
  115. package/ios/RNSScreenStackHeaderSubview.h +44 -0
  116. package/ios/RNSScreenStackHeaderSubview.mm +147 -0
  117. package/ios/RNSScreenWindowTraits.h +26 -0
  118. package/ios/RNSScreenWindowTraits.mm +266 -0
  119. package/ios/RNSSearchBar.h +43 -0
  120. package/ios/RNSSearchBar.mm +465 -0
  121. package/ios/RNScreens.xcodeproj/project.pbxproj +461 -0
  122. package/ios/UIViewController+RNScreens.h +9 -0
  123. package/ios/UIViewController+RNScreens.mm +78 -0
  124. package/ios/UIWindow+RNScreens.h +9 -0
  125. package/ios/UIWindow+RNScreens.mm +17 -0
  126. package/ios/events/RNSHeaderHeightChangeEvent.h +8 -0
  127. package/ios/events/RNSHeaderHeightChangeEvent.mm +44 -0
  128. package/ios/events/RNSScreenViewEvent.h +12 -0
  129. package/ios/events/RNSScreenViewEvent.mm +59 -0
  130. package/ios/utils/RNSUIBarButtonItem.h +5 -0
  131. package/ios/utils/RNSUIBarButtonItem.mm +22 -0
  132. package/kepler-compatibility.json +8 -0
  133. package/kepler-transformed-package-info.json +3 -0
  134. package/lib/commonjs/TransitionProgressContext.js +11 -0
  135. package/lib/commonjs/TransitionProgressContext.js.map +1 -0
  136. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js +11 -0
  137. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js.map +1 -0
  138. package/lib/commonjs/fabric/ScreenContainerNativeComponent.js +33 -0
  139. package/lib/commonjs/fabric/ScreenContainerNativeComponent.js.map +1 -0
  140. package/lib/commonjs/fabric/ScreenNativeComponent.js +70 -0
  141. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -0
  142. package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js +11 -0
  143. package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -0
  144. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +31 -0
  145. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -0
  146. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +12 -0
  147. package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -0
  148. package/lib/commonjs/fabric/ScreenStackNativeComponent.js +35 -0
  149. package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -0
  150. package/lib/commonjs/fabric/SearchBarNativeComponent.js +19 -0
  151. package/lib/commonjs/fabric/SearchBarNativeComponent.js.map +1 -0
  152. package/lib/commonjs/index.js +147 -0
  153. package/lib/commonjs/index.js.map +1 -0
  154. package/lib/commonjs/index.native.js +407 -0
  155. package/lib/commonjs/index.native.js.map +1 -0
  156. package/lib/commonjs/native-stack/index.js +49 -0
  157. package/lib/commonjs/native-stack/index.js.map +1 -0
  158. package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js +75 -0
  159. package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js.map +1 -0
  160. package/lib/commonjs/native-stack/types.js +6 -0
  161. package/lib/commonjs/native-stack/types.js.map +1 -0
  162. package/lib/commonjs/native-stack/utils/AnimatedHeaderHeightContext.js +12 -0
  163. package/lib/commonjs/native-stack/utils/AnimatedHeaderHeightContext.js.map +1 -0
  164. package/lib/commonjs/native-stack/utils/HeaderHeightContext.js +12 -0
  165. package/lib/commonjs/native-stack/utils/HeaderHeightContext.js.map +1 -0
  166. package/lib/commonjs/native-stack/utils/SafeAreaProviderCompat.js +75 -0
  167. package/lib/commonjs/native-stack/utils/SafeAreaProviderCompat.js.map +1 -0
  168. package/lib/commonjs/native-stack/utils/getDefaultHeaderHeight.js +35 -0
  169. package/lib/commonjs/native-stack/utils/getDefaultHeaderHeight.js.map +1 -0
  170. package/lib/commonjs/native-stack/utils/useAnimatedHeaderHeight.js +19 -0
  171. package/lib/commonjs/native-stack/utils/useAnimatedHeaderHeight.js.map +1 -0
  172. package/lib/commonjs/native-stack/utils/useBackPressSubscription.js +54 -0
  173. package/lib/commonjs/native-stack/utils/useBackPressSubscription.js.map +1 -0
  174. package/lib/commonjs/native-stack/utils/useHeaderHeight.js +19 -0
  175. package/lib/commonjs/native-stack/utils/useHeaderHeight.js.map +1 -0
  176. package/lib/commonjs/native-stack/views/FontProcessor.js +21 -0
  177. package/lib/commonjs/native-stack/views/FontProcessor.js.map +1 -0
  178. package/lib/commonjs/native-stack/views/HeaderConfig.js +141 -0
  179. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -0
  180. package/lib/commonjs/native-stack/views/NativeStackView.js +354 -0
  181. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -0
  182. package/lib/commonjs/reanimated/ReanimatedHeaderHeightContext.js +12 -0
  183. package/lib/commonjs/reanimated/ReanimatedHeaderHeightContext.js.map +1 -0
  184. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +101 -0
  185. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -0
  186. package/lib/commonjs/reanimated/ReanimatedScreen.js +22 -0
  187. package/lib/commonjs/reanimated/ReanimatedScreen.js.map +1 -0
  188. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js +47 -0
  189. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js.map +1 -0
  190. package/lib/commonjs/reanimated/ReanimatedTransitionProgressContext.js +12 -0
  191. package/lib/commonjs/reanimated/ReanimatedTransitionProgressContext.js.map +1 -0
  192. package/lib/commonjs/reanimated/index.js +28 -0
  193. package/lib/commonjs/reanimated/index.js.map +1 -0
  194. package/lib/commonjs/reanimated/useReanimatedHeaderHeight.js +19 -0
  195. package/lib/commonjs/reanimated/useReanimatedHeaderHeight.js.map +1 -0
  196. package/lib/commonjs/reanimated/useReanimatedTransitionProgress.js +19 -0
  197. package/lib/commonjs/reanimated/useReanimatedTransitionProgress.js.map +1 -0
  198. package/lib/commonjs/types.js +6 -0
  199. package/lib/commonjs/types.js.map +1 -0
  200. package/lib/commonjs/useTransitionProgress.js +19 -0
  201. package/lib/commonjs/useTransitionProgress.js.map +1 -0
  202. package/lib/commonjs/utils.js +21 -0
  203. package/lib/commonjs/utils.js.map +1 -0
  204. package/lib/module/TransitionProgressContext.js +3 -0
  205. package/lib/module/TransitionProgressContext.js.map +1 -0
  206. package/lib/module/fabric/FullWindowOverlayNativeComponent.js +4 -0
  207. package/lib/module/fabric/FullWindowOverlayNativeComponent.js.map +1 -0
  208. package/lib/module/fabric/ScreenContainerNativeComponent.js +25 -0
  209. package/lib/module/fabric/ScreenContainerNativeComponent.js.map +1 -0
  210. package/lib/module/fabric/ScreenNativeComponent.js +63 -0
  211. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -0
  212. package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js +4 -0
  213. package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -0
  214. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +23 -0
  215. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -0
  216. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +7 -0
  217. package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -0
  218. package/lib/module/fabric/ScreenStackNativeComponent.js +28 -0
  219. package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -0
  220. package/lib/module/fabric/SearchBarNativeComponent.js +10 -0
  221. package/lib/module/fabric/SearchBarNativeComponent.js.map +1 -0
  222. package/lib/module/index.js +67 -0
  223. package/lib/module/index.js.map +1 -0
  224. package/lib/module/index.native.js +410 -0
  225. package/lib/module/index.native.js.map +1 -0
  226. package/lib/module/native-stack/index.js +22 -0
  227. package/lib/module/native-stack/index.js.map +1 -0
  228. package/lib/module/native-stack/navigators/createNativeStackNavigator.js +72 -0
  229. package/lib/module/native-stack/navigators/createNativeStackNavigator.js.map +1 -0
  230. package/lib/module/native-stack/types.js +2 -0
  231. package/lib/module/native-stack/types.js.map +1 -0
  232. package/lib/module/native-stack/utils/AnimatedHeaderHeightContext.js +4 -0
  233. package/lib/module/native-stack/utils/AnimatedHeaderHeightContext.js.map +1 -0
  234. package/lib/module/native-stack/utils/HeaderHeightContext.js +4 -0
  235. package/lib/module/native-stack/utils/HeaderHeightContext.js.map +1 -0
  236. package/lib/module/native-stack/utils/SafeAreaProviderCompat.js +68 -0
  237. package/lib/module/native-stack/utils/SafeAreaProviderCompat.js.map +1 -0
  238. package/lib/module/native-stack/utils/getDefaultHeaderHeight.js +29 -0
  239. package/lib/module/native-stack/utils/getDefaultHeaderHeight.js.map +1 -0
  240. package/lib/module/native-stack/utils/useAnimatedHeaderHeight.js +10 -0
  241. package/lib/module/native-stack/utils/useAnimatedHeaderHeight.js.map +1 -0
  242. package/lib/module/native-stack/utils/useBackPressSubscription.js +47 -0
  243. package/lib/module/native-stack/utils/useBackPressSubscription.js.map +1 -0
  244. package/lib/module/native-stack/utils/useHeaderHeight.js +10 -0
  245. package/lib/module/native-stack/utils/useHeaderHeight.js.map +1 -0
  246. package/lib/module/native-stack/views/FontProcessor.js +13 -0
  247. package/lib/module/native-stack/views/FontProcessor.js.map +1 -0
  248. package/lib/module/native-stack/views/HeaderConfig.js +132 -0
  249. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -0
  250. package/lib/module/native-stack/views/NativeStackView.js +355 -0
  251. package/lib/module/native-stack/views/NativeStackView.js.map +1 -0
  252. package/lib/module/reanimated/ReanimatedHeaderHeightContext.js +5 -0
  253. package/lib/module/reanimated/ReanimatedHeaderHeightContext.js.map +1 -0
  254. package/lib/module/reanimated/ReanimatedNativeStackScreen.js +97 -0
  255. package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -0
  256. package/lib/module/reanimated/ReanimatedScreen.js +17 -0
  257. package/lib/module/reanimated/ReanimatedScreen.js.map +1 -0
  258. package/lib/module/reanimated/ReanimatedScreenProvider.js +40 -0
  259. package/lib/module/reanimated/ReanimatedScreenProvider.js.map +1 -0
  260. package/lib/module/reanimated/ReanimatedTransitionProgressContext.js +5 -0
  261. package/lib/module/reanimated/ReanimatedTransitionProgressContext.js.map +1 -0
  262. package/lib/module/reanimated/index.js +4 -0
  263. package/lib/module/reanimated/index.js.map +1 -0
  264. package/lib/module/reanimated/useReanimatedHeaderHeight.js +10 -0
  265. package/lib/module/reanimated/useReanimatedHeaderHeight.js.map +1 -0
  266. package/lib/module/reanimated/useReanimatedTransitionProgress.js +10 -0
  267. package/lib/module/reanimated/useReanimatedTransitionProgress.js.map +1 -0
  268. package/lib/module/types.js +2 -0
  269. package/lib/module/types.js.map +1 -0
  270. package/lib/module/useTransitionProgress.js +10 -0
  271. package/lib/module/useTransitionProgress.js.map +1 -0
  272. package/lib/module/utils.js +14 -0
  273. package/lib/module/utils.js.map +1 -0
  274. package/lib/typescript/TransitionProgressContext.d.ts +9 -0
  275. package/lib/typescript/fabric/FullWindowOverlayNativeComponent.d.ts +7 -0
  276. package/lib/typescript/fabric/ScreenContainerNativeComponent.d.ts +5 -0
  277. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +66 -0
  278. package/lib/typescript/fabric/ScreenNavigationContainerNativeComponent.d.ts +7 -0
  279. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +33 -0
  280. package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts +10 -0
  281. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts +8 -0
  282. package/lib/typescript/fabric/SearchBarNativeComponent.d.ts +49 -0
  283. package/lib/typescript/index.d.ts +33 -0
  284. package/lib/typescript/index.native.d.ts +2 -0
  285. package/lib/typescript/native-stack/index.d.ts +19 -0
  286. package/lib/typescript/native-stack/navigators/createNativeStackNavigator.d.ts +6 -0
  287. package/lib/typescript/native-stack/types.d.ts +438 -0
  288. package/lib/typescript/native-stack/utils/AnimatedHeaderHeightContext.d.ts +4 -0
  289. package/lib/typescript/native-stack/utils/HeaderHeightContext.d.ts +3 -0
  290. package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts +11 -0
  291. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts +7 -0
  292. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts +1 -0
  293. package/lib/typescript/native-stack/utils/useBackPressSubscription.d.ts +16 -0
  294. package/lib/typescript/native-stack/utils/useHeaderHeight.d.ts +1 -0
  295. package/lib/typescript/native-stack/views/FontProcessor.d.ts +1 -0
  296. package/lib/typescript/native-stack/views/HeaderConfig.d.ts +8 -0
  297. package/lib/typescript/native-stack/views/NativeStackView.d.ts +10 -0
  298. package/lib/typescript/reanimated/ReanimatedHeaderHeightContext.d.ts +4 -0
  299. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +5 -0
  300. package/lib/typescript/reanimated/ReanimatedScreen.d.ts +5 -0
  301. package/lib/typescript/reanimated/ReanimatedScreenProvider.d.ts +2 -0
  302. package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts +9 -0
  303. package/lib/typescript/reanimated/index.d.ts +3 -0
  304. package/lib/typescript/reanimated/useReanimatedHeaderHeight.d.ts +3 -0
  305. package/lib/typescript/reanimated/useReanimatedTransitionProgress.d.ts +11 -0
  306. package/lib/typescript/types.d.ts +612 -0
  307. package/lib/typescript/useTransitionProgress.d.ts +5 -0
  308. package/lib/typescript/utils.d.ts +3 -0
  309. package/native-stack/README.md +814 -0
  310. package/native-stack/package.json +6 -0
  311. package/package.json +1 -0
  312. package/react-native.config.js +42 -0
  313. package/reanimated/package.json +6 -0
  314. package/src/TransitionProgressContext.tsx +12 -0
  315. package/src/fabric/FullWindowOverlayNativeComponent.ts +7 -0
  316. package/src/fabric/ScreenContainerNativeComponent.ts +28 -0
  317. package/src/fabric/ScreenNativeComponent.ts +158 -0
  318. package/src/fabric/ScreenNavigationContainerNativeComponent.ts +10 -0
  319. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +61 -0
  320. package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +22 -0
  321. package/src/fabric/ScreenStackNativeComponent.ts +33 -0
  322. package/src/fabric/SearchBarNativeComponent.ts +79 -0
  323. package/src/index.native.tsx +599 -0
  324. package/src/index.tsx +119 -0
  325. package/src/native-stack/index.tsx +27 -0
  326. package/src/native-stack/navigators/createNativeStackNavigator.tsx +107 -0
  327. package/src/native-stack/types.tsx +486 -0
  328. package/src/native-stack/utils/AnimatedHeaderHeightContext.tsx +8 -0
  329. package/src/native-stack/utils/HeaderHeightContext.tsx +5 -0
  330. package/src/native-stack/utils/SafeAreaProviderCompat.tsx +78 -0
  331. package/src/native-stack/utils/getDefaultHeaderHeight.tsx +41 -0
  332. package/src/native-stack/utils/useAnimatedHeaderHeight.tsx +15 -0
  333. package/src/native-stack/utils/useBackPressSubscription.tsx +66 -0
  334. package/src/native-stack/utils/useHeaderHeight.tsx +15 -0
  335. package/src/native-stack/views/FontProcessor.tsx +14 -0
  336. package/src/native-stack/views/HeaderConfig.tsx +187 -0
  337. package/src/native-stack/views/NativeStackView.tsx +466 -0
  338. package/src/reanimated/ReanimatedHeaderHeightContext.tsx +7 -0
  339. package/src/reanimated/ReanimatedNativeStackScreen.tsx +130 -0
  340. package/src/reanimated/ReanimatedScreen.tsx +25 -0
  341. package/src/reanimated/ReanimatedScreenProvider.tsx +42 -0
  342. package/src/reanimated/ReanimatedTransitionProgressContext.tsx +13 -0
  343. package/src/reanimated/index.tsx +3 -0
  344. package/src/reanimated/useReanimatedHeaderHeight.tsx +14 -0
  345. package/src/reanimated/useReanimatedTransitionProgress.tsx +14 -0
  346. package/src/types.tsx +699 -0
  347. package/src/useTransitionProgress.tsx +15 -0
  348. package/src/utils.ts +18 -0
  349. package/windows/README.md +25 -0
  350. package/windows/RNScreens/PropertySheet.props +16 -0
  351. package/windows/RNScreens/RNScreens.cpp +66 -0
  352. package/windows/RNScreens/RNScreens.def +3 -0
  353. package/windows/RNScreens/RNScreens.h +41 -0
  354. package/windows/RNScreens/RNScreens.idl +8 -0
  355. package/windows/RNScreens/RNScreens.vcxproj +187 -0
  356. package/windows/RNScreens/RNScreens.vcxproj.filters +52 -0
  357. package/windows/RNScreens/ReactPackageProvider.cpp +30 -0
  358. package/windows/RNScreens/ReactPackageProvider.h +17 -0
  359. package/windows/RNScreens/ReactPackageProvider.idl +9 -0
  360. package/windows/RNScreens/Screen.cpp +122 -0
  361. package/windows/RNScreens/Screen.h +64 -0
  362. package/windows/RNScreens/ScreenContainer.cpp +49 -0
  363. package/windows/RNScreens/ScreenContainer.h +23 -0
  364. package/windows/RNScreens/ScreenContainerViewManager.cpp +133 -0
  365. package/windows/RNScreens/ScreenContainerViewManager.h +78 -0
  366. package/windows/RNScreens/ScreenStack.cpp +65 -0
  367. package/windows/RNScreens/ScreenStack.h +23 -0
  368. package/windows/RNScreens/ScreenStackHeaderConfig.cpp +19 -0
  369. package/windows/RNScreens/ScreenStackHeaderConfig.h +14 -0
  370. package/windows/RNScreens/ScreenStackHeaderConfigViewManager.cpp +89 -0
  371. package/windows/RNScreens/ScreenStackHeaderConfigViewManager.h +62 -0
  372. package/windows/RNScreens/ScreenStackViewManager.cpp +132 -0
  373. package/windows/RNScreens/ScreenStackViewManager.h +78 -0
  374. package/windows/RNScreens/ScreenViewManager.cpp +154 -0
  375. package/windows/RNScreens/ScreenViewManager.h +78 -0
  376. package/windows/RNScreens/packages.config +4 -0
  377. package/windows/RNScreens/pch.cpp +1 -0
  378. package/windows/RNScreens/pch.h +9 -0
  379. package/windows/RNScreens62.sln +254 -0
  380. package/windows/RNScreens63.sln +225 -0
  381. package/windows/RNScreens65.sln +144 -0
@@ -0,0 +1,331 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.app.Activity
5
+ import android.content.Context
6
+ import android.os.Bundle
7
+ import android.view.LayoutInflater
8
+ import android.view.View
9
+ import android.view.ViewGroup
10
+ import android.view.ViewParent
11
+ import android.widget.FrameLayout
12
+ import androidx.fragment.app.Fragment
13
+ import com.facebook.react.bridge.ReactContext
14
+ import com.facebook.react.bridge.UiThreadUtil
15
+ import com.facebook.react.uimanager.UIManagerHelper
16
+ import com.facebook.react.uimanager.events.Event
17
+ import com.facebook.react.uimanager.events.EventDispatcher
18
+ import com.swmansion.rnscreens.events.HeaderBackButtonClickedEvent
19
+ import com.swmansion.rnscreens.events.ScreenAppearEvent
20
+ import com.swmansion.rnscreens.events.ScreenDisappearEvent
21
+ import com.swmansion.rnscreens.events.ScreenDismissedEvent
22
+ import com.swmansion.rnscreens.events.ScreenTransitionProgressEvent
23
+ import com.swmansion.rnscreens.events.ScreenWillAppearEvent
24
+ import com.swmansion.rnscreens.events.ScreenWillDisappearEvent
25
+ import kotlin.math.max
26
+ import kotlin.math.min
27
+
28
+ open class ScreenFragment : Fragment, ScreenFragmentWrapper {
29
+ enum class ScreenLifecycleEvent {
30
+ Appear, WillAppear, Disappear, WillDisappear
31
+ }
32
+
33
+ override val fragment: Fragment
34
+ get() = this
35
+
36
+ // if we call empty constructor, there is no screen to be assigned so not sure why it is suggested
37
+ @Suppress("JoinDeclarationAndAssignment")
38
+ override lateinit var screen: Screen
39
+ private val mChildScreenContainers: MutableList<ScreenContainer> = ArrayList()
40
+ private var shouldUpdateOnResume = false
41
+ // if we don't set it, it will be 0.0f at the beginning so the progress will not be sent
42
+ // due to progress value being already 0.0f
43
+ private var mProgress = -1f
44
+
45
+ // those 2 vars are needed since sometimes the events would be dispatched twice in child containers
46
+ // (should only happen if parent has `NONE` animation) and we don't need too complicated logic.
47
+ // We just check if, after the event was dispatched, its "counter-event" has been also dispatched before sending the same event again.
48
+ // We do it for 'willAppear' -> 'willDisappear' and 'appear' -> 'disappear'
49
+ private var canDispatchWillAppear = true
50
+ private var canDispatchAppear = true
51
+
52
+ // we want to know if we are currently transitioning in order not to fire lifecycle events
53
+ // in nested fragments. See more explanation in dispatchViewAnimationEvent
54
+ private var isTransitioning = false
55
+
56
+ constructor() {
57
+ throw IllegalStateException(
58
+ "Screen fragments should never be restored. Follow instructions from https://github.com/software-mansion/react-native-screens/issues/17#issuecomment-424704067 to properly configure your main activity."
59
+ )
60
+ }
61
+
62
+ @SuppressLint("ValidFragment")
63
+ constructor(screenView: Screen) : super() {
64
+ screen = screenView
65
+ }
66
+
67
+ override fun onResume() {
68
+ super.onResume()
69
+ if (shouldUpdateOnResume) {
70
+ shouldUpdateOnResume = false
71
+ ScreenWindowTraits.trySetWindowTraits(screen, tryGetActivity(), tryGetContext())
72
+ }
73
+ }
74
+
75
+ override fun onCreateView(
76
+ inflater: LayoutInflater,
77
+ container: ViewGroup?,
78
+ savedInstanceState: Bundle?
79
+ ): View? {
80
+ screen.layoutParams = FrameLayout.LayoutParams(
81
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
82
+ )
83
+ val wrapper = context?.let { ScreensFrameLayout(it) }?.apply {
84
+ addView(recycleView(screen))
85
+ }
86
+ return wrapper
87
+ }
88
+
89
+ private class ScreensFrameLayout(
90
+ context: Context,
91
+ ) : FrameLayout(context) {
92
+ /**
93
+ * This method implements a workaround for RN's autoFocus functionality. Because of the way
94
+ * autoFocus is implemented it dismisses soft keyboard in fragment transition
95
+ * due to change of visibility of the view at the start of the transition. Here we override the
96
+ * call to `clearFocus` when the visibility of view is `INVISIBLE` since `clearFocus` triggers the
97
+ * hiding of the keyboard in `ReactEditText.java`.
98
+ */
99
+ override fun clearFocus() {
100
+ if (visibility != INVISIBLE) {
101
+ super.clearFocus()
102
+ }
103
+ }
104
+ }
105
+
106
+ override fun onContainerUpdate() {
107
+ updateWindowTraits()
108
+ }
109
+
110
+ private fun updateWindowTraits() {
111
+ val activity: Activity? = activity
112
+ if (activity == null) {
113
+ shouldUpdateOnResume = true
114
+ return
115
+ }
116
+ ScreenWindowTraits.trySetWindowTraits(screen, activity, tryGetContext())
117
+ }
118
+
119
+ override fun tryGetActivity(): Activity? {
120
+ activity?.let { return it }
121
+ val context = screen.context
122
+ if (context is ReactContext && context.currentActivity != null) {
123
+ return context.currentActivity
124
+ }
125
+ var parent: ViewParent? = screen.container
126
+ while (parent != null) {
127
+ if (parent is Screen) {
128
+ val fragment = parent.fragment
129
+ fragment?.activity?.let { return it }
130
+ }
131
+ parent = parent.parent
132
+ }
133
+ return null
134
+ }
135
+
136
+ override fun tryGetContext(): ReactContext? {
137
+ if (context is ReactContext) {
138
+ return context as ReactContext
139
+ }
140
+ if (screen.context is ReactContext) {
141
+ return screen.context as ReactContext
142
+ }
143
+ var parent: ViewParent? = screen.container
144
+ while (parent != null) {
145
+ if (parent is Screen) {
146
+ if (parent.context is ReactContext) {
147
+ return parent.context as ReactContext
148
+ }
149
+ }
150
+ parent = parent.parent
151
+ }
152
+ return null
153
+ }
154
+
155
+ override val childScreenContainers: List<ScreenContainer>
156
+ get() = mChildScreenContainers
157
+
158
+ override fun canDispatchLifecycleEvent(event: ScreenLifecycleEvent): Boolean = when (event) {
159
+ ScreenLifecycleEvent.WillAppear -> canDispatchWillAppear
160
+ ScreenLifecycleEvent.Appear -> canDispatchAppear
161
+ ScreenLifecycleEvent.WillDisappear -> !canDispatchWillAppear
162
+ ScreenLifecycleEvent.Disappear -> !canDispatchAppear
163
+ }
164
+
165
+ override fun updateLastEventDispatched(event: ScreenLifecycleEvent) {
166
+ when (event) {
167
+ ScreenLifecycleEvent.WillAppear -> canDispatchWillAppear = false
168
+ ScreenLifecycleEvent.Appear -> canDispatchAppear = false
169
+ ScreenLifecycleEvent.WillDisappear -> canDispatchWillAppear = true
170
+ ScreenLifecycleEvent.Disappear -> canDispatchAppear = true
171
+ }
172
+ }
173
+
174
+ private fun dispatchOnWillAppear() {
175
+ dispatchLifecycleEvent(ScreenLifecycleEvent.WillAppear, this)
176
+ dispatchTransitionProgressEvent(0.0f, false)
177
+ }
178
+
179
+ private fun dispatchOnAppear() {
180
+ dispatchLifecycleEvent(ScreenLifecycleEvent.Appear, this)
181
+ dispatchTransitionProgressEvent(1.0f, false)
182
+ }
183
+
184
+ private fun dispatchOnWillDisappear() {
185
+ dispatchLifecycleEvent(ScreenLifecycleEvent.WillDisappear, this)
186
+ dispatchTransitionProgressEvent(0.0f, true)
187
+ }
188
+
189
+ private fun dispatchOnDisappear() {
190
+ dispatchLifecycleEvent(ScreenLifecycleEvent.Disappear, this)
191
+ dispatchTransitionProgressEvent(1.0f, true)
192
+ }
193
+
194
+ override fun dispatchLifecycleEvent(event: ScreenLifecycleEvent, fragmentWrapper: ScreenFragmentWrapper) {
195
+ val fragment = fragmentWrapper.fragment
196
+ if (fragment is ScreenStackFragment && fragment.canDispatchLifecycleEvent(event)) {
197
+ fragment.screen.let {
198
+ fragmentWrapper.updateLastEventDispatched(event)
199
+ val surfaceId = UIManagerHelper.getSurfaceId(it)
200
+ val lifecycleEvent: Event<*> = when (event) {
201
+ ScreenLifecycleEvent.WillAppear -> ScreenWillAppearEvent(surfaceId, it.id)
202
+ ScreenLifecycleEvent.Appear -> ScreenAppearEvent(surfaceId, it.id)
203
+ ScreenLifecycleEvent.WillDisappear -> ScreenWillDisappearEvent(surfaceId, it.id)
204
+ ScreenLifecycleEvent.Disappear -> ScreenDisappearEvent(surfaceId, it.id)
205
+ }
206
+ val screenContext = screen.context as ReactContext
207
+ val eventDispatcher: EventDispatcher? =
208
+ UIManagerHelper.getEventDispatcherForReactTag(screenContext, screen.id)
209
+ eventDispatcher?.dispatchEvent(lifecycleEvent)
210
+ fragmentWrapper.dispatchLifecycleEventInChildContainers(event)
211
+ }
212
+ }
213
+ }
214
+
215
+ override fun dispatchLifecycleEventInChildContainers(event: ScreenLifecycleEvent) {
216
+ mChildScreenContainers.filter { it.screenCount > 0 }.forEach {
217
+ it.topScreen?.fragmentWrapper?.let { fragment -> dispatchLifecycleEvent(event, fragment) }
218
+ }
219
+ }
220
+
221
+ override fun dispatchHeaderBackButtonClickedEvent() {
222
+ val screenContext = screen.context as ReactContext
223
+ val surfaceId = UIManagerHelper.getSurfaceId(screenContext)
224
+ UIManagerHelper
225
+ .getEventDispatcherForReactTag(screenContext, screen.id)
226
+ ?.dispatchEvent(HeaderBackButtonClickedEvent(surfaceId, screen.id))
227
+ }
228
+
229
+ override fun dispatchTransitionProgressEvent(alpha: Float, closing: Boolean) {
230
+ if (this is ScreenStackFragment) {
231
+ if (mProgress != alpha) {
232
+ mProgress = max(0.0f, min(1.0f, alpha))
233
+ /* We want value of 0 and 1 to be always dispatched so we base coalescing key on the progress:
234
+ - progress is 0 -> key 1
235
+ - progress is 1 -> key 2
236
+ - progress is between 0 and 1 -> key 3
237
+ */
238
+ val coalescingKey = (if (mProgress == 0.0f) 1 else if (mProgress == 1.0f) 2 else 3).toShort()
239
+ val container: ScreenContainer? = screen.container
240
+ val goingForward = if (container is ScreenStack) container.goingForward else false
241
+ val screenContext = screen.context as ReactContext
242
+ UIManagerHelper
243
+ .getEventDispatcherForReactTag(screenContext, screen.id)
244
+ ?.dispatchEvent(
245
+ ScreenTransitionProgressEvent(
246
+ UIManagerHelper.getSurfaceId(screenContext),
247
+ screen.id, mProgress, closing, goingForward, coalescingKey
248
+ )
249
+ )
250
+ }
251
+ }
252
+ }
253
+
254
+ override fun addChildScreenContainer(container: ScreenContainer) {
255
+ mChildScreenContainers.add(container)
256
+ }
257
+
258
+ override fun removeChildScreenContainer(container: ScreenContainer) {
259
+ mChildScreenContainers.remove(container)
260
+ }
261
+
262
+ override fun onViewAnimationStart() {
263
+ dispatchViewAnimationEvent(false)
264
+ }
265
+
266
+ override fun onViewAnimationEnd() {
267
+ dispatchViewAnimationEvent(true)
268
+ }
269
+
270
+ private fun dispatchViewAnimationEvent(animationEnd: Boolean) {
271
+ isTransitioning = !animationEnd
272
+ // if parent fragment is transitioning, we do not want the events dispatched from the child,
273
+ // since we subscribe to parent's animation start/end and dispatch events in child from there
274
+ // check for `isTransitioning` should be enough since the child's animation should take only
275
+ // 20ms due to always being `StackAnimation.NONE` when nested stack being pushed
276
+ val parent = parentFragment
277
+ if (parent == null || (parent is ScreenFragment && !parent.isTransitioning)) {
278
+ // onViewAnimationStart/End is triggered from View#onAnimationStart/End method of the fragment's root
279
+ // view. We override an appropriate method of the StackFragment's
280
+ // root view in order to achieve this.
281
+ if (isResumed) {
282
+ // Android dispatches the animation start event for the fragment that is being added first
283
+ // however we want the one being dismissed first to match iOS. It also makes more sense from
284
+ // a navigation point of view to have the disappear event first.
285
+ // Since there are no explicit relationships between the fragment being added / removed the
286
+ // practical way to fix this is delaying dispatching the appear events at the end of the
287
+ // frame.
288
+ UiThreadUtil.runOnUiThread {
289
+ if (animationEnd) dispatchOnAppear() else dispatchOnWillAppear()
290
+ }
291
+ } else {
292
+ if (animationEnd) dispatchOnDisappear() else dispatchOnWillDisappear()
293
+ }
294
+ }
295
+ }
296
+
297
+ override fun onDestroy() {
298
+ super.onDestroy()
299
+ val container = screen.container
300
+ if (container == null || !container.hasScreen(this)) {
301
+ // we only send dismissed even when the screen has been removed from its container
302
+ val screenContext = screen.context
303
+ if (screenContext is ReactContext) {
304
+ val surfaceId = UIManagerHelper.getSurfaceId(screenContext)
305
+ UIManagerHelper
306
+ .getEventDispatcherForReactTag(screenContext, screen.id)
307
+ ?.dispatchEvent(ScreenDismissedEvent(surfaceId, screen.id))
308
+ }
309
+ }
310
+ mChildScreenContainers.clear()
311
+ }
312
+
313
+ companion object {
314
+ @JvmStatic
315
+ protected fun recycleView(view: View): View {
316
+ // screen fragments reuse view instances instead of creating new ones. In order to reuse a given
317
+ // view it needs to be detached from the view hierarchy to allow the fragment to attach it back.
318
+ val parent = view.parent
319
+ if (parent != null) {
320
+ (parent as ViewGroup).endViewTransition(view)
321
+ parent.removeView(view)
322
+ }
323
+
324
+ // view detached from fragment manager get their visibility changed to GONE after their state is
325
+ // dumped. Since we don't restore the state but want to reuse the view we need to change
326
+ // visibility back to VISIBLE in order for the fragment manager to animate in the view.
327
+ view.visibility = View.VISIBLE
328
+ return view
329
+ }
330
+ }
331
+ }
@@ -0,0 +1,22 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.app.Activity
4
+ import com.facebook.react.bridge.ReactContext
5
+
6
+ interface ScreenFragmentWrapper : FragmentHolder, ScreenEventDispatcher {
7
+ var screen: Screen
8
+
9
+ // Communication with container
10
+ val childScreenContainers: List<ScreenContainer>
11
+ fun addChildScreenContainer(container: ScreenContainer)
12
+ fun removeChildScreenContainer(container: ScreenContainer)
13
+ fun onContainerUpdate()
14
+
15
+ // Animation phase callbacks
16
+ fun onViewAnimationStart()
17
+ fun onViewAnimationEnd()
18
+
19
+ // Helpers
20
+ fun tryGetActivity(): Activity?
21
+ fun tryGetContext(): ReactContext?
22
+ }
@@ -0,0 +1,336 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.content.Context
4
+ import android.graphics.Canvas
5
+ import android.view.View
6
+ import com.facebook.react.bridge.ReactContext
7
+ import com.facebook.react.uimanager.UIManagerHelper
8
+ import com.swmansion.rnscreens.Screen.StackAnimation
9
+ import com.swmansion.rnscreens.events.StackFinishTransitioningEvent
10
+ import java.util.Collections
11
+ import kotlin.collections.ArrayList
12
+ import kotlin.collections.HashSet
13
+
14
+ class ScreenStack(context: Context?) : ScreenContainer(context) {
15
+ private val mStack = ArrayList<ScreenStackFragmentWrapper>()
16
+ private val mDismissed: MutableSet<ScreenStackFragmentWrapper> = HashSet()
17
+ private val drawingOpPool: MutableList<DrawingOp> = ArrayList()
18
+ private var drawingOps: MutableList<DrawingOp> = ArrayList()
19
+ private var mTopScreen: ScreenStackFragmentWrapper? = null
20
+ private var mRemovalTransitionStarted = false
21
+ private var isDetachingCurrentScreen = false
22
+ private var reverseLastTwoChildren = false
23
+ private var previousChildrenCount = 0
24
+ var goingForward = false
25
+
26
+ fun dismiss(screenFragment: ScreenStackFragmentWrapper) {
27
+ mDismissed.add(screenFragment)
28
+ performUpdatesNow()
29
+ }
30
+
31
+ override val topScreen: Screen?
32
+ get() = mTopScreen?.screen
33
+
34
+ val rootScreen: Screen
35
+ get() {
36
+ for (i in 0 until screenCount) {
37
+ val screenWrapper = getScreenFragmentWrapperAt(i)
38
+ if (!mDismissed.contains(screenWrapper)) {
39
+ return screenWrapper.screen
40
+ }
41
+ }
42
+ throw IllegalStateException("Stack has no root screen set")
43
+ }
44
+
45
+ override fun adapt(screen: Screen) = ScreenStackFragment(screen)
46
+
47
+ override fun startViewTransition(view: View) {
48
+ super.startViewTransition(view)
49
+ mRemovalTransitionStarted = true
50
+ }
51
+
52
+ override fun endViewTransition(view: View) {
53
+ super.endViewTransition(view)
54
+ if (mRemovalTransitionStarted) {
55
+ mRemovalTransitionStarted = false
56
+ dispatchOnFinishTransitioning()
57
+ }
58
+ }
59
+
60
+ fun onViewAppearTransitionEnd() {
61
+ if (!mRemovalTransitionStarted) {
62
+ dispatchOnFinishTransitioning()
63
+ }
64
+ }
65
+
66
+ private fun dispatchOnFinishTransitioning() {
67
+ val surfaceId = UIManagerHelper.getSurfaceId(this)
68
+ UIManagerHelper
69
+ .getEventDispatcherForReactTag((context as ReactContext), id)
70
+ ?.dispatchEvent(StackFinishTransitioningEvent(surfaceId, id))
71
+ }
72
+
73
+ override fun removeScreenAt(index: Int) {
74
+ mDismissed.remove(getScreenFragmentWrapperAt(index))
75
+ super.removeScreenAt(index)
76
+ }
77
+
78
+ override fun removeAllScreens() {
79
+ mDismissed.clear()
80
+ super.removeAllScreens()
81
+ }
82
+
83
+ override fun hasScreen(screenFragmentWrapper: ScreenFragmentWrapper?): Boolean =
84
+ super.hasScreen(screenFragmentWrapper) && !mDismissed.contains(screenFragmentWrapper)
85
+
86
+ override fun onUpdate() {
87
+ // When going back from a nested stack with a single screen on it, we may hit an edge case
88
+ // when all screens are dismissed and no screen is to be displayed on top. We need to gracefully
89
+ // handle the case of newTop being NULL, which happens in several places below
90
+ var newTop: ScreenFragmentWrapper? = null // newTop is nullable, see the above comment ^
91
+ var visibleBottom: ScreenFragmentWrapper? = null // this is only set if newTop has TRANSPARENT_MODAL presentation mode
92
+ isDetachingCurrentScreen = false // we reset it so the previous value is not used by mistake
93
+ for (i in mScreenFragments.indices.reversed()) {
94
+ val screen = getScreenFragmentWrapperAt(i)
95
+ if (!mDismissed.contains(screen)) {
96
+ if (newTop == null) {
97
+ newTop = screen
98
+ } else {
99
+ visibleBottom = screen
100
+ }
101
+ if (!isTransparent(screen)) {
102
+ break
103
+ }
104
+ }
105
+ }
106
+ var shouldUseOpenAnimation = true
107
+ var stackAnimation: StackAnimation? = null
108
+ if (!mStack.contains(newTop)) {
109
+ // if new top screen wasn't on stack we do "open animation" so long it is not the very first
110
+ // screen on stack
111
+ if (mTopScreen != null && newTop != null) {
112
+ // there was some other screen attached before
113
+ // if the previous top screen does not exist anymore and the new top was not on the stack
114
+ // before, probably replace or reset was called, so we play the "close animation".
115
+ // Otherwise it's open animation
116
+ val containsTopScreen = mTopScreen?.let { mScreenFragments.contains(it) } == true
117
+ val isPushReplace = newTop.screen.replaceAnimation === Screen.ReplaceAnimation.PUSH
118
+ shouldUseOpenAnimation = containsTopScreen || isPushReplace
119
+ // if the replace animation is `push`, the new top screen provides the animation, otherwise the previous one
120
+ stackAnimation = if (shouldUseOpenAnimation) newTop.screen.stackAnimation else mTopScreen?.screen?.stackAnimation
121
+ } else if (mTopScreen == null && newTop != null) {
122
+ // mTopScreen was not present before so newTop is the first screen added to a stack
123
+ // and we don't want the animation when it is entering
124
+ stackAnimation = StackAnimation.NONE
125
+ goingForward = true
126
+ }
127
+ } else if (mTopScreen != null && mTopScreen != newTop) {
128
+ // otherwise if we are performing top screen change we do "close animation"
129
+ shouldUseOpenAnimation = false
130
+ stackAnimation = mTopScreen?.screen?.stackAnimation
131
+ }
132
+
133
+ createTransaction().let {
134
+ // animation logic start
135
+ if (stackAnimation != null) {
136
+ if (shouldUseOpenAnimation) {
137
+ when (stackAnimation) {
138
+ StackAnimation.DEFAULT -> it.setCustomAnimations(R.anim.rns_default_enter_in, R.anim.rns_default_enter_out)
139
+ StackAnimation.NONE -> it.setCustomAnimations(R.anim.rns_no_animation_20, R.anim.rns_no_animation_20)
140
+ StackAnimation.FADE -> it.setCustomAnimations(R.anim.rns_fade_in, R.anim.rns_fade_out)
141
+ StackAnimation.SLIDE_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left)
142
+ StackAnimation.SLIDE_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right)
143
+ StackAnimation.SLIDE_FROM_BOTTOM -> it.setCustomAnimations(
144
+ R.anim.rns_slide_in_from_bottom, R.anim.rns_no_animation_medium
145
+ )
146
+ StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_fade_from_bottom, R.anim.rns_no_animation_350)
147
+ }
148
+ } else {
149
+ when (stackAnimation) {
150
+ StackAnimation.DEFAULT -> it.setCustomAnimations(R.anim.rns_default_exit_in, R.anim.rns_default_exit_out)
151
+ StackAnimation.NONE -> it.setCustomAnimations(R.anim.rns_no_animation_20, R.anim.rns_no_animation_20)
152
+ StackAnimation.FADE -> it.setCustomAnimations(R.anim.rns_fade_in, R.anim.rns_fade_out)
153
+ StackAnimation.SLIDE_FROM_RIGHT -> it.setCustomAnimations(R.anim.rns_slide_in_from_left, R.anim.rns_slide_out_to_right)
154
+ StackAnimation.SLIDE_FROM_LEFT -> it.setCustomAnimations(R.anim.rns_slide_in_from_right, R.anim.rns_slide_out_to_left)
155
+ StackAnimation.SLIDE_FROM_BOTTOM -> it.setCustomAnimations(
156
+ R.anim.rns_no_animation_medium, R.anim.rns_slide_out_to_bottom
157
+ )
158
+ StackAnimation.FADE_FROM_BOTTOM -> it.setCustomAnimations(R.anim.rns_no_animation_250, R.anim.rns_fade_to_bottom)
159
+ }
160
+ }
161
+ }
162
+
163
+ // animation logic end
164
+ goingForward = shouldUseOpenAnimation
165
+
166
+ if (shouldUseOpenAnimation &&
167
+ newTop != null && needsDrawReordering(newTop) &&
168
+ visibleBottom == null
169
+ ) {
170
+ // When using an open animation in which two screens overlap (eg. fade_from_bottom or
171
+ // slide_from_bottom), we want to draw the previous screen under the new one,
172
+ // which is apparently not the default option. Android always draws the disappearing view
173
+ // on top of the appearing one. We then reverse the order of the views so the new screen
174
+ // appears on top of the previous one. You can read more about in the comment
175
+ // for the code we use to change that behavior:
176
+ // https://github.com/airbnb/native-navigation/blob/9cf50bf9b751b40778f473f3b19fcfe2c4d40599/lib/android/src/main/java/com/airbnb/android/react/navigation/ScreenCoordinatorLayout.java#L18
177
+ isDetachingCurrentScreen = true
178
+ }
179
+
180
+ // remove all screens previously on stack
181
+ for (fragmentWrapper in mStack) {
182
+ if (!mScreenFragments.contains(fragmentWrapper) || mDismissed.contains(fragmentWrapper)) {
183
+ it.remove(fragmentWrapper.fragment)
184
+ }
185
+ }
186
+ for (fragmentWrapper in mScreenFragments) {
187
+ // Stop detaching screens when reaching visible bottom. All screens above bottom should be
188
+ // visible.
189
+ if (fragmentWrapper === visibleBottom) {
190
+ break
191
+ }
192
+ // detach all screens that should not be visible
193
+ if (fragmentWrapper !== newTop && !mDismissed.contains(fragmentWrapper)) {
194
+ it.remove(fragmentWrapper.fragment)
195
+ }
196
+ }
197
+
198
+ // attach screens that just became visible
199
+ if (visibleBottom != null && !visibleBottom.fragment.isAdded) {
200
+ val top = newTop
201
+ var beneathVisibleBottom = true
202
+ for (fragmentWrapper in mScreenFragments) {
203
+ // ignore all screens beneath the visible bottom
204
+ if (beneathVisibleBottom) {
205
+ beneathVisibleBottom = if (fragmentWrapper === visibleBottom) {
206
+ false
207
+ } else continue
208
+ }
209
+ // when first visible screen found, make all screens after that visible
210
+ it.add(id, fragmentWrapper.fragment).runOnCommit { top?.screen?.bringToFront() }
211
+ }
212
+ } else if (newTop != null && !newTop.fragment.isAdded) {
213
+ it.add(id, newTop.fragment)
214
+ }
215
+ mTopScreen = newTop as? ScreenStackFragmentWrapper
216
+ mStack.clear()
217
+ mStack.addAll(mScreenFragments.map { it as ScreenStackFragmentWrapper })
218
+
219
+ turnOffA11yUnderTransparentScreen(visibleBottom)
220
+
221
+ it.commitNowAllowingStateLoss()
222
+ }
223
+ }
224
+
225
+ // only top visible screen should be accessible
226
+ private fun turnOffA11yUnderTransparentScreen(visibleBottom: ScreenFragmentWrapper?) {
227
+ if (mScreenFragments.size > 1 && visibleBottom != null) {
228
+ mTopScreen?.let {
229
+ if (isTransparent(it)) {
230
+ val screenFragmentsBeneathTop = mScreenFragments.slice(0 until mScreenFragments.size - 1).asReversed()
231
+ // go from the top of the stack excluding the top screen
232
+ for (fragmentWrapper in screenFragmentsBeneathTop) {
233
+ fragmentWrapper.screen.changeAccessibilityMode(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
234
+
235
+ // don't change a11y below non-transparent screens
236
+ if (fragmentWrapper == visibleBottom) {
237
+ break
238
+ }
239
+ }
240
+ }
241
+ }
242
+ }
243
+
244
+ topScreen?.changeAccessibilityMode(IMPORTANT_FOR_ACCESSIBILITY_AUTO)
245
+ }
246
+
247
+ override fun notifyContainerUpdate() {
248
+ mStack.forEach { it.onContainerUpdate() }
249
+ }
250
+
251
+ // below methods are taken from
252
+ // https://github.com/airbnb/native-navigation/blob/9cf50bf9b751b40778f473f3b19fcfe2c4d40599/lib/android/src/main/java/com/airbnb/android/react/navigation/ScreenCoordinatorLayout.java#L43
253
+ // and are used to swap the order of drawing views when navigating forward with the transitions
254
+ // that are making transitioning fragments appear one on another. See more info in the comment to
255
+ // the linked class.
256
+ override fun removeView(view: View) {
257
+ // we set this property to reverse the order of drawing views
258
+ // when we want to push new fragment on top of the previous one and their animations collide.
259
+ // More information in:
260
+ // https://github.com/airbnb/native-navigation/blob/9cf50bf9b751b40778f473f3b19fcfe2c4d40599/lib/android/src/main/java/com/airbnb/android/react/navigation/ScreenCoordinatorLayout.java#L17
261
+ if (isDetachingCurrentScreen) {
262
+ isDetachingCurrentScreen = false
263
+ reverseLastTwoChildren = true
264
+ }
265
+ super.removeView(view)
266
+ }
267
+
268
+ private fun drawAndRelease() {
269
+ // We make a copy of the drawingOps and use it to dispatch draws in order to be sure
270
+ // that we do not modify the original list. There are cases when `op.draw` can call
271
+ // `drawChild` which would modify the list through which we are iterating. See more:
272
+ // https://github.com/software-mansion/react-native-screens/pull/1406
273
+ val drawingOpsCopy = drawingOps
274
+ drawingOps = ArrayList()
275
+ for (op in drawingOpsCopy) {
276
+ op.draw()
277
+ drawingOpPool.add(op)
278
+ }
279
+ }
280
+
281
+ override fun dispatchDraw(canvas: Canvas) {
282
+ super.dispatchDraw(canvas)
283
+
284
+ // check the view removal is completed (by comparing the previous children count)
285
+ if (drawingOps.size < previousChildrenCount) {
286
+ reverseLastTwoChildren = false
287
+ }
288
+ previousChildrenCount = drawingOps.size
289
+ if (reverseLastTwoChildren && drawingOps.size >= 2) {
290
+ Collections.swap(drawingOps, drawingOps.size - 1, drawingOps.size - 2)
291
+ }
292
+ drawAndRelease()
293
+ }
294
+
295
+ override fun drawChild(canvas: Canvas, child: View, drawingTime: Long): Boolean {
296
+ drawingOps.add(
297
+ obtainDrawingOp().apply {
298
+ this.canvas = canvas
299
+ this.child = child
300
+ this.drawingTime = drawingTime
301
+ }
302
+ )
303
+ return true
304
+ }
305
+
306
+ private fun performDraw(op: DrawingOp) {
307
+ // Canvas parameter can not be null here https://developer.android.com/reference/android/view/ViewGroup#drawChild(android.graphics.Canvas,%20android.view.View,%20long)
308
+ // So if we are passing null here, we would crash anyway
309
+ super.drawChild(op.canvas!!, op.child, op.drawingTime)
310
+ }
311
+
312
+ private fun obtainDrawingOp(): DrawingOp =
313
+ if (drawingOpPool.isEmpty()) DrawingOp() else drawingOpPool.removeLast()
314
+
315
+ private inner class DrawingOp {
316
+ var canvas: Canvas? = null
317
+ var child: View? = null
318
+ var drawingTime: Long = 0
319
+
320
+ fun draw() {
321
+ performDraw(this)
322
+ canvas = null
323
+ child = null
324
+ drawingTime = 0
325
+ }
326
+ }
327
+
328
+ companion object {
329
+ private fun isTransparent(fragmentWrapper: ScreenFragmentWrapper): Boolean =
330
+ fragmentWrapper.screen.stackPresentation === Screen.StackPresentation.TRANSPARENT_MODAL
331
+
332
+ private fun needsDrawReordering(fragmentWrapper: ScreenFragmentWrapper): Boolean =
333
+ fragmentWrapper.screen.stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
334
+ fragmentWrapper.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM
335
+ }
336
+ }