react-native-screens 5.0.0-alpha.2 → 5.0.0-alpha.3
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/Package.swift +87 -0
- package/README.md +0 -7
- package/android/src/main/cpp/NativeProxy.cpp +30 -6
- package/android/src/main/cpp/NativeProxy.h +7 -1
- package/android/src/main/java/com/swmansion/rnscreens/common/container/Container.kt +8 -0
- package/android/src/main/java/com/swmansion/rnscreens/common/container/ContainerItem.kt +13 -1
- package/android/src/main/java/com/swmansion/rnscreens/common/text/ReactTextAppearance.kt +62 -0
- package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearance.kt +20 -0
- package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearanceDefaults.kt +65 -0
- package/android/src/main/java/com/swmansion/rnscreens/helpers/PropIconResolver.kt +17 -23
- package/android/src/main/java/com/swmansion/rnscreens/legacy/Screen.kt +3 -1
- package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStack.kt +2 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetBehaviorController.kt +49 -18
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetDimensionsCoordinator.kt +65 -40
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetKeyboardCoordinator.kt +101 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetNativeDismissCoordinator.kt +0 -6
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetAvailableHeightProvider.kt +44 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialog.kt +35 -3
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialogManager.kt +33 -106
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/interfaces/FormSheetDialogEventEmitter.kt +2 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/model/FormSheetDetents.kt +61 -15
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetAnimatorFactory.kt +8 -9
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDimmingManager.kt +115 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDismissalOrigin.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentation.kt +173 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationManager.kt +141 -49
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationState.kt +1 -1
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetStackRegistry.kt +28 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/event/FormSheetDismissEvent.kt +29 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/host/FormSheetHostEventEmitter.kt +7 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/host/FormSheetHostViewManager.kt +2 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderApplicator.kt +369 -58
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderBackPressHandler.kt +11 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderCoordinatorLayout.kt +143 -98
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderAppBarLayout.kt +155 -23
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderContentScrimDrawable.kt +36 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderCollapsedTitleGravityMode.kt +6 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfig.kt +170 -167
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigViewManager.kt +385 -12
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationObserver.kt +0 -4
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationProviding.kt +32 -3
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderDelegate.kt +0 -7
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderInvalidationFlags.kt +7 -2
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuApplicator.kt +27 -280
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuController.kt +448 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuDelegate.kt +10 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuMapper.kt +28 -20
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuConfig.kt +3 -55
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuGroupMetadata.kt +1 -10
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuItemConfig.kt +1 -3
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuModel.kt +180 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementOptions.kt +57 -6
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementRawUpdate.kt +3 -1
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementUpdate.kt +1 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuIconResolver.kt +4 -3
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuUpdateQueue.kt +23 -9
- package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackContainer.kt +103 -3
- package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHost.kt +13 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHostViewManager.kt +14 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreen.kt +4 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragment.kt +20 -1
- package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragmentDelegate.kt +12 -0
- package/android/src/main/java/com/swmansion/rnscreens/tabs/appearance/TabsAppearanceCoordinator.kt +2 -4
- package/android/src/main/java/com/swmansion/rnscreens/tabs/container/MenuHelpers.kt +5 -23
- package/android/src/main/java/com/swmansion/rnscreens/tabs/container/TabsContainer.kt +46 -25
- package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHost.kt +10 -0
- package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHostA11yCoordinator.kt +23 -2
- package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreen.kt +17 -0
- package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenFragment.kt +3 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/DimensionUtils.kt +7 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/StyleUtils.kt +22 -0
- package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_available_space.xml +8 -0
- package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_entire_space.xml +8 -0
- package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_available_space.xml +8 -0
- package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_entire_space.xml +8 -0
- package/cpp/legacy/RNSScreenRemovalListener.cpp +31 -1
- package/cpp/legacy/RNSScreenRemovalListener.h +18 -3
- package/ios/RNSEnums.h +2 -0
- package/ios/conversion/RNSConversions.h +7 -108
- package/ios/legacy/RNSFullWindowOverlay.mm +1 -1
- package/ios/legacy/RNSModalScreen.mm +1 -1
- package/ios/legacy/RNSScreen.mm +8 -19
- package/ios/legacy/RNSScreenStackHeaderConfig.mm +3 -1
- package/ios/legacy/RNSScreenStackHeaderSubview.mm +1 -1
- package/ios/legacy/RNSScreenWindowTraits.mm +5 -13
- package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.h +1 -3
- package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.mm +11 -22
- package/ios/modals/form-sheet/RNSFormSheetContentController.h +1 -1
- package/ios/modals/form-sheet/RNSFormSheetContentController.mm +7 -18
- package/ios/modals/form-sheet/RNSFormSheetHostComponentView.mm +4 -4
- package/ios/modals/form-sheet/RNSFormSheetHostShadowStateProxy.mm +2 -2
- package/ios/modals/form-sheet/RNSFormSheetUpdateFlags.h +3 -0
- package/ios/safe-area/RNSSafeAreaViewComponentView.mm +2 -2
- package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.mm +2 -3
- package/ios/split/RNSSplitAppearanceApplicator.h +4 -4
- package/ios/split/RNSSplitAppearanceApplicator.mm +53 -56
- package/ios/split/RNSSplitHostComponentEventEmitter.h +1 -0
- package/ios/split/RNSSplitHostComponentEventEmitter.mm +1 -1
- package/ios/split/RNSSplitHostComponentView.h +5 -15
- package/ios/split/RNSSplitHostComponentView.mm +55 -6
- package/ios/split/RNSSplitHostController.h +25 -6
- package/ios/split/RNSSplitHostController.mm +24 -92
- package/ios/split/RNSSplitHostProviders.h +67 -0
- package/ios/split/RNSSplitScreenComponentView.h +0 -39
- package/ios/split/RNSSplitScreenComponentView.mm +27 -10
- package/ios/split/RNSSplitScreenController.h +26 -3
- package/ios/split/RNSSplitScreenController.mm +13 -30
- package/ios/split/RNSSplitScreenShadowStateProxy.h +1 -40
- package/ios/split/RNSSplitScreenShadowStateProxy.mm +1 -26
- package/ios/split/conversion/RNSConversions-SplitView.h +56 -0
- package/ios/{conversion → split/conversion}/RNSConversions-SplitView.mm +4 -1
- package/ios/stack/conversion/RNSConversions-Stack.h +32 -0
- package/ios/stack/conversion/RNSConversions-Stack.mm +55 -0
- package/ios/stack/header/RNSStackHeaderAppearanceMapper.h +26 -0
- package/ios/stack/header/RNSStackHeaderAppearanceMapper.mm +88 -0
- package/ios/stack/header/RNSStackHeaderConfigComponentView.h +10 -1
- package/ios/stack/header/RNSStackHeaderConfigComponentView.mm +67 -35
- package/ios/stack/header/RNSStackHeaderConfigDataProviding.h +6 -0
- package/ios/stack/header/RNSStackHeaderConfigShadowStateProxy.mm +1 -1
- package/ios/stack/header/RNSStackHeaderIconResolver.mm +7 -0
- package/ios/stack/header/RNSStackHeaderItemComponentView.h +3 -1
- package/ios/stack/header/RNSStackHeaderItemComponentView.mm +15 -2
- package/ios/stack/header/RNSStackHeaderItemDataProviding.h +2 -0
- package/ios/stack/header/RNSStackHeaderItemShadowStateProxy.mm +1 -1
- package/ios/stack/header/RNSStackHeaderItemSpacerComponentView.mm +2 -1
- package/ios/stack/header/RNSStackHeaderMenuMapper.mm +4 -0
- package/ios/stack/host/RNSStackNavigationBar.h +25 -0
- package/ios/stack/host/RNSStackNavigationBar.mm +80 -0
- package/ios/stack/host/RNSStackNavigationBarCoordinator.h +8 -0
- package/ios/stack/host/RNSStackNavigationBarCoordinator.mm +11 -0
- package/ios/stack/host/RNSStackNavigationController.mm +13 -5
- package/ios/stack/host/RNSStackOperation.h +0 -2
- package/ios/stack/screen/RNSStackScreenComponentView.mm +9 -2
- package/ios/stack/screen/RNSStackScreenController.mm +12 -0
- package/ios/stack/screen/RNSStackScreenHeaderCoordinator.h +8 -0
- package/ios/stack/screen/RNSStackScreenHeaderCoordinator.mm +98 -16
- package/ios/tabs/RNSTabBarAppearanceCoordinator.mm +40 -9
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.h +1 -1
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm +1 -1
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm +1 -1
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryEventEmitter.mm +1 -1
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryShadowStateProxy.mm +1 -1
- package/ios/tabs/conversion/RNSConversions-Tabs.h +78 -0
- package/ios/{conversion → tabs/conversion}/RNSConversions-Tabs.mm +8 -71
- package/ios/tabs/extensions/RNSTabsHostComponentView+RNSImageLoader.h +1 -1
- package/ios/tabs/host/RNSTabsHostComponentView.h +2 -0
- package/ios/tabs/host/RNSTabsHostComponentView.mm +10 -3
- package/ios/tabs/host/RNSTabsHostEventEmitter.mm +1 -1
- package/ios/tabs/screen/RNSTabsScreenComponentView.mm +20 -5
- package/ios/utils/RNSDefines.h +3 -0
- package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js +34 -19
- package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js.map +1 -1
- package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js +33 -1
- package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
- package/lib/commonjs/components/stack/host/StackHost.js +9 -6
- package/lib/commonjs/components/stack/host/StackHost.js.map +1 -1
- package/lib/commonjs/components/stack/index.js.map +1 -1
- package/lib/commonjs/components/tabs/host/TabsHost.ios.js +1 -0
- package/lib/commonjs/components/tabs/host/TabsHost.ios.js.map +1 -1
- package/lib/commonjs/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/stack/StackHostNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
- package/lib/module/components/stack/header/StackHeaderConfig.android.js +35 -20
- package/lib/module/components/stack/header/StackHeaderConfig.android.js.map +1 -1
- package/lib/module/components/stack/header/StackHeaderConfig.ios.js +34 -2
- package/lib/module/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
- package/lib/module/components/stack/host/StackHost.js +9 -6
- package/lib/module/components/stack/host/StackHost.js.map +1 -1
- package/lib/module/components/stack/index.js.map +1 -1
- package/lib/module/components/tabs/host/TabsHost.ios.js +1 -0
- package/lib/module/components/tabs/host/TabsHost.ios.js.map +1 -1
- package/lib/module/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
- package/lib/module/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
- package/lib/module/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
- package/lib/module/fabric/stack/StackHostNativeComponent.js.map +1 -1
- package/lib/module/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
- package/lib/typescript/components/modals/form-sheet/FormSheet.types.d.ts +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.android.d.ts.map +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts +616 -21
- package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts.map +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.ios.d.ts.map +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts +226 -2
- package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts.map +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.types.d.ts +2 -2
- package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts +2 -0
- package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts.map +1 -1
- package/lib/typescript/components/stack/host/StackHost.d.ts +1 -1
- package/lib/typescript/components/stack/host/StackHost.d.ts.map +1 -1
- package/lib/typescript/components/stack/host/StackHost.types.d.ts +24 -0
- package/lib/typescript/components/stack/host/StackHost.types.d.ts.map +1 -1
- package/lib/typescript/components/stack/index.d.ts +2 -2
- package/lib/typescript/components/stack/index.d.ts.map +1 -1
- package/lib/typescript/components/tabs/host/TabsHost.ios.d.ts.map +1 -1
- package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts +16 -0
- package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts.map +1 -1
- package/lib/typescript/components/tabs/host/TabsHost.types.d.ts +3 -0
- package/lib/typescript/components/tabs/host/TabsHost.types.d.ts.map +1 -1
- package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts +52 -0
- package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts +25 -1
- package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts +2 -0
- package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts +3 -1
- package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts +1 -0
- package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts.map +1 -1
- package/package.json +8 -7
- package/react-native.config.js +3 -0
- package/src/components/modals/form-sheet/FormSheet.types.ts +1 -1
- package/src/components/stack/header/StackHeaderConfig.android.tsx +48 -23
- package/src/components/stack/header/StackHeaderConfig.android.types.ts +637 -21
- package/src/components/stack/header/StackHeaderConfig.ios.tsx +45 -1
- package/src/components/stack/header/StackHeaderConfig.ios.types.ts +238 -2
- package/src/components/stack/header/StackHeaderConfig.types.ts +2 -2
- package/src/components/stack/header/ios/StackHeaderItem.ios.types.ts +2 -0
- package/src/components/stack/host/StackHost.tsx +4 -2
- package/src/components/stack/host/StackHost.types.ts +26 -0
- package/src/components/stack/index.ts +6 -1
- package/src/components/tabs/host/TabsHost.ios.tsx +1 -0
- package/src/components/tabs/host/TabsHost.ios.types.ts +16 -0
- package/src/components/tabs/host/TabsHost.types.ts +3 -0
- package/src/fabric/stack/StackHeaderConfigAndroidNativeComponent.ts +78 -0
- package/src/fabric/stack/StackHeaderConfigIOSNativeComponent.ts +32 -0
- package/src/fabric/stack/StackHeaderItemIOSNativeComponent.ts +2 -0
- package/src/fabric/stack/StackHostNativeComponent.ts +11 -2
- package/src/fabric/tabs/TabsHostIOSNativeComponent.ts +1 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingView.kt +0 -83
- package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewManager.kt +0 -89
- package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewPointerEvents.kt +0 -18
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuSelectionController.kt +0 -83
- package/ios/conversion/RNSConversions-Stack.h +0 -32
- package/ios/conversion/RNSConversions-Stack.mm +0 -41
- package/ios/conversion/always_false.h +0 -31
- /package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.h +0 -0
package/Package.swift
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// swift-tools-version: 6.0
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
// Header search paths for quoted cross-directory imports (SPM has no CocoaPods header maps).
|
|
5
|
+
// Keep in sync when adding new ios/ subdirectories that contain headers.
|
|
6
|
+
let headerSearchPaths: [String] = [
|
|
7
|
+
"ios",
|
|
8
|
+
"ios/bridging",
|
|
9
|
+
"ios/conversion",
|
|
10
|
+
"ios/helpers/container",
|
|
11
|
+
"ios/helpers/image",
|
|
12
|
+
"ios/helpers/scroll-view",
|
|
13
|
+
"ios/legacy",
|
|
14
|
+
"ios/legacy/events",
|
|
15
|
+
"ios/legacy/integrations",
|
|
16
|
+
"ios/legacy/utils",
|
|
17
|
+
"ios/modals/form-sheet",
|
|
18
|
+
"ios/modals/utils",
|
|
19
|
+
"ios/safe-area",
|
|
20
|
+
"ios/scroll-to-top-guard",
|
|
21
|
+
"ios/scroll-view-marker",
|
|
22
|
+
"ios/scroll-view-marker/conversion",
|
|
23
|
+
"ios/split",
|
|
24
|
+
"ios/split/conversion",
|
|
25
|
+
"ios/stack",
|
|
26
|
+
"ios/stack/conversion",
|
|
27
|
+
"ios/stack/header",
|
|
28
|
+
"ios/stack/host",
|
|
29
|
+
"ios/stack/screen",
|
|
30
|
+
"ios/tabs",
|
|
31
|
+
"ios/tabs/bottom-accessory",
|
|
32
|
+
"ios/tabs/conversion",
|
|
33
|
+
"ios/tabs/extensions",
|
|
34
|
+
"ios/tabs/host",
|
|
35
|
+
"ios/tabs/screen",
|
|
36
|
+
"ios/utils",
|
|
37
|
+
"ios/utils/extensions",
|
|
38
|
+
"common/cpp",
|
|
39
|
+
"cpp/legacy",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
let cSettings: [CSetting] = headerSearchPaths.map { .headerSearchPath($0) }
|
|
43
|
+
|
|
44
|
+
let cxxSettings: [CXXSetting] = [
|
|
45
|
+
.define("DEBUG", .when(configuration: .debug)),
|
|
46
|
+
.define("NDEBUG", .when(configuration: .release)),
|
|
47
|
+
] + headerSearchPaths.map { .headerSearchPath($0) }
|
|
48
|
+
|
|
49
|
+
let package = Package(
|
|
50
|
+
name: "RNScreens",
|
|
51
|
+
platforms: [.iOS(.v15)],
|
|
52
|
+
products: [
|
|
53
|
+
.library(name: "RNScreens", targets: ["RNScreens"]),
|
|
54
|
+
],
|
|
55
|
+
dependencies: [
|
|
56
|
+
// Resolved from the autolinker symlink `<app>/ios/build/generated/autolinking/libs/RNScreens`,
|
|
57
|
+
// not from node_modules: `../../../../xcframeworks` -> `<app>/ios/build/xcframeworks`,
|
|
58
|
+
// `../../../ios` -> `<app>/ios/build/generated/ios`. Same layout `npx react-native spm scaffold` emits.
|
|
59
|
+
// Making this self-contained (remote RN package URL + shipping our own codegen output) is blocked
|
|
60
|
+
// on RN publishing a remote SPM package and would require `codegenConfig.includesGeneratedCode`, see:
|
|
61
|
+
// https://github.com/react/react-native/blob/v0.87.1/packages/react-native/scripts/spm/__docs__/spm-header-paths-contract.md#hand-authored-community-library-contract
|
|
62
|
+
.package(name: "ReactNative", path: "../../../../xcframeworks"),
|
|
63
|
+
.package(name: "React-GeneratedCode", path: "../../../ios"),
|
|
64
|
+
],
|
|
65
|
+
targets: [
|
|
66
|
+
.target(
|
|
67
|
+
name: "RNScreens",
|
|
68
|
+
dependencies: [
|
|
69
|
+
.product(name: "ReactHeaders", package: "ReactNative"),
|
|
70
|
+
.product(name: "ReactNativeHeaders", package: "ReactNative"),
|
|
71
|
+
.product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"),
|
|
72
|
+
.product(name: "ReactAppHeaders", package: "React-GeneratedCode"),
|
|
73
|
+
],
|
|
74
|
+
path: ".",
|
|
75
|
+
exclude: ["ios/RNScreens.xcodeproj"],
|
|
76
|
+
sources: ["ios", "common/cpp", "cpp"],
|
|
77
|
+
publicHeadersPath: "ios",
|
|
78
|
+
cSettings: cSettings,
|
|
79
|
+
cxxSettings: cxxSettings,
|
|
80
|
+
linkerSettings: [
|
|
81
|
+
.linkedFramework("UIKit"),
|
|
82
|
+
.linkedFramework("Foundation"),
|
|
83
|
+
]
|
|
84
|
+
),
|
|
85
|
+
],
|
|
86
|
+
cxxLanguageStandard: .cxx20
|
|
87
|
+
)
|
package/README.md
CHANGED
|
@@ -254,13 +254,6 @@ There are many ways to contribute to this project. See [CONTRIBUTING](https://gi
|
|
|
254
254
|
|
|
255
255
|
React native screens library is licensed under [The MIT License](LICENSE).
|
|
256
256
|
|
|
257
|
-
## Credits
|
|
258
|
-
|
|
259
|
-
This project has been built and is maintained thanks to the support from [Expo.io](https://expo.io) and [Software Mansion](https://swmansion.com).
|
|
260
|
-
|
|
261
|
-
[](https://expo.io)
|
|
262
|
-
[](https://swmansion.com)
|
|
263
|
-
|
|
264
257
|
## React Native Screens is created by Software Mansion
|
|
265
258
|
|
|
266
259
|
Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues. We can help you build your next dream product – [Hire us](https://swmansion.com/contact/projects?utm_source=screens&utm_medium=readme).
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include <react/fabric/Binding.h>
|
|
3
3
|
#include <react/renderer/scheduler/Scheduler.h>
|
|
4
4
|
|
|
5
|
+
#include <memory>
|
|
5
6
|
#include <string>
|
|
6
7
|
|
|
7
8
|
#include "NativeProxy.h"
|
|
@@ -11,6 +12,19 @@ using namespace react;
|
|
|
11
12
|
|
|
12
13
|
namespace rnscreens {
|
|
13
14
|
|
|
15
|
+
namespace {
|
|
16
|
+
// Keep this listener process-lifetime to avoid races during initialization,
|
|
17
|
+
// when nativeAddMutationsListener() can be called concurrently from different
|
|
18
|
+
// threads. A function-local static initializes thread-safely, and an immortal
|
|
19
|
+
// instance suits core's delegate list, which is append-only. For more details:
|
|
20
|
+
// https://github.com/software-mansion/react-native-screens/pull/4413
|
|
21
|
+
const std::shared_ptr<RNSScreenRemovalListener> &removalListener() {
|
|
22
|
+
static const std::shared_ptr<RNSScreenRemovalListener> instance =
|
|
23
|
+
std::make_shared<RNSScreenRemovalListener>();
|
|
24
|
+
return instance;
|
|
25
|
+
}
|
|
26
|
+
} // namespace
|
|
27
|
+
|
|
14
28
|
NativeProxy::NativeProxy(jni::alias_ref<NativeProxy::javaobject> jThis)
|
|
15
29
|
: javaPart_(jni::make_global(jThis)) {}
|
|
16
30
|
|
|
@@ -32,13 +46,18 @@ void NativeProxy::nativeAddMutationsListener(
|
|
|
32
46
|
auto uiManager =
|
|
33
47
|
fabricUIManager->getBinding()->getScheduler()->getUIManager();
|
|
34
48
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
{
|
|
50
|
+
// Capture a copy of the global ref, never `this`: the listener outlives
|
|
51
|
+
// this NativeProxy, and the old live read of javaPart_ at call time raced
|
|
52
|
+
// invalidateNative(). installMutex_ keeps the copy from racing the
|
|
53
|
+
// invalidation write and keeps the stored token matching the last install.
|
|
54
|
+
std::lock_guard<std::mutex> lock(installMutex_);
|
|
55
|
+
removalListenerToken_ =
|
|
56
|
+
removalListener()->setListener([javaPart = javaPart_](int tag) {
|
|
38
57
|
static const auto method =
|
|
39
|
-
|
|
58
|
+
javaPart->getClass()->getMethod<void(jint)>(
|
|
40
59
|
"notifyScreenRemoved");
|
|
41
|
-
method(
|
|
60
|
+
method(javaPart, tag);
|
|
42
61
|
});
|
|
43
62
|
}
|
|
44
63
|
|
|
@@ -79,7 +98,7 @@ void NativeProxy::addMountingCoordinatorIfNeeded(
|
|
|
79
98
|
});
|
|
80
99
|
|
|
81
100
|
if (!wasRegistered) {
|
|
82
|
-
coordinator->setMountingOverrideDelegate(
|
|
101
|
+
coordinator->setMountingOverrideDelegate(removalListener());
|
|
83
102
|
coordinatorsWithMountingOverrides_.push_back(coordinator);
|
|
84
103
|
}
|
|
85
104
|
}
|
|
@@ -90,6 +109,11 @@ jni::local_ref<NativeProxy::jhybriddata> NativeProxy::initHybrid(
|
|
|
90
109
|
}
|
|
91
110
|
|
|
92
111
|
void NativeProxy::invalidateNative() {
|
|
112
|
+
// Disarm before the hybrid is collected; also releases the captured global
|
|
113
|
+
// ref so the Java NativeProxy stays collectable. Serialized with the install
|
|
114
|
+
// path so the token is never stale and javaPart_ is not nulled mid-capture.
|
|
115
|
+
std::lock_guard<std::mutex> lock(installMutex_);
|
|
116
|
+
removalListener()->clearListener(removalListenerToken_);
|
|
93
117
|
javaPart_ = nullptr;
|
|
94
118
|
}
|
|
95
119
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <react/fabric/JFabricUIManager.h>
|
|
5
5
|
#include "RNSScreenRemovalListener.h"
|
|
6
6
|
|
|
7
|
+
#include <cstdint>
|
|
7
8
|
#include <mutex>
|
|
8
9
|
#include <string>
|
|
9
10
|
|
|
@@ -13,7 +14,6 @@ using namespace facebook::jni;
|
|
|
13
14
|
|
|
14
15
|
class NativeProxy : public jni::HybridClass<NativeProxy> {
|
|
15
16
|
public:
|
|
16
|
-
std::shared_ptr<RNSScreenRemovalListener> screenRemovalListener_;
|
|
17
17
|
std::vector<std::weak_ptr<const facebook::react::MountingCoordinator>>
|
|
18
18
|
coordinatorsWithMountingOverrides_;
|
|
19
19
|
static auto constexpr kJavaDescriptor =
|
|
@@ -28,6 +28,12 @@ class NativeProxy : public jni::HybridClass<NativeProxy> {
|
|
|
28
28
|
|
|
29
29
|
std::mutex coordinatorsMutex_;
|
|
30
30
|
|
|
31
|
+
// Serializes callback install (nativeAddMutationsListener) with
|
|
32
|
+
// invalidateNative: the install-time copy of javaPart_ must not race the
|
|
33
|
+
// invalidation write, and the stored token must match the last install.
|
|
34
|
+
std::mutex installMutex_;
|
|
35
|
+
uint64_t removalListenerToken_{0};
|
|
36
|
+
|
|
31
37
|
explicit NativeProxy(jni::alias_ref<NativeProxy::javaobject> jThis);
|
|
32
38
|
|
|
33
39
|
void nativeAddMutationsListener(
|
|
@@ -9,4 +9,12 @@ interface Container {
|
|
|
9
9
|
* (if any).
|
|
10
10
|
*/
|
|
11
11
|
fun resolveCurrentContentScrollView(): ViewGroup?
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Asked when this container's whole subtree is about to be natively dismissed,
|
|
15
|
+
* e.g. the screen hosting this container is popped. Returns the item that
|
|
16
|
+
* vetoes the dismissal via `preventNativeDismiss`, or null when nothing
|
|
17
|
+
* in the subtree does.
|
|
18
|
+
*/
|
|
19
|
+
fun wantsToPreventStackNativeDismiss(): ContainerItem?
|
|
12
20
|
}
|
|
@@ -2,7 +2,7 @@ package com.swmansion.rnscreens.common.container
|
|
|
2
2
|
|
|
3
3
|
import android.view.ViewGroup
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface ContainerItem {
|
|
6
6
|
// region Nested Container handling
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -27,4 +27,16 @@ internal interface ContainerItem {
|
|
|
27
27
|
fun findContentScrollView(): ViewGroup?
|
|
28
28
|
|
|
29
29
|
// endregion
|
|
30
|
+
|
|
31
|
+
// region Native dismissal
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Asked when this item (screen) is about to be natively dismissed together
|
|
35
|
+
* with its subtree. The nested container (if any) is consulted first; its
|
|
36
|
+
* non-null answer wins, otherwise the item answers for itself, returning
|
|
37
|
+
* itself when it vetoes the dismissal or null otherwise.
|
|
38
|
+
*/
|
|
39
|
+
fun wantsToPreventStackNativeDismiss(): ContainerItem?
|
|
40
|
+
|
|
41
|
+
// endregion
|
|
30
42
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
package com.swmansion.rnscreens.common.text
|
|
2
|
+
|
|
3
|
+
import android.content.res.AssetManager
|
|
4
|
+
import android.graphics.Typeface
|
|
5
|
+
import android.os.Build
|
|
6
|
+
import com.facebook.react.common.ReactConstants
|
|
7
|
+
import com.facebook.react.common.assets.ReactFontManager.TypefaceStyle
|
|
8
|
+
import com.facebook.react.views.text.ReactTypefaceUtils
|
|
9
|
+
import kotlin.properties.Delegates
|
|
10
|
+
import kotlin.properties.ReadWriteProperty
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* [TextAppearance] driven by React props. Font family, weight and style are kept as the raw
|
|
14
|
+
* React values and turned into a [Typeface]. [onChanged] is invoked whenever a property
|
|
15
|
+
* actually changes value.
|
|
16
|
+
*/
|
|
17
|
+
internal class ReactTextAppearance(
|
|
18
|
+
private val assets: AssetManager,
|
|
19
|
+
onChanged: () -> Unit,
|
|
20
|
+
) : TextAppearance {
|
|
21
|
+
override var color: Int? by changeNotifying(onChanged)
|
|
22
|
+
override var fontSize: Float? by changeNotifying(onChanged)
|
|
23
|
+
internal var fontFamily: String? by changeNotifying(onChanged)
|
|
24
|
+
internal var fontWeight: String? by changeNotifying(onChanged)
|
|
25
|
+
internal var fontStyle: String? by changeNotifying(onChanged)
|
|
26
|
+
|
|
27
|
+
override fun resolveTypeface(base: Typeface): Typeface {
|
|
28
|
+
val weight = ReactTypefaceUtils.parseFontWeight(fontWeight)
|
|
29
|
+
val style = ReactTypefaceUtils.parseFontStyle(fontStyle)
|
|
30
|
+
|
|
31
|
+
if (fontFamily == null && weight == ReactConstants.UNSET && style == ReactConstants.UNSET) {
|
|
32
|
+
return base
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ReactFontManager.TypefaceStyle turns an unset weight into 400 and an unset style into
|
|
36
|
+
// "not italic" rather than deriving them from the base. This would drop default styling
|
|
37
|
+
// from base typeface. Resolve both up front so it never receives UNSET style or weight.
|
|
38
|
+
return ReactTypefaceUtils.applyStyles(
|
|
39
|
+
base,
|
|
40
|
+
if (style != ReactConstants.UNSET) style else base.resolveStyle(),
|
|
41
|
+
if (weight != ReactConstants.UNSET) weight else base.resolveWeight(),
|
|
42
|
+
fontFamily,
|
|
43
|
+
assets,
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private fun <T> changeNotifying(onChanged: () -> Unit): ReadWriteProperty<Any?, T?> =
|
|
49
|
+
Delegates.observable(null) { _, old, new -> if (old != new) onChanged() }
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Numeric weight of this typeface. [Typeface.getWeight] requires API 28; below it only bold
|
|
53
|
+
* can be told apart from regular.
|
|
54
|
+
*/
|
|
55
|
+
private fun Typeface.resolveWeight(): Int =
|
|
56
|
+
when {
|
|
57
|
+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> weight
|
|
58
|
+
isBold -> TypefaceStyle.BOLD
|
|
59
|
+
else -> TypefaceStyle.NORMAL
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private fun Typeface.resolveStyle(): Int = if (isItalic) Typeface.ITALIC else Typeface.NORMAL
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.swmansion.rnscreens.common.text
|
|
2
|
+
|
|
3
|
+
import android.graphics.Typeface
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Provides text styling for some given part of the interface. Interface is React-agnostic. A `null`
|
|
7
|
+
* value means "keep the default".
|
|
8
|
+
*/
|
|
9
|
+
internal interface TextAppearance {
|
|
10
|
+
val color: Int?
|
|
11
|
+
|
|
12
|
+
/** Font size in SP. */
|
|
13
|
+
val fontSize: Float?
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Returns the modified typeface based on [base] typeface. Properties that are not overridden
|
|
17
|
+
* are inherited from [base], which is returned unchanged when there are no overrides at all.
|
|
18
|
+
*/
|
|
19
|
+
fun resolveTypeface(base: Typeface): Typeface
|
|
20
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
package com.swmansion.rnscreens.common.text
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Typeface
|
|
5
|
+
import androidx.annotation.AttrRes
|
|
6
|
+
import com.swmansion.rnscreens.utils.resolveColorAttr
|
|
7
|
+
import com.swmansion.rnscreens.utils.resolveStyleResAttr
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Default text styling of a single title/subtitle slot, resolved from the M3 type-scale
|
|
11
|
+
* style behind [textAppearanceAttr] and the color behind [textColorAttr].
|
|
12
|
+
*
|
|
13
|
+
* Resolved from the style rather than read back from the widget: Material resolves a slot's
|
|
14
|
+
* default typeface asynchronously, so until that lands the widget reports [Typeface.DEFAULT].
|
|
15
|
+
*/
|
|
16
|
+
internal class TextAppearanceDefaults(
|
|
17
|
+
val color: Int,
|
|
18
|
+
val textSizePx: Float,
|
|
19
|
+
val typeface: Typeface,
|
|
20
|
+
) {
|
|
21
|
+
companion object {
|
|
22
|
+
fun resolve(
|
|
23
|
+
context: Context,
|
|
24
|
+
@AttrRes textAppearanceAttr: Int,
|
|
25
|
+
@AttrRes textColorAttr: Int,
|
|
26
|
+
): TextAppearanceDefaults {
|
|
27
|
+
val appearanceRes = resolveStyleResAttr(context, textAppearanceAttr)
|
|
28
|
+
val attrs = context.obtainStyledAttributes(appearanceRes, APPEARANCE_ATTRS)
|
|
29
|
+
try {
|
|
30
|
+
val textSizePx = attrs.getDimension(IDX_TEXT_SIZE, 0f)
|
|
31
|
+
require(textSizePx > 0f) { "[RNScreens] Text appearance defines no text size." }
|
|
32
|
+
|
|
33
|
+
// android:fontFamily is either a font resource (@font/…, resolvable only
|
|
34
|
+
// asynchronously) or a family name. The M3 type scale always declares a family
|
|
35
|
+
// name (@string/m3_ref_typeface_* — "sans-serif" / "sans-serif-medium"),
|
|
36
|
+
// so we can unconditionally take the synchronous path (Material's own fallback and
|
|
37
|
+
// AppCompatTextHelper do the same).
|
|
38
|
+
val textStyle = attrs.getInt(IDX_TEXT_STYLE, Typeface.NORMAL)
|
|
39
|
+
val typeface =
|
|
40
|
+
attrs.getString(IDX_FONT_FAMILY)?.let { Typeface.create(it, textStyle) }
|
|
41
|
+
?: Typeface.defaultFromStyle(textStyle)
|
|
42
|
+
|
|
43
|
+
return TextAppearanceDefaults(
|
|
44
|
+
resolveColorAttr(context, textColorAttr),
|
|
45
|
+
textSizePx,
|
|
46
|
+
typeface,
|
|
47
|
+
)
|
|
48
|
+
} finally {
|
|
49
|
+
attrs.recycle()
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Framework attr ids are compile-time constants; the array must stay sorted
|
|
54
|
+
// ascending (obtainStyledAttributes requirement).
|
|
55
|
+
private val APPEARANCE_ATTRS =
|
|
56
|
+
intArrayOf(
|
|
57
|
+
android.R.attr.textSize,
|
|
58
|
+
android.R.attr.textStyle,
|
|
59
|
+
android.R.attr.fontFamily,
|
|
60
|
+
)
|
|
61
|
+
private const val IDX_TEXT_SIZE = 0
|
|
62
|
+
private const val IDX_TEXT_STYLE = 1
|
|
63
|
+
private const val IDX_FONT_FAMILY = 2
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
package com.swmansion.rnscreens.helpers
|
|
2
2
|
|
|
3
|
-
import android.content.Context
|
|
4
3
|
import android.graphics.drawable.Drawable
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -21,27 +20,28 @@ internal sealed interface IconResolution {
|
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
22
|
* Stateful, latest-wins icon resolver for a single declaratively-driven icon slot — a `toolbarMenu`
|
|
24
|
-
* prop menu item, or the back button — that is re-evaluated on every
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* prop menu item, or the back button — that is re-evaluated on every source change. It deduplicates
|
|
24
|
+
* unchanged sources ([IconResolution.Unchanged]) to avoid needless reloads/flicker, and drops stale
|
|
25
|
+
* async results so a slow load cannot clobber a newer source.
|
|
26
|
+
*
|
|
27
|
+
* [load] must invoke its completion callback exactly once — synchronously or asynchronously,
|
|
28
|
+
* always on the main thread — with the loaded drawable, or `null` when the source resolves to
|
|
29
|
+
* no icon or fails to load (see e.g. [resolveImage]).
|
|
27
30
|
*/
|
|
28
|
-
internal class PropIconResolver
|
|
31
|
+
internal class PropIconResolver(
|
|
32
|
+
private val load: (drawableIconResourceName: String?, imageIconUri: String?, onComplete: (Drawable?) -> Unit) -> Unit,
|
|
33
|
+
) {
|
|
29
34
|
private var lastDrawableName: String? = null
|
|
30
35
|
private var lastImageUri: String? = null
|
|
31
36
|
private var lastEmittedDrawableName: String? = null
|
|
32
37
|
private var lastEmittedImageUri: String? = null
|
|
33
38
|
|
|
34
39
|
/**
|
|
35
|
-
* Resolves an icon from a drawable resource name or an image uri.
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* and asynchronously for image uris. For image uris, the callback is only invoked if the
|
|
39
|
-
* resolved uri is still the latest requested source (stale requests are dropped). On a failed
|
|
40
|
-
* image load the latest request still emits [IconResolution.Resolved] with a `null` drawable, so
|
|
41
|
-
* the icon is cleared rather than left stale.
|
|
40
|
+
* Resolves an icon from a drawable resource name or an image uri. The result is delivered
|
|
41
|
+
* to [onResult] only if the requested source is still the latest one (stale async results
|
|
42
|
+
* are dropped).
|
|
42
43
|
*/
|
|
43
44
|
fun resolve(
|
|
44
|
-
context: Context,
|
|
45
45
|
drawableIconResourceName: String?,
|
|
46
46
|
imageIconUri: String?,
|
|
47
47
|
onResult: (IconResolution) -> Unit,
|
|
@@ -56,16 +56,10 @@ internal class PropIconResolver {
|
|
|
56
56
|
}
|
|
57
57
|
lastEmittedDrawableName = drawableIconResourceName
|
|
58
58
|
lastEmittedImageUri = imageIconUri
|
|
59
|
-
|
|
60
|
-
drawableIconResourceName
|
|
61
|
-
onResult(IconResolution.Resolved(
|
|
62
|
-
|
|
63
|
-
loadImage(context, imageIconUri) { drawable ->
|
|
64
|
-
if (imageIconUri == lastImageUri && lastDrawableName == null) {
|
|
65
|
-
onResult(IconResolution.Resolved(drawable))
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
else -> onResult(IconResolution.Resolved(null))
|
|
59
|
+
load(drawableIconResourceName, imageIconUri) { drawable ->
|
|
60
|
+
if (drawableIconResourceName == lastDrawableName && imageIconUri == lastImageUri) {
|
|
61
|
+
onResult(IconResolution.Resolved(drawable))
|
|
62
|
+
}
|
|
69
63
|
}
|
|
70
64
|
}
|
|
71
65
|
}
|
|
@@ -495,8 +495,10 @@ class Screen(
|
|
|
495
495
|
// It has a custom `getChildDrawingOrder` method which returns
|
|
496
496
|
// wrong index if we called `startViewTransition` on the views on new arch.
|
|
497
497
|
// We add a simple View to bump the number of children to make it work.
|
|
498
|
+
// Appended, not inserted at `i`: a filler before the circle inflates the
|
|
499
|
+
// index `onMeasure` caches for it, which then outlives the child it points at.
|
|
498
500
|
// TODO: find a better way to handle this scenario
|
|
499
|
-
it.addView(View(context)
|
|
501
|
+
it.addView(View(context))
|
|
500
502
|
} else {
|
|
501
503
|
child?.let { view -> it.startViewTransition(view) }
|
|
502
504
|
}
|
|
@@ -282,6 +282,8 @@ class ScreenStack(
|
|
|
282
282
|
screenWrappers
|
|
283
283
|
.asSequence()
|
|
284
284
|
.dropWhile { it !== visibleBottom } // ignore all screens beneath the visible bottom
|
|
285
|
+
// dismissed screens are already removed above & preloaded ones must stay detached
|
|
286
|
+
.filter { !dismissedWrappers.contains(it) && it.screen.activityState !== Screen.ActivityState.INACTIVE }
|
|
285
287
|
.forEach { wrapper ->
|
|
286
288
|
// TODO: It should be enough to dispatch this on commit action once.
|
|
287
289
|
transaction.add(id, wrapper.fragment).runOnCommit {
|
|
@@ -69,6 +69,9 @@ internal class FormSheetBehaviorController(
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
+
* Expected to be called from the measure pass, before the sheet is measured (see
|
|
73
|
+
* `FormSheetAvailableHeightProvider`), so the metrics below are consumed by the ongoing traversal.
|
|
74
|
+
*
|
|
72
75
|
* @param detents - parsed detents configuration.
|
|
73
76
|
* @param sheetAvailableSpace - the full window height that detent fractions are measured against.
|
|
74
77
|
* Using the full height lets a BottomSheet with large detent configured to slide
|
|
@@ -77,7 +80,11 @@ internal class FormSheetBehaviorController(
|
|
|
77
80
|
* Used exclusively when the sheet is in `fitToContents` mode.
|
|
78
81
|
* @param nativeContainerPaddingBottom - the bottom system inset. In `fitToContents` mode, this is added to the
|
|
79
82
|
* BottomSheet's height to extend its background behind the system bars, while the inner content remains within
|
|
80
|
-
* the safe area.
|
|
83
|
+
* the safe area. For fractional detents it is subtracted from the collapsed peek height, which Material resolves
|
|
84
|
+
* above the inset, so the lowest detent lands at its fraction of [sheetAvailableSpace] like the other ones.
|
|
85
|
+
* @param keyboardLift - the part of the keyboard inset above [nativeContainerPaddingBottom]. Every resting position
|
|
86
|
+
* is extended by it so the sheet is pushed above the keyboard as far as [sheetAvailableSpace] allows,
|
|
87
|
+
* see [FormSheetDetents].
|
|
81
88
|
* @param initialDetentIndex - the index of the detent the sheet should snap to while opening.
|
|
82
89
|
* @param applyInitialDetent - whether the sheet should forcefully snap to the initial detent state.
|
|
83
90
|
* This should typically be `true` only when the sheet transitions from closed to open.
|
|
@@ -87,6 +94,7 @@ internal class FormSheetBehaviorController(
|
|
|
87
94
|
sheetAvailableSpace: Int,
|
|
88
95
|
contentHeightForFitToContents: Int = 0,
|
|
89
96
|
nativeContainerPaddingBottom: Int = 0,
|
|
97
|
+
keyboardLift: Int = 0,
|
|
90
98
|
initialDetentIndex: Int = 0,
|
|
91
99
|
applyInitialDetent: Boolean = false,
|
|
92
100
|
) {
|
|
@@ -97,22 +105,39 @@ internal class FormSheetBehaviorController(
|
|
|
97
105
|
}
|
|
98
106
|
|
|
99
107
|
if (detents.isFitToContents) {
|
|
100
|
-
configureFitToContents(
|
|
108
|
+
configureFitToContents(
|
|
109
|
+
detents,
|
|
110
|
+
sheetAvailableSpace,
|
|
111
|
+
contentHeightForFitToContents,
|
|
112
|
+
nativeContainerPaddingBottom,
|
|
113
|
+
keyboardLift,
|
|
114
|
+
)
|
|
101
115
|
} else {
|
|
102
116
|
when (detents.count) {
|
|
103
|
-
1 -> configureSingleDetent(detents, sheetAvailableSpace)
|
|
104
|
-
2 ->
|
|
105
|
-
|
|
117
|
+
1 -> configureSingleDetent(detents, sheetAvailableSpace, keyboardLift)
|
|
118
|
+
2 ->
|
|
119
|
+
configureTwoDetents(
|
|
120
|
+
detents,
|
|
121
|
+
sheetAvailableSpace,
|
|
122
|
+
nativeContainerPaddingBottom,
|
|
123
|
+
keyboardLift,
|
|
124
|
+
initialDetentIndex,
|
|
125
|
+
applyInitialDetent,
|
|
126
|
+
)
|
|
127
|
+
3 ->
|
|
128
|
+
configureThreeDetents(
|
|
129
|
+
detents,
|
|
130
|
+
sheetAvailableSpace,
|
|
131
|
+
nativeContainerPaddingBottom,
|
|
132
|
+
keyboardLift,
|
|
133
|
+
initialDetentIndex,
|
|
134
|
+
applyInitialDetent,
|
|
135
|
+
)
|
|
106
136
|
else -> throw IllegalStateException(
|
|
107
137
|
"[RNScreens] Unsupported detent count ${detents.count}.",
|
|
108
138
|
)
|
|
109
139
|
}
|
|
110
140
|
}
|
|
111
|
-
|
|
112
|
-
// Metrics were mutated on an already-measured sheet; force a fresh layout
|
|
113
|
-
// pass so the behavior re-settles to the new detent instead of keeping its
|
|
114
|
-
// stale height.
|
|
115
|
-
sheetView.requestLayout()
|
|
116
141
|
}
|
|
117
142
|
|
|
118
143
|
private fun configureFitToContents(
|
|
@@ -120,33 +145,37 @@ internal class FormSheetBehaviorController(
|
|
|
120
145
|
sheetAvailableSpace: Int,
|
|
121
146
|
contentHeight: Int,
|
|
122
147
|
bottomInset: Int,
|
|
148
|
+
keyboardLift: Int,
|
|
123
149
|
) = behavior.apply {
|
|
124
150
|
skipCollapsed = true
|
|
125
151
|
isFitToContents = true
|
|
126
|
-
maxHeight = detents.maxAllowedHeightForFitToContents(sheetAvailableSpace, contentHeight, bottomInset)
|
|
152
|
+
maxHeight = detents.maxAllowedHeightForFitToContents(sheetAvailableSpace, contentHeight, bottomInset, keyboardLift)
|
|
127
153
|
state = BottomSheetBehavior.STATE_EXPANDED
|
|
128
154
|
}
|
|
129
155
|
|
|
130
156
|
private fun configureSingleDetent(
|
|
131
157
|
detents: FormSheetDetents,
|
|
132
158
|
sheetAvailableSpace: Int,
|
|
159
|
+
keyboardLift: Int,
|
|
133
160
|
) = behavior.apply {
|
|
134
161
|
skipCollapsed = true
|
|
135
162
|
isFitToContents = true
|
|
136
|
-
maxHeight = detents.maxAllowedHeight(sheetAvailableSpace)
|
|
163
|
+
maxHeight = detents.maxAllowedHeight(sheetAvailableSpace, keyboardLift)
|
|
137
164
|
state = BottomSheetBehavior.STATE_EXPANDED
|
|
138
165
|
}
|
|
139
166
|
|
|
140
167
|
private fun configureTwoDetents(
|
|
141
168
|
detents: FormSheetDetents,
|
|
142
169
|
sheetAvailableSpace: Int,
|
|
170
|
+
bottomInset: Int,
|
|
171
|
+
keyboardLift: Int,
|
|
143
172
|
initialDetentIndex: Int,
|
|
144
173
|
applyInitialDetent: Boolean,
|
|
145
174
|
) = behavior.apply {
|
|
146
175
|
skipCollapsed = false
|
|
147
176
|
isFitToContents = true
|
|
148
|
-
peekHeight = detents.
|
|
149
|
-
maxHeight = detents.maxAllowedHeight(sheetAvailableSpace)
|
|
177
|
+
peekHeight = detents.peekHeight(sheetAvailableSpace, bottomInset, keyboardLift)
|
|
178
|
+
maxHeight = detents.maxAllowedHeight(sheetAvailableSpace, keyboardLift)
|
|
150
179
|
if (applyInitialDetent) {
|
|
151
180
|
state = resolveStateFromIndex(initialDetentIndex, detents.count)
|
|
152
181
|
}
|
|
@@ -155,15 +184,17 @@ internal class FormSheetBehaviorController(
|
|
|
155
184
|
private fun configureThreeDetents(
|
|
156
185
|
detents: FormSheetDetents,
|
|
157
186
|
sheetAvailableSpace: Int,
|
|
187
|
+
bottomInset: Int,
|
|
188
|
+
keyboardLift: Int,
|
|
158
189
|
initialDetentIndex: Int,
|
|
159
190
|
applyInitialDetent: Boolean,
|
|
160
191
|
) = behavior.apply {
|
|
161
192
|
skipCollapsed = false
|
|
162
193
|
isFitToContents = false
|
|
163
|
-
peekHeight = detents.
|
|
164
|
-
halfExpandedRatio = detents.halfExpandedRatio()
|
|
165
|
-
expandedOffset = detents.expandedOffsetFromTop(sheetAvailableSpace)
|
|
166
|
-
maxHeight = detents.maxAllowedHeight(sheetAvailableSpace)
|
|
194
|
+
peekHeight = detents.peekHeight(sheetAvailableSpace, bottomInset, keyboardLift)
|
|
195
|
+
halfExpandedRatio = detents.halfExpandedRatio(sheetAvailableSpace, keyboardLift)
|
|
196
|
+
expandedOffset = detents.expandedOffsetFromTop(sheetAvailableSpace, keyboardLift = keyboardLift)
|
|
197
|
+
maxHeight = detents.maxAllowedHeight(sheetAvailableSpace, keyboardLift)
|
|
167
198
|
if (applyInitialDetent) {
|
|
168
199
|
state = resolveStateFromIndex(initialDetentIndex, detents.count)
|
|
169
200
|
}
|