@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.
- package/LICENSE +7 -0
- package/README.md +223 -0
- package/RNScreens.podspec +53 -0
- package/SystemBundles/8f5a820b958535e533acb38dbc0c72c1837721b9db075f4a1740e42b9fee3910.bundle +33668 -0
- package/SystemBundles/8f5a820b958535e533acb38dbc0c72c1837721b9db075f4a1740e42b9fee3910.map +1 -0
- package/SystemModules/amzn__react-native-screens.modules.txt +101 -0
- package/SystemModules/amzn__react-native-screens.private.modules.txt +244 -0
- package/SystemModules/keplerscript-system-bundle-config.json +7 -0
- package/THIRD_PARTY_NOTICES.txt +707 -0
- package/android/build.gradle +133 -0
- package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +49 -0
- package/android/src/main/AndroidManifest.xml +5 -0
- package/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt +77 -0
- package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +7 -0
- package/android/src/main/java/com/swmansion/rnscreens/FragmentBackPressOverrider.kt +29 -0
- package/android/src/main/java/com/swmansion/rnscreens/FragmentHolder.kt +7 -0
- package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +21 -0
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +289 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +372 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +40 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenEventDispatcher.kt +21 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +331 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFragmentWrapper.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +336 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +282 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragmentWrapper.kt +15 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +398 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +204 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +38 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +41 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +75 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +186 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +296 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreensShadowNode.kt +19 -0
- package/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +133 -0
- package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +178 -0
- package/android/src/main/java/com/swmansion/rnscreens/SearchViewFormatter.kt +67 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderAttachedEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderBackButtonClickedEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderDetachedEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenAppearEvent.kt +18 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDisappearEvent.kt +18 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDismissedEvent.kt +20 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenTransitionProgressEvent.kt +32 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillAppearEvent.kt +18 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillDisappearEvent.kt +18 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarBlurEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarChangeTextEvent.kt +28 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarCloseEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarFocusEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarOpenEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarSearchButtonPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/StackFinishTransitioningEvent.kt +18 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/DeviceUtils.kt +12 -0
- package/android/src/main/jni/CMakeLists.txt +72 -0
- package/android/src/main/jni/rnscreens.cpp +16 -0
- package/android/src/main/jni/rnscreens.h +28 -0
- package/android/src/main/res/base/anim/rns_default_enter_in.xml +18 -0
- package/android/src/main/res/base/anim/rns_default_enter_out.xml +19 -0
- package/android/src/main/res/base/anim/rns_default_exit_in.xml +17 -0
- package/android/src/main/res/base/anim/rns_default_exit_out.xml +18 -0
- package/android/src/main/res/base/anim/rns_fade_from_bottom.xml +14 -0
- package/android/src/main/res/base/anim/rns_fade_in.xml +7 -0
- package/android/src/main/res/base/anim/rns_fade_out.xml +7 -0
- package/android/src/main/res/base/anim/rns_fade_to_bottom.xml +15 -0
- package/android/src/main/res/base/anim/rns_no_animation_20.xml +6 -0
- package/android/src/main/res/base/anim/rns_no_animation_250.xml +7 -0
- package/android/src/main/res/base/anim/rns_no_animation_350.xml +6 -0
- package/android/src/main/res/base/anim/rns_no_animation_medium.xml +7 -0
- package/android/src/main/res/base/anim/rns_slide_in_from_bottom.xml +7 -0
- package/android/src/main/res/base/anim/rns_slide_in_from_left.xml +5 -0
- package/android/src/main/res/base/anim/rns_slide_in_from_right.xml +5 -0
- package/android/src/main/res/base/anim/rns_slide_out_to_bottom.xml +7 -0
- package/android/src/main/res/base/anim/rns_slide_out_to_left.xml +5 -0
- package/android/src/main/res/base/anim/rns_slide_out_to_right.xml +5 -0
- package/android/src/main/res/base/anim/rns_standard_accelerate_interpolator.xml +6 -0
- package/android/src/main/res/v33/anim-v33/rns_default_enter_in.xml +38 -0
- package/android/src/main/res/v33/anim-v33/rns_default_enter_out.xml +38 -0
- package/android/src/main/res/v33/anim-v33/rns_default_exit_in.xml +38 -0
- package/android/src/main/res/v33/anim-v33/rns_default_exit_out.xml +38 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +111 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +44 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerDelegate.java +107 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderConfigManagerInterface.java +42 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderSubviewManagerDelegate.java +31 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackHeaderSubviewManagerInterface.java +17 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackManagerDelegate.java +25 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenStackManagerInterface.java +16 -0
- package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledViewGroup.kt +10 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h +41 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +9 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h +30 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.cpp +14 -0
- package/common/cpp/react/renderer/components/rnscreens/RNSScreenState.h +45 -0
- package/ios/RCTImageComponentView+RNSScreenStackHeaderConfig.h +11 -0
- package/ios/RCTImageComponentView+RNSScreenStackHeaderConfig.mm +14 -0
- package/ios/RNSConvert.h +36 -0
- package/ios/RNSConvert.mm +154 -0
- package/ios/RNSEnums.h +71 -0
- package/ios/RNSFullWindowOverlay.h +34 -0
- package/ios/RNSFullWindowOverlay.mm +241 -0
- package/ios/RNSScreen.h +144 -0
- package/ios/RNSScreen.mm +1599 -0
- package/ios/RNSScreenContainer.h +45 -0
- package/ios/RNSScreenContainer.mm +343 -0
- package/ios/RNSScreenNavigationContainer.h +16 -0
- package/ios/RNSScreenNavigationContainer.mm +66 -0
- package/ios/RNSScreenStack.h +37 -0
- package/ios/RNSScreenStack.mm +1111 -0
- package/ios/RNSScreenStackAnimator.h +8 -0
- package/ios/RNSScreenStackAnimator.mm +320 -0
- package/ios/RNSScreenStackHeaderConfig.h +74 -0
- package/ios/RNSScreenStackHeaderConfig.mm +967 -0
- package/ios/RNSScreenStackHeaderSubview.h +44 -0
- package/ios/RNSScreenStackHeaderSubview.mm +147 -0
- package/ios/RNSScreenWindowTraits.h +26 -0
- package/ios/RNSScreenWindowTraits.mm +266 -0
- package/ios/RNSSearchBar.h +43 -0
- package/ios/RNSSearchBar.mm +465 -0
- package/ios/RNScreens.xcodeproj/project.pbxproj +461 -0
- package/ios/UIViewController+RNScreens.h +9 -0
- package/ios/UIViewController+RNScreens.mm +78 -0
- package/ios/UIWindow+RNScreens.h +9 -0
- package/ios/UIWindow+RNScreens.mm +17 -0
- package/ios/events/RNSHeaderHeightChangeEvent.h +8 -0
- package/ios/events/RNSHeaderHeightChangeEvent.mm +44 -0
- package/ios/events/RNSScreenViewEvent.h +12 -0
- package/ios/events/RNSScreenViewEvent.mm +59 -0
- package/ios/utils/RNSUIBarButtonItem.h +5 -0
- package/ios/utils/RNSUIBarButtonItem.mm +22 -0
- package/kepler-compatibility.json +8 -0
- package/kepler-transformed-package-info.json +3 -0
- package/lib/commonjs/TransitionProgressContext.js +11 -0
- package/lib/commonjs/TransitionProgressContext.js.map +1 -0
- package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js +11 -0
- package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenContainerNativeComponent.js +33 -0
- package/lib/commonjs/fabric/ScreenContainerNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenNativeComponent.js +70 -0
- package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js +11 -0
- package/lib/commonjs/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js +31 -0
- package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js +12 -0
- package/lib/commonjs/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenStackNativeComponent.js +35 -0
- package/lib/commonjs/fabric/ScreenStackNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/SearchBarNativeComponent.js +19 -0
- package/lib/commonjs/fabric/SearchBarNativeComponent.js.map +1 -0
- package/lib/commonjs/index.js +147 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/index.native.js +407 -0
- package/lib/commonjs/index.native.js.map +1 -0
- package/lib/commonjs/native-stack/index.js +49 -0
- package/lib/commonjs/native-stack/index.js.map +1 -0
- package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js +75 -0
- package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js.map +1 -0
- package/lib/commonjs/native-stack/types.js +6 -0
- package/lib/commonjs/native-stack/types.js.map +1 -0
- package/lib/commonjs/native-stack/utils/AnimatedHeaderHeightContext.js +12 -0
- package/lib/commonjs/native-stack/utils/AnimatedHeaderHeightContext.js.map +1 -0
- package/lib/commonjs/native-stack/utils/HeaderHeightContext.js +12 -0
- package/lib/commonjs/native-stack/utils/HeaderHeightContext.js.map +1 -0
- package/lib/commonjs/native-stack/utils/SafeAreaProviderCompat.js +75 -0
- package/lib/commonjs/native-stack/utils/SafeAreaProviderCompat.js.map +1 -0
- package/lib/commonjs/native-stack/utils/getDefaultHeaderHeight.js +35 -0
- package/lib/commonjs/native-stack/utils/getDefaultHeaderHeight.js.map +1 -0
- package/lib/commonjs/native-stack/utils/useAnimatedHeaderHeight.js +19 -0
- package/lib/commonjs/native-stack/utils/useAnimatedHeaderHeight.js.map +1 -0
- package/lib/commonjs/native-stack/utils/useBackPressSubscription.js +54 -0
- package/lib/commonjs/native-stack/utils/useBackPressSubscription.js.map +1 -0
- package/lib/commonjs/native-stack/utils/useHeaderHeight.js +19 -0
- package/lib/commonjs/native-stack/utils/useHeaderHeight.js.map +1 -0
- package/lib/commonjs/native-stack/views/FontProcessor.js +21 -0
- package/lib/commonjs/native-stack/views/FontProcessor.js.map +1 -0
- package/lib/commonjs/native-stack/views/HeaderConfig.js +141 -0
- package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -0
- package/lib/commonjs/native-stack/views/NativeStackView.js +354 -0
- package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -0
- package/lib/commonjs/reanimated/ReanimatedHeaderHeightContext.js +12 -0
- package/lib/commonjs/reanimated/ReanimatedHeaderHeightContext.js.map +1 -0
- package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +101 -0
- package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -0
- package/lib/commonjs/reanimated/ReanimatedScreen.js +22 -0
- package/lib/commonjs/reanimated/ReanimatedScreen.js.map +1 -0
- package/lib/commonjs/reanimated/ReanimatedScreenProvider.js +47 -0
- package/lib/commonjs/reanimated/ReanimatedScreenProvider.js.map +1 -0
- package/lib/commonjs/reanimated/ReanimatedTransitionProgressContext.js +12 -0
- package/lib/commonjs/reanimated/ReanimatedTransitionProgressContext.js.map +1 -0
- package/lib/commonjs/reanimated/index.js +28 -0
- package/lib/commonjs/reanimated/index.js.map +1 -0
- package/lib/commonjs/reanimated/useReanimatedHeaderHeight.js +19 -0
- package/lib/commonjs/reanimated/useReanimatedHeaderHeight.js.map +1 -0
- package/lib/commonjs/reanimated/useReanimatedTransitionProgress.js +19 -0
- package/lib/commonjs/reanimated/useReanimatedTransitionProgress.js.map +1 -0
- package/lib/commonjs/types.js +6 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/useTransitionProgress.js +19 -0
- package/lib/commonjs/useTransitionProgress.js.map +1 -0
- package/lib/commonjs/utils.js +21 -0
- package/lib/commonjs/utils.js.map +1 -0
- package/lib/module/TransitionProgressContext.js +3 -0
- package/lib/module/TransitionProgressContext.js.map +1 -0
- package/lib/module/fabric/FullWindowOverlayNativeComponent.js +4 -0
- package/lib/module/fabric/FullWindowOverlayNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenContainerNativeComponent.js +25 -0
- package/lib/module/fabric/ScreenContainerNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenNativeComponent.js +63 -0
- package/lib/module/fabric/ScreenNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js +4 -0
- package/lib/module/fabric/ScreenNavigationContainerNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js +23 -0
- package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js +7 -0
- package/lib/module/fabric/ScreenStackHeaderSubviewNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenStackNativeComponent.js +28 -0
- package/lib/module/fabric/ScreenStackNativeComponent.js.map +1 -0
- package/lib/module/fabric/SearchBarNativeComponent.js +10 -0
- package/lib/module/fabric/SearchBarNativeComponent.js.map +1 -0
- package/lib/module/index.js +67 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/index.native.js +410 -0
- package/lib/module/index.native.js.map +1 -0
- package/lib/module/native-stack/index.js +22 -0
- package/lib/module/native-stack/index.js.map +1 -0
- package/lib/module/native-stack/navigators/createNativeStackNavigator.js +72 -0
- package/lib/module/native-stack/navigators/createNativeStackNavigator.js.map +1 -0
- package/lib/module/native-stack/types.js +2 -0
- package/lib/module/native-stack/types.js.map +1 -0
- package/lib/module/native-stack/utils/AnimatedHeaderHeightContext.js +4 -0
- package/lib/module/native-stack/utils/AnimatedHeaderHeightContext.js.map +1 -0
- package/lib/module/native-stack/utils/HeaderHeightContext.js +4 -0
- package/lib/module/native-stack/utils/HeaderHeightContext.js.map +1 -0
- package/lib/module/native-stack/utils/SafeAreaProviderCompat.js +68 -0
- package/lib/module/native-stack/utils/SafeAreaProviderCompat.js.map +1 -0
- package/lib/module/native-stack/utils/getDefaultHeaderHeight.js +29 -0
- package/lib/module/native-stack/utils/getDefaultHeaderHeight.js.map +1 -0
- package/lib/module/native-stack/utils/useAnimatedHeaderHeight.js +10 -0
- package/lib/module/native-stack/utils/useAnimatedHeaderHeight.js.map +1 -0
- package/lib/module/native-stack/utils/useBackPressSubscription.js +47 -0
- package/lib/module/native-stack/utils/useBackPressSubscription.js.map +1 -0
- package/lib/module/native-stack/utils/useHeaderHeight.js +10 -0
- package/lib/module/native-stack/utils/useHeaderHeight.js.map +1 -0
- package/lib/module/native-stack/views/FontProcessor.js +13 -0
- package/lib/module/native-stack/views/FontProcessor.js.map +1 -0
- package/lib/module/native-stack/views/HeaderConfig.js +132 -0
- package/lib/module/native-stack/views/HeaderConfig.js.map +1 -0
- package/lib/module/native-stack/views/NativeStackView.js +355 -0
- package/lib/module/native-stack/views/NativeStackView.js.map +1 -0
- package/lib/module/reanimated/ReanimatedHeaderHeightContext.js +5 -0
- package/lib/module/reanimated/ReanimatedHeaderHeightContext.js.map +1 -0
- package/lib/module/reanimated/ReanimatedNativeStackScreen.js +97 -0
- package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -0
- package/lib/module/reanimated/ReanimatedScreen.js +17 -0
- package/lib/module/reanimated/ReanimatedScreen.js.map +1 -0
- package/lib/module/reanimated/ReanimatedScreenProvider.js +40 -0
- package/lib/module/reanimated/ReanimatedScreenProvider.js.map +1 -0
- package/lib/module/reanimated/ReanimatedTransitionProgressContext.js +5 -0
- package/lib/module/reanimated/ReanimatedTransitionProgressContext.js.map +1 -0
- package/lib/module/reanimated/index.js +4 -0
- package/lib/module/reanimated/index.js.map +1 -0
- package/lib/module/reanimated/useReanimatedHeaderHeight.js +10 -0
- package/lib/module/reanimated/useReanimatedHeaderHeight.js.map +1 -0
- package/lib/module/reanimated/useReanimatedTransitionProgress.js +10 -0
- package/lib/module/reanimated/useReanimatedTransitionProgress.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/useTransitionProgress.js +10 -0
- package/lib/module/useTransitionProgress.js.map +1 -0
- package/lib/module/utils.js +14 -0
- package/lib/module/utils.js.map +1 -0
- package/lib/typescript/TransitionProgressContext.d.ts +9 -0
- package/lib/typescript/fabric/FullWindowOverlayNativeComponent.d.ts +7 -0
- package/lib/typescript/fabric/ScreenContainerNativeComponent.d.ts +5 -0
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts +66 -0
- package/lib/typescript/fabric/ScreenNavigationContainerNativeComponent.d.ts +7 -0
- package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +33 -0
- package/lib/typescript/fabric/ScreenStackHeaderSubviewNativeComponent.d.ts +10 -0
- package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts +8 -0
- package/lib/typescript/fabric/SearchBarNativeComponent.d.ts +49 -0
- package/lib/typescript/index.d.ts +33 -0
- package/lib/typescript/index.native.d.ts +2 -0
- package/lib/typescript/native-stack/index.d.ts +19 -0
- package/lib/typescript/native-stack/navigators/createNativeStackNavigator.d.ts +6 -0
- package/lib/typescript/native-stack/types.d.ts +438 -0
- package/lib/typescript/native-stack/utils/AnimatedHeaderHeightContext.d.ts +4 -0
- package/lib/typescript/native-stack/utils/HeaderHeightContext.d.ts +3 -0
- package/lib/typescript/native-stack/utils/SafeAreaProviderCompat.d.ts +11 -0
- package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts +7 -0
- package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts +1 -0
- package/lib/typescript/native-stack/utils/useBackPressSubscription.d.ts +16 -0
- package/lib/typescript/native-stack/utils/useHeaderHeight.d.ts +1 -0
- package/lib/typescript/native-stack/views/FontProcessor.d.ts +1 -0
- package/lib/typescript/native-stack/views/HeaderConfig.d.ts +8 -0
- package/lib/typescript/native-stack/views/NativeStackView.d.ts +10 -0
- package/lib/typescript/reanimated/ReanimatedHeaderHeightContext.d.ts +4 -0
- package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +5 -0
- package/lib/typescript/reanimated/ReanimatedScreen.d.ts +5 -0
- package/lib/typescript/reanimated/ReanimatedScreenProvider.d.ts +2 -0
- package/lib/typescript/reanimated/ReanimatedTransitionProgressContext.d.ts +9 -0
- package/lib/typescript/reanimated/index.d.ts +3 -0
- package/lib/typescript/reanimated/useReanimatedHeaderHeight.d.ts +3 -0
- package/lib/typescript/reanimated/useReanimatedTransitionProgress.d.ts +11 -0
- package/lib/typescript/types.d.ts +612 -0
- package/lib/typescript/useTransitionProgress.d.ts +5 -0
- package/lib/typescript/utils.d.ts +3 -0
- package/native-stack/README.md +814 -0
- package/native-stack/package.json +6 -0
- package/package.json +1 -0
- package/react-native.config.js +42 -0
- package/reanimated/package.json +6 -0
- package/src/TransitionProgressContext.tsx +12 -0
- package/src/fabric/FullWindowOverlayNativeComponent.ts +7 -0
- package/src/fabric/ScreenContainerNativeComponent.ts +28 -0
- package/src/fabric/ScreenNativeComponent.ts +158 -0
- package/src/fabric/ScreenNavigationContainerNativeComponent.ts +10 -0
- package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +61 -0
- package/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +22 -0
- package/src/fabric/ScreenStackNativeComponent.ts +33 -0
- package/src/fabric/SearchBarNativeComponent.ts +79 -0
- package/src/index.native.tsx +599 -0
- package/src/index.tsx +119 -0
- package/src/native-stack/index.tsx +27 -0
- package/src/native-stack/navigators/createNativeStackNavigator.tsx +107 -0
- package/src/native-stack/types.tsx +486 -0
- package/src/native-stack/utils/AnimatedHeaderHeightContext.tsx +8 -0
- package/src/native-stack/utils/HeaderHeightContext.tsx +5 -0
- package/src/native-stack/utils/SafeAreaProviderCompat.tsx +78 -0
- package/src/native-stack/utils/getDefaultHeaderHeight.tsx +41 -0
- package/src/native-stack/utils/useAnimatedHeaderHeight.tsx +15 -0
- package/src/native-stack/utils/useBackPressSubscription.tsx +66 -0
- package/src/native-stack/utils/useHeaderHeight.tsx +15 -0
- package/src/native-stack/views/FontProcessor.tsx +14 -0
- package/src/native-stack/views/HeaderConfig.tsx +187 -0
- package/src/native-stack/views/NativeStackView.tsx +466 -0
- package/src/reanimated/ReanimatedHeaderHeightContext.tsx +7 -0
- package/src/reanimated/ReanimatedNativeStackScreen.tsx +130 -0
- package/src/reanimated/ReanimatedScreen.tsx +25 -0
- package/src/reanimated/ReanimatedScreenProvider.tsx +42 -0
- package/src/reanimated/ReanimatedTransitionProgressContext.tsx +13 -0
- package/src/reanimated/index.tsx +3 -0
- package/src/reanimated/useReanimatedHeaderHeight.tsx +14 -0
- package/src/reanimated/useReanimatedTransitionProgress.tsx +14 -0
- package/src/types.tsx +699 -0
- package/src/useTransitionProgress.tsx +15 -0
- package/src/utils.ts +18 -0
- package/windows/README.md +25 -0
- package/windows/RNScreens/PropertySheet.props +16 -0
- package/windows/RNScreens/RNScreens.cpp +66 -0
- package/windows/RNScreens/RNScreens.def +3 -0
- package/windows/RNScreens/RNScreens.h +41 -0
- package/windows/RNScreens/RNScreens.idl +8 -0
- package/windows/RNScreens/RNScreens.vcxproj +187 -0
- package/windows/RNScreens/RNScreens.vcxproj.filters +52 -0
- package/windows/RNScreens/ReactPackageProvider.cpp +30 -0
- package/windows/RNScreens/ReactPackageProvider.h +17 -0
- package/windows/RNScreens/ReactPackageProvider.idl +9 -0
- package/windows/RNScreens/Screen.cpp +122 -0
- package/windows/RNScreens/Screen.h +64 -0
- package/windows/RNScreens/ScreenContainer.cpp +49 -0
- package/windows/RNScreens/ScreenContainer.h +23 -0
- package/windows/RNScreens/ScreenContainerViewManager.cpp +133 -0
- package/windows/RNScreens/ScreenContainerViewManager.h +78 -0
- package/windows/RNScreens/ScreenStack.cpp +65 -0
- package/windows/RNScreens/ScreenStack.h +23 -0
- package/windows/RNScreens/ScreenStackHeaderConfig.cpp +19 -0
- package/windows/RNScreens/ScreenStackHeaderConfig.h +14 -0
- package/windows/RNScreens/ScreenStackHeaderConfigViewManager.cpp +89 -0
- package/windows/RNScreens/ScreenStackHeaderConfigViewManager.h +62 -0
- package/windows/RNScreens/ScreenStackViewManager.cpp +132 -0
- package/windows/RNScreens/ScreenStackViewManager.h +78 -0
- package/windows/RNScreens/ScreenViewManager.cpp +154 -0
- package/windows/RNScreens/ScreenViewManager.h +78 -0
- package/windows/RNScreens/packages.config +4 -0
- package/windows/RNScreens/pch.cpp +1 -0
- package/windows/RNScreens/pch.h +9 -0
- package/windows/RNScreens62.sln +254 -0
- package/windows/RNScreens63.sln +225 -0
- package/windows/RNScreens65.sln +144 -0
|
@@ -0,0 +1,967 @@
|
|
|
1
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
+
#import <React/RCTConversions.h>
|
|
3
|
+
#import <React/RCTFabricComponentsPlugins.h>
|
|
4
|
+
#import <React/RCTImageComponentView.h>
|
|
5
|
+
#import <React/UIView+React.h>
|
|
6
|
+
#import <react/renderer/components/image/ImageProps.h>
|
|
7
|
+
#import <react/renderer/components/rnscreens/ComponentDescriptors.h>
|
|
8
|
+
#import <react/renderer/components/rnscreens/EventEmitters.h>
|
|
9
|
+
#import <react/renderer/components/rnscreens/Props.h>
|
|
10
|
+
#import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
|
|
11
|
+
#import "RCTImageComponentView+RNSScreenStackHeaderConfig.h"
|
|
12
|
+
#else
|
|
13
|
+
#import <React/RCTImageView.h>
|
|
14
|
+
#import <React/RCTShadowView.h>
|
|
15
|
+
#import <React/RCTUIManager.h>
|
|
16
|
+
#import <React/RCTUIManagerUtils.h>
|
|
17
|
+
#endif
|
|
18
|
+
#import <React/RCTBridge.h>
|
|
19
|
+
#import <React/RCTFont.h>
|
|
20
|
+
#import <React/RCTImageLoader.h>
|
|
21
|
+
#import <React/RCTImageSource.h>
|
|
22
|
+
#import "RNSScreen.h"
|
|
23
|
+
#import "RNSScreenStackHeaderConfig.h"
|
|
24
|
+
#import "RNSSearchBar.h"
|
|
25
|
+
#import "RNSUIBarButtonItem.h"
|
|
26
|
+
|
|
27
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
28
|
+
namespace react = facebook::react;
|
|
29
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
30
|
+
|
|
31
|
+
#ifndef RCT_NEW_ARCH_ENABLED
|
|
32
|
+
// Some RN private method hacking below. Couldn't figure out better way to access image data
|
|
33
|
+
// of a given RCTImageView. See more comments in the code section processing SubviewTypeBackButton
|
|
34
|
+
@interface RCTImageView (Private)
|
|
35
|
+
- (UIImage *)image;
|
|
36
|
+
@end
|
|
37
|
+
#endif // !RCT_NEW_ARCH_ENABLED
|
|
38
|
+
|
|
39
|
+
@interface RCTImageLoader (Private)
|
|
40
|
+
- (id<RCTImageCache>)imageCache;
|
|
41
|
+
@end
|
|
42
|
+
|
|
43
|
+
@implementation NSString (RNSStringUtil)
|
|
44
|
+
|
|
45
|
+
+ (BOOL)RNSisBlank:(NSString *)string
|
|
46
|
+
{
|
|
47
|
+
if (string == nil) {
|
|
48
|
+
return YES;
|
|
49
|
+
}
|
|
50
|
+
return [[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@end
|
|
54
|
+
|
|
55
|
+
@implementation RNSScreenStackHeaderConfig {
|
|
56
|
+
NSMutableArray<RNSScreenStackHeaderSubview *> *_reactSubviews;
|
|
57
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
58
|
+
BOOL _initialPropsSet;
|
|
59
|
+
#else
|
|
60
|
+
#endif
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
64
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
65
|
+
{
|
|
66
|
+
if (self = [super initWithFrame:frame]) {
|
|
67
|
+
static const auto defaultProps = std::make_shared<const react::RNSScreenStackHeaderConfigProps>();
|
|
68
|
+
_props = defaultProps;
|
|
69
|
+
_show = YES;
|
|
70
|
+
_translucent = NO;
|
|
71
|
+
[self initProps];
|
|
72
|
+
}
|
|
73
|
+
return self;
|
|
74
|
+
}
|
|
75
|
+
#else
|
|
76
|
+
- (instancetype)init
|
|
77
|
+
{
|
|
78
|
+
if (self = [super init]) {
|
|
79
|
+
_translucent = YES;
|
|
80
|
+
[self initProps];
|
|
81
|
+
}
|
|
82
|
+
return self;
|
|
83
|
+
}
|
|
84
|
+
#endif
|
|
85
|
+
|
|
86
|
+
- (void)initProps
|
|
87
|
+
{
|
|
88
|
+
self.hidden = YES;
|
|
89
|
+
_reactSubviews = [NSMutableArray new];
|
|
90
|
+
_backTitleVisible = YES;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
- (UIView *)reactSuperview
|
|
94
|
+
{
|
|
95
|
+
return _screenView;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
- (NSArray<UIView *> *)reactSubviews
|
|
99
|
+
{
|
|
100
|
+
return _reactSubviews;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
- (void)removeFromSuperview
|
|
104
|
+
{
|
|
105
|
+
[super removeFromSuperview];
|
|
106
|
+
_screenView = nil;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// this method is never invoked by the system since this view
|
|
110
|
+
// is not added to native view hierarchy so we can apply our logic
|
|
111
|
+
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
|
112
|
+
{
|
|
113
|
+
for (RNSScreenStackHeaderSubview *subview in _reactSubviews) {
|
|
114
|
+
if (subview.type == RNSScreenStackHeaderSubviewTypeLeft || subview.type == RNSScreenStackHeaderSubviewTypeRight) {
|
|
115
|
+
// we wrap the headerLeft/Right component in a UIBarButtonItem
|
|
116
|
+
// so we need to use the only subview of it to retrieve the correct view
|
|
117
|
+
UIView *headerComponent = subview.subviews.firstObject;
|
|
118
|
+
// we convert the point to RNSScreenStackView since it always contains the header inside it
|
|
119
|
+
CGPoint convertedPoint = [_screenView.reactSuperview convertPoint:point toView:headerComponent];
|
|
120
|
+
|
|
121
|
+
UIView *hitTestResult = [headerComponent hitTest:convertedPoint withEvent:event];
|
|
122
|
+
if (hitTestResult != nil) {
|
|
123
|
+
return hitTestResult;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return nil;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
- (void)updateViewControllerIfNeeded
|
|
131
|
+
{
|
|
132
|
+
UIViewController *vc = _screenView.controller;
|
|
133
|
+
UINavigationController *nav = (UINavigationController *)vc.parentViewController;
|
|
134
|
+
UIViewController *nextVC = nav.visibleViewController;
|
|
135
|
+
if (nav.transitionCoordinator != nil) {
|
|
136
|
+
// if navigator is performing transition instead of allowing to update of `visibleConttroller`
|
|
137
|
+
// we look at `topController`. This is because during transitiong the `visibleController` won't
|
|
138
|
+
// point to the controller that is going to be revealed after transition. This check fixes the
|
|
139
|
+
// problem when config gets updated while the transition is ongoing.
|
|
140
|
+
nextVC = nav.topViewController;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// we want updates sent to the VC below modal too since it is also visible
|
|
144
|
+
BOOL isPresentingVC = nextVC != nil && vc.presentedViewController == nextVC;
|
|
145
|
+
|
|
146
|
+
BOOL isInFullScreenModal = nav == nil && _screenView.stackPresentation == RNSScreenStackPresentationFullScreenModal;
|
|
147
|
+
// if nav is nil, it means we can be in a fullScreen modal, so there is no nextVC, but we still want to update
|
|
148
|
+
if (vc != nil && (nextVC == vc || isInFullScreenModal || isPresentingVC)) {
|
|
149
|
+
[RNSScreenStackHeaderConfig updateViewController:self.screenView.controller withConfig:self animated:YES];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
- (void)layoutNavigationControllerView
|
|
154
|
+
{
|
|
155
|
+
// We need to layout navigation controller view after translucent prop changes, because otherwise
|
|
156
|
+
// frame of RNSScreen will not be changed and screen content will remain the same size.
|
|
157
|
+
// For more details look at https://github.com/software-mansion/react-native-screens/issues/1158
|
|
158
|
+
UIViewController *vc = _screenView.controller;
|
|
159
|
+
UINavigationController *navctr = vc.navigationController;
|
|
160
|
+
[navctr.view setNeedsLayout];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
+ (void)setAnimatedConfig:(UIViewController *)vc withConfig:(RNSScreenStackHeaderConfig *)config
|
|
164
|
+
{
|
|
165
|
+
UINavigationBar *navbar = ((UINavigationController *)vc.parentViewController).navigationBar;
|
|
166
|
+
// It is workaround for loading custom back icon when transitioning from a screen without header to the screen which
|
|
167
|
+
// has one. This action fails when navigating to the screen with header for the second time and loads default back
|
|
168
|
+
// button. It looks like changing the tint color of navbar triggers an update of the items belonging to it and it
|
|
169
|
+
// seems to load the custom back image so we change the tint color's alpha by a very small amount and then set it to
|
|
170
|
+
// the one it should have.
|
|
171
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_14_0) && \
|
|
172
|
+
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
|
|
173
|
+
// it brakes the behavior of `headerRight` in iOS 14, where the bug desribed above seems to be fixed, so we do nothing
|
|
174
|
+
// in iOS 14
|
|
175
|
+
if (@available(iOS 14.0, *)) {
|
|
176
|
+
} else
|
|
177
|
+
#endif
|
|
178
|
+
{
|
|
179
|
+
[navbar setTintColor:[config.color colorWithAlphaComponent:CGColorGetAlpha(config.color.CGColor) - 0.01]];
|
|
180
|
+
}
|
|
181
|
+
[navbar setTintColor:config.color];
|
|
182
|
+
|
|
183
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
|
184
|
+
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
|
185
|
+
if (@available(iOS 13.0, *)) {
|
|
186
|
+
// font customized on the navigation item level, so nothing to do here
|
|
187
|
+
} else
|
|
188
|
+
#endif
|
|
189
|
+
{
|
|
190
|
+
BOOL hideShadow = config.hideShadow;
|
|
191
|
+
|
|
192
|
+
if (config.backgroundColor && CGColorGetAlpha(config.backgroundColor.CGColor) == 0.) {
|
|
193
|
+
[navbar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
|
|
194
|
+
[navbar setBarTintColor:[UIColor clearColor]];
|
|
195
|
+
hideShadow = YES;
|
|
196
|
+
} else {
|
|
197
|
+
[navbar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
|
|
198
|
+
[navbar setBarTintColor:config.backgroundColor];
|
|
199
|
+
}
|
|
200
|
+
[navbar setTranslucent:config.translucent];
|
|
201
|
+
[navbar setValue:@(hideShadow ? YES : NO) forKey:@"hidesShadow"];
|
|
202
|
+
|
|
203
|
+
if (config.titleFontFamily || config.titleFontSize || config.titleFontWeight || config.titleColor) {
|
|
204
|
+
NSMutableDictionary *attrs = [NSMutableDictionary new];
|
|
205
|
+
|
|
206
|
+
if (config.titleColor) {
|
|
207
|
+
attrs[NSForegroundColorAttributeName] = config.titleColor;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
NSString *family = config.titleFontFamily ?: nil;
|
|
211
|
+
NSNumber *size = config.titleFontSize ?: @17;
|
|
212
|
+
NSString *weight = config.titleFontWeight ?: nil;
|
|
213
|
+
if (family || weight) {
|
|
214
|
+
attrs[NSFontAttributeName] = [RCTFont updateFont:nil
|
|
215
|
+
withFamily:family
|
|
216
|
+
size:size
|
|
217
|
+
weight:weight
|
|
218
|
+
style:nil
|
|
219
|
+
variant:nil
|
|
220
|
+
scaleMultiplier:1.0];
|
|
221
|
+
} else {
|
|
222
|
+
attrs[NSFontAttributeName] = [UIFont boldSystemFontOfSize:[size floatValue]];
|
|
223
|
+
}
|
|
224
|
+
[navbar setTitleTextAttributes:attrs];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
#if !TARGET_OS_TV
|
|
228
|
+
if (@available(iOS 11.0, *)) {
|
|
229
|
+
if (config.largeTitle &&
|
|
230
|
+
(config.largeTitleFontFamily || config.largeTitleFontSize || config.largeTitleFontWeight ||
|
|
231
|
+
config.largeTitleColor || config.titleColor)) {
|
|
232
|
+
NSMutableDictionary *largeAttrs = [NSMutableDictionary new];
|
|
233
|
+
if (config.largeTitleColor || config.titleColor) {
|
|
234
|
+
largeAttrs[NSForegroundColorAttributeName] =
|
|
235
|
+
config.largeTitleColor ? config.largeTitleColor : config.titleColor;
|
|
236
|
+
}
|
|
237
|
+
NSString *largeFamily = config.largeTitleFontFamily ?: nil;
|
|
238
|
+
NSNumber *largeSize = config.largeTitleFontSize ?: @34;
|
|
239
|
+
NSString *largeWeight = config.largeTitleFontWeight ?: nil;
|
|
240
|
+
if (largeFamily || largeWeight) {
|
|
241
|
+
largeAttrs[NSFontAttributeName] = [RCTFont updateFont:nil
|
|
242
|
+
withFamily:largeFamily
|
|
243
|
+
size:largeSize
|
|
244
|
+
weight:largeWeight
|
|
245
|
+
style:nil
|
|
246
|
+
variant:nil
|
|
247
|
+
scaleMultiplier:1.0];
|
|
248
|
+
} else {
|
|
249
|
+
largeAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:[largeSize floatValue] weight:UIFontWeightBold];
|
|
250
|
+
}
|
|
251
|
+
[navbar setLargeTitleTextAttributes:largeAttrs];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
#endif
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
+ (void)setTitleAttibutes:(NSDictionary *)attrs forButton:(UIBarButtonItem *)button
|
|
259
|
+
{
|
|
260
|
+
[button setTitleTextAttributes:attrs forState:UIControlStateNormal];
|
|
261
|
+
[button setTitleTextAttributes:attrs forState:UIControlStateHighlighted];
|
|
262
|
+
[button setTitleTextAttributes:attrs forState:UIControlStateDisabled];
|
|
263
|
+
[button setTitleTextAttributes:attrs forState:UIControlStateSelected];
|
|
264
|
+
[button setTitleTextAttributes:attrs forState:UIControlStateFocused];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
+ (UIImage *)loadBackButtonImageInViewController:(UIViewController *)vc withConfig:(RNSScreenStackHeaderConfig *)config
|
|
268
|
+
{
|
|
269
|
+
BOOL hasBackButtonImage = NO;
|
|
270
|
+
for (RNSScreenStackHeaderSubview *subview in config.reactSubviews) {
|
|
271
|
+
if (subview.type == RNSScreenStackHeaderSubviewTypeBackButton && subview.subviews.count > 0) {
|
|
272
|
+
hasBackButtonImage = YES;
|
|
273
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
274
|
+
RCTImageComponentView *imageView = subview.subviews[0];
|
|
275
|
+
#else
|
|
276
|
+
RCTImageView *imageView = subview.subviews[0];
|
|
277
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
278
|
+
if (imageView.image == nil) {
|
|
279
|
+
// This is yet another workaround for loading custom back icon. It turns out that under
|
|
280
|
+
// certain circumstances image attribute can be null despite the app running in production
|
|
281
|
+
// mode (when images are loaded from the filesystem). This can happen because image attribute
|
|
282
|
+
// is reset when image view is detached from window, and also in some cases initialization
|
|
283
|
+
// does not populate the frame of the image view before the loading start. The latter result
|
|
284
|
+
// in the image attribute not being updated. We manually set frame to the size of an image
|
|
285
|
+
// in order to trigger proper reload that'd update the image attribute.
|
|
286
|
+
RCTImageSource *imageSource = [RNSScreenStackHeaderConfig imageSourceFromImageView:imageView];
|
|
287
|
+
[imageView reactSetFrame:CGRectMake(
|
|
288
|
+
imageView.frame.origin.x,
|
|
289
|
+
imageView.frame.origin.y,
|
|
290
|
+
imageSource.size.width,
|
|
291
|
+
imageSource.size.height)];
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
UIImage *image = imageView.image;
|
|
295
|
+
|
|
296
|
+
// IMPORTANT!!!
|
|
297
|
+
// image can be nil in DEV MODE ONLY
|
|
298
|
+
//
|
|
299
|
+
// It is so, because in dev mode images are loaded over HTTP from the packager. In that case
|
|
300
|
+
// we first check if image is already loaded in cache and if it is, we take it from cache and
|
|
301
|
+
// display immediately. Otherwise we wait for the transition to finish and retry updating
|
|
302
|
+
// header config.
|
|
303
|
+
// Unfortunately due to some problems in UIKit we cannot update the image while the screen
|
|
304
|
+
// transition is ongoing. This results in the settings being reset after the transition is done
|
|
305
|
+
// to the state from before the transition.
|
|
306
|
+
if (image == nil) {
|
|
307
|
+
// in DEV MODE we try to load from cache (we use private API for that as it is not exposed
|
|
308
|
+
// publically in headers).
|
|
309
|
+
RCTImageSource *imageSource = [RNSScreenStackHeaderConfig imageSourceFromImageView:imageView];
|
|
310
|
+
RCTImageLoader *imageLoader = [subview.bridge moduleForClass:[RCTImageLoader class]];
|
|
311
|
+
|
|
312
|
+
image = [imageLoader.imageCache
|
|
313
|
+
imageForUrl:imageSource.request.URL.absoluteString
|
|
314
|
+
size:imageSource.size
|
|
315
|
+
scale:imageSource.scale
|
|
316
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
317
|
+
resizeMode:resizeModeFromCppEquiv(
|
|
318
|
+
std::static_pointer_cast<const react::ImageProps>(imageView.props)->resizeMode)];
|
|
319
|
+
#else
|
|
320
|
+
resizeMode:imageView.resizeMode];
|
|
321
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
322
|
+
}
|
|
323
|
+
if (image == nil) {
|
|
324
|
+
// This will be triggered if the image is not in the cache yet. What we do is we wait until
|
|
325
|
+
// the end of transition and run header config updates again. We could potentially wait for
|
|
326
|
+
// image on load to trigger, but that would require even more private method hacking.
|
|
327
|
+
if (vc.transitionCoordinator) {
|
|
328
|
+
[vc.transitionCoordinator
|
|
329
|
+
animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
|
|
330
|
+
// nothing, we just want completion
|
|
331
|
+
}
|
|
332
|
+
completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
|
|
333
|
+
// in order for new back button image to be loaded we need to trigger another change
|
|
334
|
+
// in back button props that'd make UIKit redraw the button. Otherwise the changes are
|
|
335
|
+
// not reflected. Here we change back button visibility which is then immediately restored
|
|
336
|
+
#if !TARGET_OS_TV
|
|
337
|
+
vc.navigationItem.hidesBackButton = YES;
|
|
338
|
+
#endif
|
|
339
|
+
[config updateViewControllerIfNeeded];
|
|
340
|
+
}];
|
|
341
|
+
}
|
|
342
|
+
return [UIImage new];
|
|
343
|
+
} else {
|
|
344
|
+
return image;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return nil;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
+ (void)willShowViewController:(UIViewController *)vc
|
|
352
|
+
animated:(BOOL)animated
|
|
353
|
+
withConfig:(RNSScreenStackHeaderConfig *)config
|
|
354
|
+
{
|
|
355
|
+
[self updateViewController:vc withConfig:config animated:animated];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
|
359
|
+
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
|
360
|
+
+ (UINavigationBarAppearance *)buildAppearance:(UIViewController *)vc
|
|
361
|
+
withConfig:(RNSScreenStackHeaderConfig *)config API_AVAILABLE(ios(13.0))
|
|
362
|
+
{
|
|
363
|
+
UINavigationBarAppearance *appearance = [UINavigationBarAppearance new];
|
|
364
|
+
|
|
365
|
+
if (config.backgroundColor && CGColorGetAlpha(config.backgroundColor.CGColor) == 0.) {
|
|
366
|
+
// transparent background color
|
|
367
|
+
[appearance configureWithTransparentBackground];
|
|
368
|
+
} else {
|
|
369
|
+
[appearance configureWithOpaqueBackground];
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// set background color if specified
|
|
373
|
+
if (config.backgroundColor) {
|
|
374
|
+
appearance.backgroundColor = config.backgroundColor;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// TODO: implement blurEffect on Fabric
|
|
378
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
379
|
+
#else
|
|
380
|
+
if (config.blurEffect) {
|
|
381
|
+
appearance.backgroundEffect = [UIBlurEffect effectWithStyle:config.blurEffect];
|
|
382
|
+
}
|
|
383
|
+
#endif
|
|
384
|
+
|
|
385
|
+
if (config.hideShadow) {
|
|
386
|
+
appearance.shadowColor = nil;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (config.titleFontFamily || config.titleFontSize || config.titleFontWeight || config.titleColor) {
|
|
390
|
+
NSMutableDictionary *attrs = [NSMutableDictionary new];
|
|
391
|
+
|
|
392
|
+
if (config.titleColor) {
|
|
393
|
+
attrs[NSForegroundColorAttributeName] = config.titleColor;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
NSString *family = config.titleFontFamily ?: nil;
|
|
397
|
+
NSNumber *size = config.titleFontSize ?: @17;
|
|
398
|
+
NSString *weight = config.titleFontWeight ?: nil;
|
|
399
|
+
if (family || weight) {
|
|
400
|
+
attrs[NSFontAttributeName] = [RCTFont updateFont:nil
|
|
401
|
+
withFamily:config.titleFontFamily
|
|
402
|
+
size:size
|
|
403
|
+
weight:weight
|
|
404
|
+
style:nil
|
|
405
|
+
variant:nil
|
|
406
|
+
scaleMultiplier:1.0];
|
|
407
|
+
} else {
|
|
408
|
+
attrs[NSFontAttributeName] = [UIFont boldSystemFontOfSize:[size floatValue]];
|
|
409
|
+
}
|
|
410
|
+
appearance.titleTextAttributes = attrs;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (config.largeTitleFontFamily || config.largeTitleFontSize || config.largeTitleFontWeight ||
|
|
414
|
+
config.largeTitleColor || config.titleColor) {
|
|
415
|
+
NSMutableDictionary *largeAttrs = [NSMutableDictionary new];
|
|
416
|
+
|
|
417
|
+
if (config.largeTitleColor || config.titleColor) {
|
|
418
|
+
largeAttrs[NSForegroundColorAttributeName] = config.largeTitleColor ? config.largeTitleColor : config.titleColor;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
NSString *largeFamily = config.largeTitleFontFamily ?: nil;
|
|
422
|
+
NSNumber *largeSize = config.largeTitleFontSize ?: @34;
|
|
423
|
+
NSString *largeWeight = config.largeTitleFontWeight ?: nil;
|
|
424
|
+
if (largeFamily || largeWeight) {
|
|
425
|
+
largeAttrs[NSFontAttributeName] = [RCTFont updateFont:nil
|
|
426
|
+
withFamily:largeFamily
|
|
427
|
+
size:largeSize
|
|
428
|
+
weight:largeWeight
|
|
429
|
+
style:nil
|
|
430
|
+
variant:nil
|
|
431
|
+
scaleMultiplier:1.0];
|
|
432
|
+
} else {
|
|
433
|
+
largeAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:[largeSize floatValue] weight:UIFontWeightBold];
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
appearance.largeTitleTextAttributes = largeAttrs;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
UIImage *backButtonImage = [self loadBackButtonImageInViewController:vc withConfig:config];
|
|
440
|
+
if (backButtonImage) {
|
|
441
|
+
[appearance setBackIndicatorImage:backButtonImage transitionMaskImage:backButtonImage];
|
|
442
|
+
} else if (appearance.backIndicatorImage) {
|
|
443
|
+
[appearance setBackIndicatorImage:nil transitionMaskImage:nil];
|
|
444
|
+
}
|
|
445
|
+
return appearance;
|
|
446
|
+
}
|
|
447
|
+
#endif // Check for >= iOS 13.0
|
|
448
|
+
|
|
449
|
+
+ (void)updateViewController:(UIViewController *)vc
|
|
450
|
+
withConfig:(RNSScreenStackHeaderConfig *)config
|
|
451
|
+
animated:(BOOL)animated
|
|
452
|
+
{
|
|
453
|
+
UINavigationItem *navitem = vc.navigationItem;
|
|
454
|
+
UINavigationController *navctr = (UINavigationController *)vc.parentViewController;
|
|
455
|
+
|
|
456
|
+
NSUInteger currentIndex = [navctr.viewControllers indexOfObject:vc];
|
|
457
|
+
UINavigationItem *prevItem =
|
|
458
|
+
currentIndex > 0 ? [navctr.viewControllers objectAtIndex:currentIndex - 1].navigationItem : nil;
|
|
459
|
+
|
|
460
|
+
BOOL wasHidden = navctr.navigationBarHidden;
|
|
461
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
462
|
+
BOOL shouldHide = config == nil || !config.show;
|
|
463
|
+
#else
|
|
464
|
+
BOOL shouldHide = config == nil || config.hide;
|
|
465
|
+
#endif
|
|
466
|
+
|
|
467
|
+
if (!shouldHide && !config.translucent) {
|
|
468
|
+
// when nav bar is not translucent we chage edgesForExtendedLayout to avoid system laying out
|
|
469
|
+
// the screen underneath navigation controllers
|
|
470
|
+
vc.edgesForExtendedLayout = UIRectEdgeNone;
|
|
471
|
+
} else {
|
|
472
|
+
// system default is UIRectEdgeAll
|
|
473
|
+
vc.edgesForExtendedLayout = UIRectEdgeAll;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
[navctr setNavigationBarHidden:shouldHide animated:animated];
|
|
477
|
+
|
|
478
|
+
if ((config.direction == UISemanticContentAttributeForceLeftToRight ||
|
|
479
|
+
config.direction == UISemanticContentAttributeForceRightToLeft) &&
|
|
480
|
+
// iOS 12 cancels swipe gesture when direction is changed. See #1091
|
|
481
|
+
navctr.view.semanticContentAttribute != config.direction) {
|
|
482
|
+
navctr.view.semanticContentAttribute = config.direction;
|
|
483
|
+
navctr.navigationBar.semanticContentAttribute = config.direction;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (shouldHide) {
|
|
487
|
+
navitem.title = config.title;
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
#if !TARGET_OS_TV
|
|
492
|
+
const auto isBackTitleBlank = [NSString RNSisBlank:config.backTitle] == YES;
|
|
493
|
+
NSString *resolvedBackTitle = isBackTitleBlank ? prevItem.title : config.backTitle;
|
|
494
|
+
RNSUIBarButtonItem *backBarButtonItem = [[RNSUIBarButtonItem alloc] initWithTitle:resolvedBackTitle
|
|
495
|
+
style:UIBarButtonItemStylePlain
|
|
496
|
+
target:nil
|
|
497
|
+
action:nil];
|
|
498
|
+
[backBarButtonItem setMenuHidden:config.disableBackButtonMenu];
|
|
499
|
+
|
|
500
|
+
if (config.isBackTitleVisible) {
|
|
501
|
+
if (config.backTitleFontFamily || config.backTitleFontSize) {
|
|
502
|
+
NSMutableDictionary *attrs = [NSMutableDictionary new];
|
|
503
|
+
NSNumber *size = config.backTitleFontSize ?: @17;
|
|
504
|
+
if (config.backTitleFontFamily) {
|
|
505
|
+
attrs[NSFontAttributeName] = [RCTFont updateFont:nil
|
|
506
|
+
withFamily:config.backTitleFontFamily
|
|
507
|
+
size:size
|
|
508
|
+
weight:nil
|
|
509
|
+
style:nil
|
|
510
|
+
variant:nil
|
|
511
|
+
scaleMultiplier:1.0];
|
|
512
|
+
} else {
|
|
513
|
+
attrs[NSFontAttributeName] = [UIFont boldSystemFontOfSize:[size floatValue]];
|
|
514
|
+
}
|
|
515
|
+
[self setTitleAttibutes:attrs forButton:backBarButtonItem];
|
|
516
|
+
}
|
|
517
|
+
} else {
|
|
518
|
+
// back button title should be not visible next to back button,
|
|
519
|
+
// but it should still appear in back menu (if one is enabled)
|
|
520
|
+
|
|
521
|
+
// When backBarButtonItem's title is null, back menu will use value
|
|
522
|
+
// of backButtonTitle
|
|
523
|
+
[backBarButtonItem setTitle:nil];
|
|
524
|
+
prevItem.backButtonTitle = resolvedBackTitle;
|
|
525
|
+
}
|
|
526
|
+
prevItem.backBarButtonItem = backBarButtonItem;
|
|
527
|
+
|
|
528
|
+
if (@available(iOS 11.0, *)) {
|
|
529
|
+
if (config.largeTitle) {
|
|
530
|
+
navctr.navigationBar.prefersLargeTitles = YES;
|
|
531
|
+
}
|
|
532
|
+
navitem.largeTitleDisplayMode =
|
|
533
|
+
config.largeTitle ? UINavigationItemLargeTitleDisplayModeAlways : UINavigationItemLargeTitleDisplayModeNever;
|
|
534
|
+
}
|
|
535
|
+
#endif
|
|
536
|
+
|
|
537
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
|
538
|
+
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
|
539
|
+
if (@available(iOS 13.0, tvOS 13.0, *)) {
|
|
540
|
+
UINavigationBarAppearance *appearance = [self buildAppearance:vc withConfig:config];
|
|
541
|
+
navitem.standardAppearance = appearance;
|
|
542
|
+
navitem.compactAppearance = appearance;
|
|
543
|
+
|
|
544
|
+
UINavigationBarAppearance *scrollEdgeAppearance =
|
|
545
|
+
[[UINavigationBarAppearance alloc] initWithBarAppearance:appearance];
|
|
546
|
+
if (config.largeTitleBackgroundColor != nil) {
|
|
547
|
+
scrollEdgeAppearance.backgroundColor = config.largeTitleBackgroundColor;
|
|
548
|
+
}
|
|
549
|
+
if (config.largeTitleHideShadow) {
|
|
550
|
+
scrollEdgeAppearance.shadowColor = nil;
|
|
551
|
+
}
|
|
552
|
+
navitem.scrollEdgeAppearance = scrollEdgeAppearance;
|
|
553
|
+
} else
|
|
554
|
+
#endif
|
|
555
|
+
{
|
|
556
|
+
#if !TARGET_OS_TV
|
|
557
|
+
// updating backIndicatotImage does not work when called during transition. On iOS pre 13 we need
|
|
558
|
+
// to update it before the navigation starts.
|
|
559
|
+
UIImage *backButtonImage = [self loadBackButtonImageInViewController:vc withConfig:config];
|
|
560
|
+
if (backButtonImage) {
|
|
561
|
+
navctr.navigationBar.backIndicatorImage = backButtonImage;
|
|
562
|
+
navctr.navigationBar.backIndicatorTransitionMaskImage = backButtonImage;
|
|
563
|
+
} else if (navctr.navigationBar.backIndicatorImage) {
|
|
564
|
+
navctr.navigationBar.backIndicatorImage = nil;
|
|
565
|
+
navctr.navigationBar.backIndicatorTransitionMaskImage = nil;
|
|
566
|
+
}
|
|
567
|
+
#endif
|
|
568
|
+
}
|
|
569
|
+
#if !TARGET_OS_TV
|
|
570
|
+
navitem.hidesBackButton = config.hideBackButton;
|
|
571
|
+
#endif
|
|
572
|
+
navitem.leftBarButtonItem = nil;
|
|
573
|
+
navitem.rightBarButtonItem = nil;
|
|
574
|
+
navitem.titleView = nil;
|
|
575
|
+
|
|
576
|
+
for (RNSScreenStackHeaderSubview *subview in config.reactSubviews) {
|
|
577
|
+
switch (subview.type) {
|
|
578
|
+
case RNSScreenStackHeaderSubviewTypeLeft: {
|
|
579
|
+
#if !TARGET_OS_TV
|
|
580
|
+
navitem.leftItemsSupplementBackButton = config.backButtonInCustomView;
|
|
581
|
+
#endif
|
|
582
|
+
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithCustomView:subview];
|
|
583
|
+
navitem.leftBarButtonItem = buttonItem;
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
case RNSScreenStackHeaderSubviewTypeRight: {
|
|
587
|
+
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithCustomView:subview];
|
|
588
|
+
navitem.rightBarButtonItem = buttonItem;
|
|
589
|
+
break;
|
|
590
|
+
}
|
|
591
|
+
case RNSScreenStackHeaderSubviewTypeCenter:
|
|
592
|
+
case RNSScreenStackHeaderSubviewTypeTitle: {
|
|
593
|
+
navitem.titleView = subview;
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
case RNSScreenStackHeaderSubviewTypeSearchBar: {
|
|
597
|
+
if (subview.subviews == nil || [subview.subviews count] == 0) {
|
|
598
|
+
RCTLogWarn(
|
|
599
|
+
@"Failed to attach search bar to the header. We recommend using `useLayoutEffect` when managing "
|
|
600
|
+
"searchBar properties dynamically. \n\nSee: github.com/software-mansion/react-native-screens/issues/1188");
|
|
601
|
+
break;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if ([subview.subviews[0] isKindOfClass:[RNSSearchBar class]]) {
|
|
605
|
+
#if !TARGET_OS_TV
|
|
606
|
+
if (@available(iOS 11.0, *)) {
|
|
607
|
+
RNSSearchBar *searchBar = subview.subviews[0];
|
|
608
|
+
navitem.searchController = searchBar.controller;
|
|
609
|
+
navitem.hidesSearchBarWhenScrolling = searchBar.hideWhenScrolling;
|
|
610
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_16_0) && \
|
|
611
|
+
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_16_0
|
|
612
|
+
if (@available(iOS 16.0, *)) {
|
|
613
|
+
navitem.preferredSearchBarPlacement = [searchBar placementAsUINavigationItemSearchBarPlacement];
|
|
614
|
+
}
|
|
615
|
+
#endif /* Check for iOS 16.0 */
|
|
616
|
+
}
|
|
617
|
+
#endif /* !TARGET_OS_TV */
|
|
618
|
+
}
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
case RNSScreenStackHeaderSubviewTypeBackButton: {
|
|
622
|
+
break;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// This assignment should be done after `navitem.titleView = ...` assignment (iOS 16.0 bug).
|
|
628
|
+
// See: https://github.com/software-mansion/react-native-screens/issues/1570 (comments)
|
|
629
|
+
navitem.title = config.title;
|
|
630
|
+
|
|
631
|
+
if (animated && vc.transitionCoordinator != nil &&
|
|
632
|
+
vc.transitionCoordinator.presentationStyle == UIModalPresentationNone && !wasHidden) {
|
|
633
|
+
// when there is an ongoing transition we may need to update navbar setting in animation block
|
|
634
|
+
// using animateAlongsideTransition. However, we only do that given the transition is not a modal
|
|
635
|
+
// transition (presentationStyle == UIModalPresentationNone) and that the bar was not previously
|
|
636
|
+
// hidden. This is because both for modal transitions and transitions from screen with hidden bar
|
|
637
|
+
// the transition animation block does not get triggered. This is ok, because with both of those
|
|
638
|
+
// types of transitions there is no "shared" navigation bar that needs to be updated in an animated
|
|
639
|
+
// way.
|
|
640
|
+
[vc.transitionCoordinator
|
|
641
|
+
animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
|
|
642
|
+
[self setAnimatedConfig:vc withConfig:config];
|
|
643
|
+
}
|
|
644
|
+
completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
|
|
645
|
+
if ([context isCancelled]) {
|
|
646
|
+
UIViewController *fromVC = [context viewControllerForKey:UITransitionContextFromViewControllerKey];
|
|
647
|
+
RNSScreenStackHeaderConfig *config = nil;
|
|
648
|
+
for (UIView *subview in fromVC.view.reactSubviews) {
|
|
649
|
+
if ([subview isKindOfClass:[RNSScreenStackHeaderConfig class]]) {
|
|
650
|
+
config = (RNSScreenStackHeaderConfig *)subview;
|
|
651
|
+
break;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
[self setAnimatedConfig:fromVC withConfig:config];
|
|
655
|
+
}
|
|
656
|
+
}];
|
|
657
|
+
} else {
|
|
658
|
+
[self setAnimatedConfig:vc withConfig:config];
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
- (void)insertReactSubview:(RNSScreenStackHeaderSubview *)subview atIndex:(NSInteger)atIndex
|
|
663
|
+
{
|
|
664
|
+
[_reactSubviews insertObject:subview atIndex:atIndex];
|
|
665
|
+
subview.reactSuperview = self;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
- (void)removeReactSubview:(RNSScreenStackHeaderSubview *)subview
|
|
669
|
+
{
|
|
670
|
+
[_reactSubviews removeObject:subview];
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
- (void)didUpdateReactSubviews
|
|
674
|
+
{
|
|
675
|
+
[super didUpdateReactSubviews];
|
|
676
|
+
[self updateViewControllerIfNeeded];
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
680
|
+
#pragma mark - Fabric specific
|
|
681
|
+
|
|
682
|
+
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
683
|
+
{
|
|
684
|
+
if (![childComponentView isKindOfClass:[RNSScreenStackHeaderSubview class]]) {
|
|
685
|
+
RCTLogError(@"ScreenStackHeader only accepts children of type ScreenStackHeaderSubview");
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
RCTAssert(
|
|
690
|
+
childComponentView.superview == nil,
|
|
691
|
+
@"Attempt to mount already mounted component view. (parent: %@, child: %@, index: %@, existing parent: %@)",
|
|
692
|
+
self,
|
|
693
|
+
childComponentView,
|
|
694
|
+
@(index),
|
|
695
|
+
@([childComponentView.superview tag]));
|
|
696
|
+
|
|
697
|
+
// [_reactSubviews insertObject:(RNSScreenStackHeaderSubview *)childComponentView atIndex:index];
|
|
698
|
+
[self insertReactSubview:(RNSScreenStackHeaderSubview *)childComponentView atIndex:index];
|
|
699
|
+
[self updateViewControllerIfNeeded];
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
703
|
+
{
|
|
704
|
+
[_reactSubviews removeObject:(RNSScreenStackHeaderSubview *)childComponentView];
|
|
705
|
+
[childComponentView removeFromSuperview];
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
static RCTResizeMode resizeModeFromCppEquiv(react::ImageResizeMode resizeMode)
|
|
709
|
+
{
|
|
710
|
+
switch (resizeMode) {
|
|
711
|
+
case react::ImageResizeMode::Cover:
|
|
712
|
+
return RCTResizeModeCover;
|
|
713
|
+
case react::ImageResizeMode::Contain:
|
|
714
|
+
return RCTResizeModeContain;
|
|
715
|
+
case react::ImageResizeMode::Stretch:
|
|
716
|
+
return RCTResizeModeStretch;
|
|
717
|
+
case react::ImageResizeMode::Center:
|
|
718
|
+
return RCTResizeModeCenter;
|
|
719
|
+
case react::ImageResizeMode::Repeat:
|
|
720
|
+
return RCTResizeModeRepeat;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Fabric implementation of helper method for +loadBackButtonImageInViewController:withConfig:
|
|
726
|
+
* There is corresponding Paper implementation (with different parameter type) in Paper specific section.
|
|
727
|
+
*/
|
|
728
|
+
+ (RCTImageSource *)imageSourceFromImageView:(RCTImageComponentView *)view
|
|
729
|
+
{
|
|
730
|
+
auto const imageProps = *std::static_pointer_cast<const react::ImageProps>(view.props);
|
|
731
|
+
react::ImageSource cppImageSource = imageProps.sources.at(0);
|
|
732
|
+
auto imageSize = CGSize{cppImageSource.size.width, cppImageSource.size.height};
|
|
733
|
+
NSURLRequest *request =
|
|
734
|
+
[NSURLRequest requestWithURL:[NSURL URLWithString:RCTNSStringFromStringNilIfEmpty(cppImageSource.uri)]];
|
|
735
|
+
RCTImageSource *imageSource = [[RCTImageSource alloc] initWithURLRequest:request
|
|
736
|
+
size:imageSize
|
|
737
|
+
scale:cppImageSource.scale];
|
|
738
|
+
return imageSource;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
#pragma mark - RCTComponentViewProtocol
|
|
742
|
+
|
|
743
|
+
- (void)prepareForRecycle
|
|
744
|
+
{
|
|
745
|
+
[super prepareForRecycle];
|
|
746
|
+
_initialPropsSet = NO;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
+ (react::ComponentDescriptorProvider)componentDescriptorProvider
|
|
750
|
+
{
|
|
751
|
+
return react::concreteComponentDescriptorProvider<react::RNSScreenStackHeaderConfigComponentDescriptor>();
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
- (NSNumber *)getFontSizePropValue:(int)value
|
|
755
|
+
{
|
|
756
|
+
if (value > 0)
|
|
757
|
+
return [NSNumber numberWithInt:value];
|
|
758
|
+
return nil;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
- (UISemanticContentAttribute)getDirectionPropValue:(react::RNSScreenStackHeaderConfigDirection)direction
|
|
762
|
+
{
|
|
763
|
+
switch (direction) {
|
|
764
|
+
case react::RNSScreenStackHeaderConfigDirection::Rtl:
|
|
765
|
+
return UISemanticContentAttributeForceRightToLeft;
|
|
766
|
+
case react::RNSScreenStackHeaderConfigDirection::Ltr:
|
|
767
|
+
return UISemanticContentAttributeForceLeftToRight;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
- (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::Shared const &)oldProps
|
|
772
|
+
{
|
|
773
|
+
const auto &oldScreenProps = *std::static_pointer_cast<const react::RNSScreenStackHeaderConfigProps>(_props);
|
|
774
|
+
const auto &newScreenProps = *std::static_pointer_cast<const react::RNSScreenStackHeaderConfigProps>(props);
|
|
775
|
+
|
|
776
|
+
BOOL needsNavigationControllerLayout = !_initialPropsSet;
|
|
777
|
+
|
|
778
|
+
if (newScreenProps.hidden != !_show) {
|
|
779
|
+
_show = !newScreenProps.hidden;
|
|
780
|
+
needsNavigationControllerLayout = YES;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
if (newScreenProps.translucent != _translucent) {
|
|
784
|
+
_translucent = newScreenProps.translucent;
|
|
785
|
+
needsNavigationControllerLayout = YES;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
if (newScreenProps.backButtonInCustomView != _backButtonInCustomView) {
|
|
789
|
+
[self setBackButtonInCustomView:newScreenProps.backButtonInCustomView];
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
_title = RCTNSStringFromStringNilIfEmpty(newScreenProps.title);
|
|
793
|
+
if (newScreenProps.titleFontFamily != oldScreenProps.titleFontFamily) {
|
|
794
|
+
_titleFontFamily = RCTNSStringFromStringNilIfEmpty(newScreenProps.titleFontFamily);
|
|
795
|
+
}
|
|
796
|
+
_titleFontWeight = RCTNSStringFromStringNilIfEmpty(newScreenProps.titleFontWeight);
|
|
797
|
+
_titleFontSize = [self getFontSizePropValue:newScreenProps.titleFontSize];
|
|
798
|
+
_hideShadow = newScreenProps.hideShadow;
|
|
799
|
+
|
|
800
|
+
_largeTitle = newScreenProps.largeTitle;
|
|
801
|
+
if (newScreenProps.largeTitleFontFamily != oldScreenProps.largeTitleFontFamily) {
|
|
802
|
+
_largeTitleFontFamily = RCTNSStringFromStringNilIfEmpty(newScreenProps.largeTitleFontFamily);
|
|
803
|
+
}
|
|
804
|
+
_largeTitleFontWeight = RCTNSStringFromStringNilIfEmpty(newScreenProps.largeTitleFontWeight);
|
|
805
|
+
_largeTitleFontSize = [self getFontSizePropValue:newScreenProps.largeTitleFontSize];
|
|
806
|
+
_largeTitleHideShadow = newScreenProps.largeTitleHideShadow;
|
|
807
|
+
|
|
808
|
+
_backTitle = RCTNSStringFromStringNilIfEmpty(newScreenProps.backTitle);
|
|
809
|
+
if (newScreenProps.backTitleFontFamily != oldScreenProps.backTitleFontFamily) {
|
|
810
|
+
_backTitleFontFamily = RCTNSStringFromStringNilIfEmpty(newScreenProps.backTitleFontFamily);
|
|
811
|
+
}
|
|
812
|
+
_backTitleFontSize = [self getFontSizePropValue:newScreenProps.backTitleFontSize];
|
|
813
|
+
_hideBackButton = newScreenProps.hideBackButton;
|
|
814
|
+
_disableBackButtonMenu = newScreenProps.disableBackButtonMenu;
|
|
815
|
+
|
|
816
|
+
if (newScreenProps.direction != oldScreenProps.direction) {
|
|
817
|
+
_direction = [self getDirectionPropValue:newScreenProps.direction];
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
_backTitleVisible = newScreenProps.backTitleVisible;
|
|
821
|
+
|
|
822
|
+
// We cannot compare SharedColor because it is shared value.
|
|
823
|
+
// We could compare color value, but it is more performant to just assign new value
|
|
824
|
+
_titleColor = RCTUIColorFromSharedColor(newScreenProps.titleColor);
|
|
825
|
+
_largeTitleColor = RCTUIColorFromSharedColor(newScreenProps.largeTitleColor);
|
|
826
|
+
_color = RCTUIColorFromSharedColor(newScreenProps.color);
|
|
827
|
+
_backgroundColor = RCTUIColorFromSharedColor(newScreenProps.backgroundColor);
|
|
828
|
+
|
|
829
|
+
[self updateViewControllerIfNeeded];
|
|
830
|
+
|
|
831
|
+
if (needsNavigationControllerLayout) {
|
|
832
|
+
[self layoutNavigationControllerView];
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
_initialPropsSet = YES;
|
|
836
|
+
_props = std::static_pointer_cast<react::RNSScreenStackHeaderConfigProps const>(props);
|
|
837
|
+
|
|
838
|
+
[super updateProps:props oldProps:oldProps];
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
#else
|
|
842
|
+
#pragma mark - Paper specific
|
|
843
|
+
|
|
844
|
+
- (void)didSetProps:(NSArray<NSString *> *)changedProps
|
|
845
|
+
{
|
|
846
|
+
[super didSetProps:changedProps];
|
|
847
|
+
[self updateViewControllerIfNeeded];
|
|
848
|
+
// We need to layout navigation controller view after translucent prop changes, because otherwise
|
|
849
|
+
// frame of RNSScreen will not be changed and screen content will remain the same size.
|
|
850
|
+
// For more details look at https://github.com/software-mansion/react-native-screens/issues/1158
|
|
851
|
+
if ([changedProps containsObject:@"translucent"]) {
|
|
852
|
+
[self layoutNavigationControllerView];
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* Paper implementation of helper method for +loadBackButtonImageInViewController:withConfig:
|
|
858
|
+
* There is corresponding Fabric implementation (with different parameter type) in Fabric specific section.
|
|
859
|
+
*/
|
|
860
|
+
+ (RCTImageSource *)imageSourceFromImageView:(RCTImageView *)view
|
|
861
|
+
{
|
|
862
|
+
return view.imageSources[0];
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
#endif
|
|
866
|
+
@end
|
|
867
|
+
|
|
868
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
869
|
+
Class<RCTComponentViewProtocol> RNSScreenStackHeaderConfigCls(void)
|
|
870
|
+
{
|
|
871
|
+
return RNSScreenStackHeaderConfig.class;
|
|
872
|
+
}
|
|
873
|
+
#endif
|
|
874
|
+
|
|
875
|
+
@implementation RNSScreenStackHeaderConfigManager
|
|
876
|
+
|
|
877
|
+
RCT_EXPORT_MODULE()
|
|
878
|
+
|
|
879
|
+
- (UIView *)view
|
|
880
|
+
{
|
|
881
|
+
return [RNSScreenStackHeaderConfig new];
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
RCT_EXPORT_VIEW_PROPERTY(title, NSString)
|
|
885
|
+
RCT_EXPORT_VIEW_PROPERTY(titleFontFamily, NSString)
|
|
886
|
+
RCT_EXPORT_VIEW_PROPERTY(titleFontSize, NSNumber)
|
|
887
|
+
RCT_EXPORT_VIEW_PROPERTY(titleFontWeight, NSString)
|
|
888
|
+
RCT_EXPORT_VIEW_PROPERTY(titleColor, UIColor)
|
|
889
|
+
RCT_EXPORT_VIEW_PROPERTY(backTitle, NSString)
|
|
890
|
+
RCT_EXPORT_VIEW_PROPERTY(backTitleFontFamily, NSString)
|
|
891
|
+
RCT_EXPORT_VIEW_PROPERTY(backTitleFontSize, NSNumber)
|
|
892
|
+
RCT_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor)
|
|
893
|
+
RCT_EXPORT_VIEW_PROPERTY(backTitleVisible, BOOL)
|
|
894
|
+
RCT_EXPORT_VIEW_PROPERTY(blurEffect, UIBlurEffectStyle)
|
|
895
|
+
RCT_EXPORT_VIEW_PROPERTY(color, UIColor)
|
|
896
|
+
RCT_EXPORT_VIEW_PROPERTY(direction, UISemanticContentAttribute)
|
|
897
|
+
RCT_EXPORT_VIEW_PROPERTY(largeTitle, BOOL)
|
|
898
|
+
RCT_EXPORT_VIEW_PROPERTY(largeTitleFontFamily, NSString)
|
|
899
|
+
RCT_EXPORT_VIEW_PROPERTY(largeTitleFontSize, NSNumber)
|
|
900
|
+
RCT_EXPORT_VIEW_PROPERTY(largeTitleFontWeight, NSString)
|
|
901
|
+
RCT_EXPORT_VIEW_PROPERTY(largeTitleColor, UIColor)
|
|
902
|
+
RCT_EXPORT_VIEW_PROPERTY(largeTitleBackgroundColor, UIColor)
|
|
903
|
+
RCT_EXPORT_VIEW_PROPERTY(largeTitleHideShadow, BOOL)
|
|
904
|
+
RCT_EXPORT_VIEW_PROPERTY(hideBackButton, BOOL)
|
|
905
|
+
RCT_EXPORT_VIEW_PROPERTY(hideShadow, BOOL)
|
|
906
|
+
RCT_EXPORT_VIEW_PROPERTY(backButtonInCustomView, BOOL)
|
|
907
|
+
RCT_EXPORT_VIEW_PROPERTY(disableBackButtonMenu, BOOL)
|
|
908
|
+
// `hidden` is an UIView property, we need to use different name internally
|
|
909
|
+
RCT_REMAP_VIEW_PROPERTY(hidden, hide, BOOL)
|
|
910
|
+
RCT_EXPORT_VIEW_PROPERTY(translucent, BOOL)
|
|
911
|
+
|
|
912
|
+
@end
|
|
913
|
+
|
|
914
|
+
@implementation RCTConvert (RNSScreenStackHeader)
|
|
915
|
+
|
|
916
|
+
+ (NSMutableDictionary *)blurEffectsForIOSVersion
|
|
917
|
+
{
|
|
918
|
+
NSMutableDictionary *blurEffects = [NSMutableDictionary new];
|
|
919
|
+
[blurEffects addEntriesFromDictionary:@{
|
|
920
|
+
@"extraLight" : @(UIBlurEffectStyleExtraLight),
|
|
921
|
+
@"light" : @(UIBlurEffectStyleLight),
|
|
922
|
+
@"dark" : @(UIBlurEffectStyleDark),
|
|
923
|
+
}];
|
|
924
|
+
|
|
925
|
+
if (@available(iOS 10.0, *)) {
|
|
926
|
+
[blurEffects addEntriesFromDictionary:@{
|
|
927
|
+
@"regular" : @(UIBlurEffectStyleRegular),
|
|
928
|
+
@"prominent" : @(UIBlurEffectStyleProminent),
|
|
929
|
+
}];
|
|
930
|
+
}
|
|
931
|
+
#if !TARGET_OS_TV && defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
|
|
932
|
+
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
|
|
933
|
+
if (@available(iOS 13.0, *)) {
|
|
934
|
+
[blurEffects addEntriesFromDictionary:@{
|
|
935
|
+
@"systemUltraThinMaterial" : @(UIBlurEffectStyleSystemUltraThinMaterial),
|
|
936
|
+
@"systemThinMaterial" : @(UIBlurEffectStyleSystemThinMaterial),
|
|
937
|
+
@"systemMaterial" : @(UIBlurEffectStyleSystemMaterial),
|
|
938
|
+
@"systemThickMaterial" : @(UIBlurEffectStyleSystemThickMaterial),
|
|
939
|
+
@"systemChromeMaterial" : @(UIBlurEffectStyleSystemChromeMaterial),
|
|
940
|
+
@"systemUltraThinMaterialLight" : @(UIBlurEffectStyleSystemUltraThinMaterialLight),
|
|
941
|
+
@"systemThinMaterialLight" : @(UIBlurEffectStyleSystemThinMaterialLight),
|
|
942
|
+
@"systemMaterialLight" : @(UIBlurEffectStyleSystemMaterialLight),
|
|
943
|
+
@"systemThickMaterialLight" : @(UIBlurEffectStyleSystemThickMaterialLight),
|
|
944
|
+
@"systemChromeMaterialLight" : @(UIBlurEffectStyleSystemChromeMaterialLight),
|
|
945
|
+
@"systemUltraThinMaterialDark" : @(UIBlurEffectStyleSystemUltraThinMaterialDark),
|
|
946
|
+
@"systemThinMaterialDark" : @(UIBlurEffectStyleSystemThinMaterialDark),
|
|
947
|
+
@"systemMaterialDark" : @(UIBlurEffectStyleSystemMaterialDark),
|
|
948
|
+
@"systemThickMaterialDark" : @(UIBlurEffectStyleSystemThickMaterialDark),
|
|
949
|
+
@"systemChromeMaterialDark" : @(UIBlurEffectStyleSystemChromeMaterialDark),
|
|
950
|
+
}];
|
|
951
|
+
}
|
|
952
|
+
#endif
|
|
953
|
+
return blurEffects;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
RCT_ENUM_CONVERTER(
|
|
957
|
+
UISemanticContentAttribute,
|
|
958
|
+
(@{
|
|
959
|
+
@"ltr" : @(UISemanticContentAttributeForceLeftToRight),
|
|
960
|
+
@"rtl" : @(UISemanticContentAttributeForceRightToLeft),
|
|
961
|
+
}),
|
|
962
|
+
UISemanticContentAttributeUnspecified,
|
|
963
|
+
integerValue)
|
|
964
|
+
|
|
965
|
+
RCT_ENUM_CONVERTER(UIBlurEffectStyle, ([self blurEffectsForIOSVersion]), UIBlurEffectStyleExtraLight, integerValue)
|
|
966
|
+
|
|
967
|
+
@end
|